-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add frontend tests with playwright (#256)
* Add frontend tests with playwright The tests are written in python Add a Pipeline for github. * fix tests * fix pipeline * fix pipeline * Remove checked in vscode folder * refactor: autofix issues in 1 file Resolved issues in ui/tests/test_ui.py with DeepSource Autofix * Configure more tests location for python code * Revert "refactor: autofix issues in 1 file" This reverts commit f9970b2. assert in test code is OK in python, so revert this. * Simplify assertion --------- Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> Co-authored-by: Felix Schumacher <felix@internetallee.de> Co-authored-by: Felix Schumacher <felix.schumacher@internetallee.de>
- Loading branch information
1 parent
4f4cd04
commit a9b128d
Showing
9 changed files
with
428 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ version = 1 | |
|
||
test_patterns = [ | ||
"api/tests/**", | ||
"ui/tests/**", | ||
"test_*.py" | ||
] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
name: Run Python Playwright Tests | ||
on: | ||
pull_request: | ||
types: | ||
- opened | ||
- reopened | ||
- synchronize | ||
push: | ||
branches: | ||
- main | ||
- master | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.12' | ||
|
||
- name: Install dependencies | ||
run: | | ||
cd api | ||
pip install . | ||
- name: Install Playwright Browsers | ||
run: | | ||
cd api | ||
playwright install | ||
- name: Start Vue.js Development Server | ||
run: | | ||
cd ui | ||
npm install | ||
nohup npm run dev & | ||
sleep 5 | ||
- name: Run Playwright Tests | ||
run: | | ||
cd ui | ||
pytest tests/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VITE_MOCK_NAMESPACES=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import os | ||
from playwright.sync_api import sync_playwright, Page | ||
|
||
|
||
def test_ui_start(): | ||
with sync_playwright() as ctx: | ||
browser = ctx.chromium.launch(headless=True) | ||
page = browser.new_page() | ||
page.goto("http://localhost:8080") | ||
page.wait_for_load_state("load") | ||
assert page.title() == "Kubeseal Webgui" | ||
browser.close() | ||
|
||
|
||
def test_secret_form_with_value(): | ||
with sync_playwright() as ctx: | ||
browser = ctx.chromium.launch(headless=True) | ||
page = browser.new_page() | ||
page.goto("http://localhost:8080") | ||
page.wait_for_load_state("load") | ||
|
||
disabled_encrypt_button(page) | ||
namespace_select(page) | ||
secret_name(page) | ||
scope_strict(page) | ||
add_secret_key_value(page) | ||
click_encrypt_button(page) | ||
|
||
browser.close() | ||
|
||
|
||
def test_secret_form_with_file(): | ||
with sync_playwright() as ctx: | ||
browser = ctx.chromium.launch(headless=True) | ||
page = browser.new_page() | ||
page.goto("http://localhost:8080") | ||
page.wait_for_load_state("load") | ||
|
||
disabled_encrypt_button(page) | ||
namespace_select(page) | ||
secret_name(page) | ||
scope_strict(page) | ||
add_secret_key_file(page) | ||
click_encrypt_button(page) | ||
|
||
browser.close() | ||
|
||
|
||
def test_secret_form_with_invalid_file(): | ||
with sync_playwright() as ctx: | ||
browser = ctx.chromium.launch(headless=True) | ||
page = browser.new_page() | ||
page.goto("http://localhost:8080") | ||
page.wait_for_load_state("load") | ||
|
||
file_input = page.locator('input[type="file"]#input-16') | ||
# Try to upload a non-valid file | ||
invalid_file_path = os.path.join(os.getcwd(), "large_test_file.txt") | ||
with open(invalid_file_path, "w") as f: | ||
f.write( | ||
"X" * (10 * 1024 * 1024) | ||
) # Create a 10MB file (assuming it's too large) | ||
file_input.set_input_files(invalid_file_path) | ||
|
||
# Check for an error message (adjust the selector as needed) | ||
error_message = page.locator( | ||
"text='File size should be less than 1 MB!'" | ||
) # Replace with actual error message | ||
assert ( | ||
error_message.is_visible() | ||
), "Error message should be visible for invalid file" | ||
if os.path.exists(invalid_file_path): | ||
os.remove(invalid_file_path) | ||
browser.close() | ||
|
||
|
||
def namespace_select(page: Page): | ||
input_selector = "input#input-4" | ||
page.wait_for_selector(input_selector, timeout=10000) | ||
page.click(input_selector) | ||
suggestions = page.query_selector_all(".v-list-item-title") | ||
assert len(suggestions) > 0, "No suggestions found." | ||
first_suggestion_text = suggestions[0].inner_text() | ||
suggestions[0].click() | ||
selected_value = page.input_value(input_selector) | ||
assert ( | ||
selected_value == first_suggestion_text | ||
), f"Expected '{first_suggestion_text}', but got '{selected_value}'" | ||
|
||
|
||
def secret_name(page: Page): | ||
input_selector = "#input-secret-name" | ||
page.wait_for_selector(input_selector) | ||
input_text = "valid-secret-name" | ||
page.fill(input_selector, input_text) | ||
assert ( | ||
page.input_value(input_selector) == input_text | ||
), f"Expected {input_text}, but got {page.input_value(input_selector)}" | ||
|
||
|
||
def scope_strict(page: Page): | ||
select_selector = "div.v-select" | ||
page.wait_for_selector(select_selector) | ||
page.click(select_selector) | ||
item_selector = "div.v-list-item" | ||
page.wait_for_selector(item_selector) | ||
items = page.query_selector_all(item_selector) | ||
assert len(items) > 0, "No items found in the dropdown." | ||
for item in items: | ||
title_element = item.query_selector("div.v-list-item-title") | ||
if title_element and title_element.inner_text().strip() == "strict": | ||
item.click() | ||
break | ||
|
||
|
||
def add_secret_key_value(page: Page): | ||
page.wait_for_selector("textarea#input-12") | ||
page.fill("textarea#input-12", "my-secret-key") | ||
assert page.locator("textarea#input-12").input_value() == "my-secret-key" | ||
page.wait_for_selector("textarea#input-14") | ||
page.fill("textarea#input-14", "my-secret-value") | ||
assert page.locator("textarea#input-14").input_value() == "my-secret-value" | ||
file_input = page.locator('input[type="file"]#input-16') | ||
assert ( | ||
not file_input.is_enabled() | ||
), "File input should be disabled when value is filled" | ||
|
||
|
||
def add_secret_key_file(page: Page): | ||
page.wait_for_selector("textarea#input-12") | ||
page.fill("textarea#input-12", "my-secret-key") | ||
assert page.locator("textarea#input-12").input_value() == "my-secret-key" | ||
|
||
file_input = page.locator('input[type="file"]#input-16') | ||
assert file_input.is_visible() | ||
test_file_path = os.path.join(os.getcwd(), "test_file.txt") | ||
with open(test_file_path, "w") as f: | ||
f.write("This is a test file.") | ||
file_input.set_input_files(test_file_path) | ||
if os.path.exists(test_file_path): | ||
os.remove(test_file_path) | ||
|
||
|
||
def disabled_encrypt_button(page: Page): | ||
encrypt_button = page.locator('button:has-text("Encrypt")') | ||
encrypt_button.wait_for() | ||
assert encrypt_button.is_disabled() | ||
|
||
|
||
def click_encrypt_button(page: Page): | ||
# Mock the fetchEncodedSecrets function by overriding it in the browser context | ||
page.evaluate( | ||
""" | ||
const appElement = document.querySelector('#app'); | ||
const vueApp = appElement.__vue_app__; | ||
if (vueApp) { | ||
vueApp._instance.proxy.fetchEncodedSecrets = function() { | ||
window.fetchEncodedSecretsCalled = true; | ||
}; | ||
} | ||
""" | ||
) | ||
encrypt_button = page.locator('button:has-text("Encrypt")') | ||
encrypt_button.wait_for() | ||
assert encrypt_button.is_enabled() | ||
encrypt_button.click() | ||
is_called = page.evaluate("window.fetchEncodedSecretsCalled === true") | ||
assert is_called, "fetchEncodedSecrets function was not called!" |