[WIP] Add new automated test framework (#1)

Co-authored-by: Daniel <d.brummerloh@gmail.com>
Co-committed-by: Daniel <d.brummerloh@gmail.com>
This commit is contained in:
Daniel 2023-11-22 21:40:13 +01:00 committed by dan
parent 859bd57006
commit 97ed87c79f
31 changed files with 769 additions and 6 deletions

11
previous-work/README.md Normal file
View file

@ -0,0 +1,11 @@
# Installation
pip install pytest-playwright
playwright install
# Run Tests:
pytest -k nextcloud
playwright show-trace trace.zip

View file

@ -0,0 +1,23 @@
from conftest import check_for, testuser, RECORDS
# playwright = sync_playwright().start()
# browser = playwright.chromium.launch(headless=False)
""" Test Changing Username in Authentik """
def test_authentik_change_username(user_session):
context, page = user_session
page.get_by_role("banner").get_by_role("link").nth(1).click()
page.get_by_placeholder(testuser["username"]).click()
page.get_by_placeholder(testuser["username"]).fill("renameduser")
page.get_by_role("button", name="Speichern").click()
check_for(page.get_by_role("heading", name="Not allowed to change username."))
context.tracing.stop(path=f"{RECORDS}/change_username.zip")
#""" Click all Apps """
#def test_dashboard(user_session):
# context, page = user_session
# for link in page.locator("ak-library-app").get_by_role("link").all():
# link.click()
# context.tracing.stop(path=f"{RECORDS}/test_dashboard.zip")
# context.close()
#

15
previous-work/config.yaml Normal file
View file

@ -0,0 +1,15 @@
timeout: 1200000
domain: "https://dev.local-it.cloud"
admin: "akadmin"
admin_pw: "grab-football-charting-cherisher-obtrusive-announcer"
locale: de
default_quota: 10
welcome_message: "Willkommen bei Local-IT"
apps:
- nextcloud
- onlyoffice
- wordpress
- wekan
- vikunja
nc_apps:
- Calendar

149
previous-work/conftest.py Normal file
View file

@ -0,0 +1,149 @@
import pytest
import yaml
from pathlib import Path
from playwright.sync_api import sync_playwright, expect, Browser, Locator
# playwright = sync_playwright().start()
# browser = playwright.chromium.launch(headless=False)
with open("config.yaml") as file:
CONFIG = yaml.safe_load(file)
testuser = {'username': 'testuser',
'name': "Test User",
'password': 'test123',
'email': 'test@example.com'}
RECORDS = Path("records")
RECORDS.mkdir(exist_ok=True)
STATES = Path("states")
STATES.mkdir(exist_ok=True)
TIMEOUT = CONFIG['timeout']
def check_for(locator: Locator):
expect(locator).to_be_visible(timeout=TIMEOUT)
def setup_context(browser, state_file=None):
if state_file:
context = browser.new_context(storage_state=state_file)
else:
context = browser.new_context()
context.tracing.start(screenshots=True, snapshots=True, sources=True)
context.set_default_timeout(TIMEOUT)
return context
""" Test Authentik Login and DE Locale """
@pytest.fixture(scope="session", autouse=True)
def admin_login(browser: Browser):
context = setup_context(browser)
page = context.new_page()
page.goto(CONFIG['domain'])
welcome_message = CONFIG.get('welcome_message')
if welcome_message:
check_for(page.get_by_text(welcome_message))
if CONFIG['locale'] == 'de':
check_for(page.get_by_text("Benutzername oder Passwort vergessen?"))
check_for(page.get_by_text("E-Mail or Anmeldename"))
check_for(page.get_by_text("Passwort", exact=True))
page.locator("input[name=\"uidField\"]").fill(CONFIG['admin'])
page.locator("ak-stage-identification input[name=\"password\"]").fill(CONFIG['admin_pw'])
page.get_by_role("button", name="Log In").click()
check_for(page.locator("ak-library"))
if CONFIG['locale'] == 'de':
check_for(page.get_by_text("Meine Anwendungen"))
context.storage_state(path=f"{STATES}/admin_state.json")
page.close()
context.tracing.stop(path=f"{RECORDS}/admin_login.zip")
context.close()
""" Create User """
@pytest.fixture(scope="session", autouse=True)
def init_create_user(browser: Browser, admin_login):
admin_context = setup_context(browser, f"{STATES}/admin_state.json")
admin_page = admin_context.new_page()
invitelink = create_invite_link(admin_page)
admin_context.tracing.stop(path=f"{RECORDS}/create_invite_link.zip")
admin_context.close()
user_context = setup_context(browser)
create_user(user_context, invitelink)
user_context.tracing.stop(path=f"{RECORDS}/create_user.zip")
user_context.close()
""" Delete User """
@pytest.fixture(scope="session", autouse=True)
def post_delete_user(browser: Browser):
yield
context = browser.new_context(storage_state=f"{STATES}/admin_state.json")
context.tracing.start(screenshots=True, snapshots=True, sources=True)
context.set_default_timeout(TIMEOUT)
page = context.new_page()
# delete_nextcloud_user(page)
delete_authentik_user(page)
context.tracing.stop(path=f"{RECORDS}/delete_user.zip")
""" Create Invite Link """
def create_invite_link(page):
page.goto(CONFIG['domain'])
page.get_by_role("link", name="Admin Interface").click()
page.get_by_text("Verzeichnis").click()
page.get_by_text("Benutzer").nth(2).click()
page.get_by_text("Einladungen").click()
page.get_by_role("button", name="Erstellen").first.click()
page.locator("input[name=\"name\"]").click()
linkname = "testlink9433"
page.locator("input[name=\"name\"]").fill(linkname)
page.get_by_placeholder("Wählen Sie ein Objekt aus.").click()
page.get_by_role("option", name="invitation-enrollment-flow invitation-enrollment-flow").click()
page.get_by_text("Erstellen", exact=True).first.click()
linklocator = page.get_by_role("rowgroup").filter(has=page.get_by_text(linkname))
linklocator.locator('.fa-angle-down').click()
invitelink = linklocator.get_by_role("textbox").get_attribute(name='value')
return invitelink
""" Create User from invitelink """
def create_user(context, invitelink):
page = context.new_page()
page.goto(invitelink)
page.get_by_placeholder("Benutzername").click()
page.get_by_placeholder("Benutzername").fill(testuser["username"])
page.locator("input[name=\"name\"]").click()
page.locator("input[name=\"name\"]").fill(testuser["name"])
page.locator("input[name=\"email\"]").click()
page.locator("input[name=\"email\"]").fill(testuser["email"])
page.get_by_placeholder("Passwort", exact=True).click()
page.get_by_placeholder("Passwort", exact=True).fill(testuser["password"])
page.get_by_placeholder("Passwort (wiederholen)").click()
page.get_by_placeholder("Passwort (wiederholen)").fill(testuser["password"])
page.get_by_role("button", name="Weiter").click()
check_for(page.locator("ak-library"))
context.storage_state(path=f"{STATES}/user_state.json")
""" Delete Authentik Account """
def delete_authentik_user(page):
page.goto(CONFIG['domain'])
page.get_by_role("link", name="Admin Interface").click()
page.get_by_text("Verzeichnis").click()
page.get_by_text("Benutzer").nth(2).click()
page.get_by_role("row").filter(has=page.get_by_text(testuser["username"])).get_by_role('checkbox').click()
page.get_by_role("button", name="Löschen").click()
page.get_by_role("dialog").get_by_role("button", name="Löschen").click()
check_for(page.get_by_text('1 Benutzer erfolgreich gelöscht'))
""" Reuse Authentik Admin Session """
@pytest.fixture
def admin_session(browser: Browser):
context = setup_context(browser, f"{STATES}/admin_state.json")
page = context.new_page()
page.goto(CONFIG['domain'])
yield context, page
context.close()
""" Reuse Authentik User Session """
@pytest.fixture
def user_session(browser: Browser):
context = setup_context(browser, f"{STATES}/user_state.json")
page = context.new_page()
page.goto(CONFIG['domain'])
yield context, page
context.close()

View file

@ -0,0 +1,90 @@
import pytest
from playwright.sync_api import Browser, expect
from conftest import CONFIG, RECORDS, check_for, testuser, setup_context, STATES
# playwright = sync_playwright().start()
# browser = playwright.chromium.launch(headless=False)
""" Delete Nextcloud Account """
@pytest.fixture(scope="session", autouse=True)
def delete_nextcloud_user(browser: Browser):
yield
context = setup_context(browser, f"{STATES}/admin_state.json")
page = context.new_page()
page.goto(CONFIG['domain'])
with page.expect_popup() as nextcloud_info:
page.get_by_role("link", name="Nextcloud").click()
nextcloud = nextcloud_info.value
nextcloud.get_by_role("link", name="Open settings menu").click()
nextcloud.get_by_role("link", name="Users").click()
nextcloud.locator("#app-content div").filter(has_text=testuser["username"]).get_by_role("button", name="Toggle user actions menu").click()
nextcloud.get_by_role("button", name="Delete user").click()
nextcloud.get_by_role("button", name=f"Delete authentik-{testuser['username']}'s account").click()
context.tracing.stop(path=f"{RECORDS}/nextcloud_delete_user.zip")
context.close()
""" Nextcloud Login """
@pytest.fixture(scope="session", autouse=True)
def nc_login(browser: Browser):
context = setup_context(browser, f"{STATES}/user_state.json")
page = context.new_page()
page.goto(CONFIG['domain'])
with page.expect_popup() as nextcloud_info:
link = page.get_by_role("link", name="Nextcloud")
CONFIG['nc_domain'] = link.get_attribute("href")
link.click()
nextcloud = nextcloud_info.value
check_for(nextcloud.get_by_role("link", name="Name"))
if nextcloud.query_selector('.close-icon'):
close_button = nextcloud.get_by_role("button", name="Close modal")
close_button.click()
expect(close_button).to_be_hidden()
nextcloud.wait_for_timeout(2000)
context.storage_state(path=f"{STATES}/nc_user_state.json")
context.tracing.stop(path=f"{RECORDS}/nextcloud_login_user.zip")
context.close()
""" Reuse Nextcloud User Session """
@pytest.fixture
def nc_session(browser: Browser):
context = setup_context(browser, f"{STATES}/nc_user_state.json")
page = context.new_page()
page.goto(CONFIG['nc_domain'])
if page.query_selector('.close-icon'):
page.get_by_role("button", name="Close modal").click()
yield context, page
context.close()
""" Test Nextcloud """
def test_nextcloud(nc_session):
context, page = nc_session
#if page.query_selector('.close-icon'):
# page.get_by_role("button", name="Close modal").click()
if CONFIG.get('default_quota'):
quota = int(page.get_by_role("listitem", name="Storage informations").get_by_role("link").inner_text().split()[3])
assert quota == CONFIG['default_quota']
for app in CONFIG['nc_apps']:
check_for(page.get_by_role("link", name=app))
context.tracing.stop(path=f"{RECORDS}/nextcloud.zip")
""" Test Onlyoffice in Nextcloud """
def test_onlyoffice(nc_session):
context, page = nc_session
#if page.query_selector('.close-icon'):
# page.get_by_role("button", name="Close modal").click()
page.get_by_role("link", name="New file/folder menu").click()
page.get_by_role("link", name="New document").click()
page.locator("#view9-input-file").fill("test.docx")
page.get_by_role("button", name="Submit").click()
outer_frame = page.frame_locator('#onlyofficeFrame')
check_for(outer_frame.locator('body'))
inner_frame = outer_frame.frame_locator('#app > iframe')
check_for(inner_frame.locator('body'))
onlyoffice = page.frame("frameEditor")
check_for(onlyoffice.locator('//*[@id="area_id"]'))
onlyoffice.locator("#btn-goback").click()
page.get_by_role("link", name="Not favorited test .docx Share Actions").get_by_role("link", name="Actions").click()
page.get_by_role("link", name="Delete file").click()
context.tracing.stop(path=f"{RECORDS}/onlyoffice.zip")

9
previous-work/pytest.ini Normal file
View file

@ -0,0 +1,9 @@
[pytest]
addopts=--headed -s --setup-show --browser=firefox --tracing=on --screenshot=on --output=results
# --setup-show
log_cli = 1
log_cli_level = INFO
log_file = ./TestResults/test_log.log
log_file_level = INFO

View file

@ -0,0 +1,12 @@
from conftest import check_for, RECORDS
""" Test Vikunja """
def test_vikunja(admin_session):
context, page = admin_session
with page.expect_popup() as info:
page.get_by_role("link", name="Vikunja").click()
vikunja = info.value
vikunja.get_by_text("Log in with").click()
check_for(vikunja.get_by_placeholder("Add a new task…"))
context.tracing.stop(path=f"{RECORDS}/vikunja.zip")

View file

@ -0,0 +1,13 @@
from conftest import check_for, RECORDS
""" Test Wekan """
def test_wekan(admin_session):
context, page = admin_session
with page.expect_popup() as info:
page.get_by_role("link", name="Wekan").click()
wekan = info.value
wekan.get_by_role("link", name="Member Settings").click()
check_for(wekan.get_by_role("link", name=" Admin Panel"))
context.tracing.stop(path=f"{RECORDS}/wekan.zip")

View file

@ -0,0 +1,14 @@
from conftest import CONFIG, check_for, RECORDS
""" Test Wordpress """
def test_wordpress(admin_session):
context, page = admin_session
with page.expect_popup() as info:
page.get_by_role("link", name="Wordpress").click()
wordpress = info.value
check_for(wordpress.locator("#wpcontent"))
if CONFIG['locale'] == 'de':
check_for(wordpress.get_by_role("heading", name="Willkommen bei WordPress!"))
context.tracing.stop(path=f"{RECORDS}/wordpress.zip")