From f161ab9125610d88fccbf651eca4db966150f696 Mon Sep 17 00:00:00 2001 From: ibizaman Date: Thu, 30 Jan 2025 21:40:10 +0100 Subject: [PATCH] add playwright test for nextcloud --- test/common.nix | 27 ++++++----- test/services/deluge.nix | 4 +- test/services/forgejo.nix | 6 +-- test/services/nextcloud.nix | 95 +++++++++++++++++++++++-------------- 4 files changed, 79 insertions(+), 53 deletions(-) diff --git a/test/common.nix b/test/common.nix index d168422..bbb4cca 100644 --- a/test/common.nix +++ b/test/common.nix @@ -91,6 +91,10 @@ let if response['auth_query'] != "rd=${proto_fqdn}/": raise Exception(f"auth query should be rd=${proto_fqdn}/ but is {response['auth_query']}") '') + + (let + script = extraScript args; + in + lib.optionalString (script != "") script) + (optionalString (hasAttr "test" nodes.client && hasAttr "login" nodes.client.test) '' with subtest("Login"): code, logs = client.execute("login_playwright firefox") @@ -99,10 +103,6 @@ let if code != 0: raise Exception("login_playwright did not succeed") '') - + (let - script = extraScript args; - in - lib.optionalString (script != "") script) ); backupScript = args: (accessScript args).override { @@ -153,15 +153,15 @@ in cfg = config.test.login; in { options.test.login = { - usernameFieldLabel = mkOption { + usernameFieldLabelRegex = mkOption { type = str; default = "username"; }; - passwordFieldLabel = mkOption { + passwordFieldLabelRegex = mkOption { type = str; default = "password"; }; - loginButtonName = mkOption { + loginButtonNameRegex = mkOption { type = str; default = "login"; }; @@ -234,6 +234,7 @@ in print(f"Testing for user {u['username']} and password {u['password']}") context = browser.new_context(ignore_https_errors=True) + context.set_default_navigation_timeout(2 * 60 * 1000) context.tracing.start(screenshots=True, snapshots=True, sources=True) try: page = context.new_page() @@ -241,14 +242,14 @@ in page.goto(testCfg['startUrl']) if u['username'] is not None: - print(f"Filling field {testCfg['usernameFieldLabel']} with {u['username']}") - page.get_by_label(testCfg['usernameFieldLabel']).fill(u['username']) + print(f"Filling field {testCfg['usernameFieldLabelRegex']} with {u['username']}") + page.get_by_label(re.compile(testCfg['usernameFieldLabelRegex'])).fill(u['username']) if u['password'] is not None: - print(f"Filling field {testCfg['passwordFieldLabel']} with {u['password']}") - page.get_by_label(testCfg['passwordFieldLabel']).fill(u['password']) + print(f"Filling field {testCfg['passwordFieldLabelRegex']} with {u['password']}") + page.get_by_label(re.compile(testCfg['passwordFieldLabelRegex'])).fill(u['password']) - print(f"Clicking button {testCfg['loginButtonName']}") - page.get_by_role("button", name=testCfg['loginButtonName']).click() + print(f"Clicking button {testCfg['loginButtonNameRegex']}") + page.get_by_role("button", name=re.compile(testCfg['loginButtonNameRegex'])).click() for line in u['nextPageExpect']: print(f"Running: {line}") diff --git a/test/services/deluge.nix b/test/services/deluge.nix index a10350f..1d57f07 100644 --- a/test/services/deluge.nix +++ b/test/services/deluge.nix @@ -108,8 +108,8 @@ let }; test.login = { - passwordFieldLabel = "Password"; - loginButtonName = "Login"; + passwordFieldLabelRegex = "Password"; + loginButtonNameRegex = "Login"; testLoginWith = [ { password = "deluge"; nextPageExpect = [ "expect(page.get_by_role('button', name='Login')).not_to_be_visible()" diff --git a/test/services/forgejo.nix b/test/services/forgejo.nix index 4467e10..eb5e85c 100644 --- a/test/services/forgejo.nix +++ b/test/services/forgejo.nix @@ -80,9 +80,9 @@ let test.login = { startUrl = "http://${config.test.fqdn}/user/login"; - usernameFieldLabel = "Username or email address"; - passwordFieldLabel = "Password"; - loginButtonName = "Sign In"; + usernameFieldLabelRegex = "Username or email address"; + passwordFieldLabelRegex = "Password"; + loginButtonNameRegex = "Sign In"; testLoginWith = [ { username = "theadmin"; password = adminPassword + "oops"; nextPageExpect = [ "expect(page.get_by_text('Username or password is incorrect.')).to_be_visible()" diff --git a/test/services/nextcloud.nix b/test/services/nextcloud.nix index 30beb6d..9025245 100644 --- a/test/services/nextcloud.nix +++ b/test/services/nextcloud.nix @@ -21,20 +21,9 @@ let def find_in_logs(unit, text): return server.systemctl("status {}".format(unit))[1].find(text) != -1 - with subtest("cron job succeeds"): - # This calls blocks until the service is done. - server.systemctl("start nextcloud-cron.service") - - # If the service failed, then we're not happy. - status = "active" - while status == "active": - status = server.get_unit_info("nextcloud-cron")["ActiveState"] - time.sleep(5) - if status != "inactive": - raise Exception("Cron job did not finish correctly") - - if not find_in_logs("nextcloud-cron", "nextcloud-cron.service: Deactivated successfully."): - raise Exception("Nextcloud cron job did not finish successfully.") + with subtest("cron job starts"): + # This call does not block until the service is done. + server.succeed("systemctl start nextcloud-cron.service&") with subtest("fails with incorrect authentication"): client.fail( @@ -106,10 +95,27 @@ let ) if content != "hello\n": raise Exception("Got incorrect content for file, expected 'hello\n' but got:\n{}".format(content)) + + with subtest("cron job succeeds"): + # If the service failed, then we're not happy. + status = "active" + while status == "active": + status = server.get_unit_info("nextcloud-cron")["ActiveState"] + time.sleep(5) + if status != "inactive": + raise Exception("Cron job did not finish correctly") + + if not find_in_logs("nextcloud-cron", "nextcloud-cron.service: Deactivated successfully."): + raise Exception("Nextcloud cron job did not finish successfully.") ''; }; basic = { config, ... }: { + imports = [ + testLib.baseModule + ../../modules/services/nextcloud-server.nix + ]; + test = { subdomain = "n"; }; @@ -136,6 +142,36 @@ let }; }; + clientLogin = { config, ... }: { + imports = [ + testLib.baseModule + testLib.clientLoginModule + ]; + virtualisation.memorySize = 4096; + + test = { + subdomain = "n"; + }; + + test.login = { + startUrl = "http://${config.test.fqdn}"; + usernameFieldLabelRegex = "[Uu]sername"; + passwordFieldLabelRegex = "^ *[Pp]assword"; + loginButtonNameRegex = "[Ll]og [Ii]n"; + testLoginWith = [ + { username = adminUser; password = adminPass; nextPageExpect = [ + "expect(page.get_by_text('Wrong username or password')).not_to_be_visible()" + "expect(page.get_by_role('button', name=re.compile('[Ll]og [Ii]n'))).not_to_be_visible()" + "expect(page).to_have_title(re.compile('Dashboard'))" + ]; } + # Failure is after so we're not throttled too much. + { username = adminUser; password = adminPass + "oops"; nextPageExpect = [ + "expect(page.get_by_text('Wrong username or password')).to_be_visible()" + ]; } + ]; + }; + }; + https = { config, ...}: { shb.nextcloud = { ssl = config.shb.certs.certs.selfsigned.n; @@ -234,10 +270,13 @@ in basic = pkgs.testers.runNixOSTest { name = "nextcloud_basic"; + nodes.client = { + imports = [ + clientLogin + ]; + }; nodes.server = { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix basic ]; }; @@ -252,8 +291,6 @@ in nodes.server = { config, ... }: { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix basic (testLib.backup config.shb.nextcloud.backup) ]; @@ -269,10 +306,8 @@ in nodes.server = { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix - testLib.certs basic + testLib.certs https ]; }; @@ -288,10 +323,8 @@ in nodes.server = { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix - testLib.certs basic + testLib.certs https previewgenerator ]; @@ -307,10 +340,8 @@ in nodes.server = { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix - testLib.certs basic + testLib.certs https externalstorage ]; @@ -326,10 +357,8 @@ in nodes.server = { config, ... }: { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix - testLib.certs basic + testLib.certs https testLib.ldap ldap @@ -346,10 +375,8 @@ in nodes.server = { config, ... }: { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix - testLib.certs basic + testLib.certs https testLib.ldap ldap @@ -368,8 +395,6 @@ in nodes.server = { config, ... }: { imports = [ - testLib.baseModule - ../../modules/services/nextcloud-server.nix basic prometheus ];