Refactor playwright login helper

It now works for all test specs and does not require a password from the
environment.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
This commit is contained in:
Pablo Zmdl
2026-06-25 17:11:03 +02:00
parent 62ba204537
commit 22a5b65291
7 changed files with 31 additions and 49 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test';
import { DESEC_MOCK_URL, logInToContainersPage } from './desec-helpers.js';
import { DESEC_MOCK_URL, logInToContainersPage } from './helpers.js';
// Exercises reusing a slug the user already owns on an existing deSEC account. This is the
// case that previously failed: deSEC answers POST /domains/ with 403 "Domain limit exceeded"
+1 -1
View File
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test';
import { DESEC_MOCK_URL, logInToContainersPage } from './desec-helpers.js';
import { DESEC_MOCK_URL, logInToContainersPage } from './helpers.js';
// Exercises the deSEC "I already have a verified account" login path: supplying a valid
// password logs straight in and registers the domain in one step (no email-verification
-22
View File
@@ -1,22 +0,0 @@
// Shared helpers for the deSEC Playwright scenarios.
//
// The deSEC mock is wired up by seeding configuration.json (see seed-desec-mock-config.php),
// which makes AIO consider itself already installed: /setup no longer renders the
// initial-password page. The seed step therefore writes a known master password (AIO_TEST_PASSWORD)
// that we log in with directly here instead of scraping it from /setup.
export const DESEC_MOCK_URL = process.env.DESEC_MOCK_URL ?? 'http://localhost:8090';
const AIO_PASSWORD = process.env.AIO_TEST_PASSWORD;
export async function logInToContainersPage(page) {
if (!AIO_PASSWORD) {
throw new Error('AIO_TEST_PASSWORD must be set to the master password seeded into configuration.json');
}
await page.goto('./');
await page.locator('#master-password').click();
await page.locator('#master-password').fill(AIO_PASSWORD);
await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL('./containers');
return page;
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test';
import { DESEC_MOCK_URL, logInToContainersPage } from './desec-helpers.js';
import { DESEC_MOCK_URL, logInToContainersPage } from './helpers.js';
// Drives the real AIO interface through the full deSEC "register a free domain" flow
// against the local mock (php/tests/desec-mock.mjs). The mastercontainer's
+24
View File
@@ -0,0 +1,24 @@
// Shared helpers for the deSEC Playwright scenarios.
//
// The deSEC mock is wired up by seeding configuration.json (see seed-desec-mock-config.php),
// which makes AIO consider itself already installed: /setup no longer renders the
// initial-password page. The seed step therefore writes a known master password (AIO_TEST_PASSWORD)
// that we log in with directly here instead of scraping it from /setup.
export const DESEC_MOCK_URL = process.env.DESEC_MOCK_URL ?? 'http://localhost:8090';
export async function logInToContainersPage(setupPage) {
// Extract initial password
await setupPage.goto('./setup');
const password = await setupPage.locator('#initial-password').innerText()
const containersPagePromise = setupPage.waitForEvent('popup');
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
const containersPage = await containersPagePromise;
// Log in and wait for redirect
await containersPage.locator('#master-password').click();
await containersPage.locator('#master-password').fill(password);
await containersPage.getByRole('button', { name: 'Log in' }).click();
await containersPage.waitForURL('./containers');
return containersPage;
}
+2 -12
View File
@@ -1,21 +1,11 @@
import { test, expect } from '@playwright/test';
import { writeFileSync } from 'node:fs'
import { logInToContainersPage } from './helpers.js';
test('Initial setup', async ({ page: setupPage }) => {
test.setTimeout(10 * 60 * 1000)
// Extract initial password
await setupPage.goto('./setup');
const password = await setupPage.locator('#initial-password').innerText()
const containersPagePromise = setupPage.waitForEvent('popup');
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
const containersPage = await containersPagePromise;
// Log in and wait for redirect
await containersPage.locator('#master-password').click();
await containersPage.locator('#master-password').fill(password);
await containersPage.getByRole('button', { name: 'Log in' }).click();
await containersPage.waitForURL('./containers');
const containersPage = await logInToContainersPage(setupPage);
// Reject IP addresses
await containersPage.locator('#domain').click();
+2 -12
View File
@@ -1,5 +1,6 @@
import { test, expect } from '@playwright/test';
import { readFileSync } from 'node:fs';
import { logInToContainersPage } from './helpers.js';
test('Restore instance', async ({ page: setupPage }) => {
test.setTimeout(10 * 60 * 1000)
@@ -11,18 +12,7 @@ test('Restore instance', async ({ page: setupPage }) => {
borgBackupPassword,
} = JSON.parse(readFileSync('test_data.json'))
// Extract initial password
await setupPage.goto('./setup');
const password = await setupPage.locator('#initial-password').innerText()
const containersPagePromise = setupPage.waitForEvent('popup');
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
const containersPage = await containersPagePromise;
// Log in and wait for redirect
await containersPage.locator('#master-password').click();
await containersPage.locator('#master-password').fill(password);
await containersPage.getByRole('button', { name: 'Log in' }).click();
await containersPage.waitForURL('./containers');
const containersPage = await logInToContainersPage(setupPage);
// Reject example.com (requires enabled domain validation)
await containersPage.locator('#domain').click();