diff --git a/playwright/README.md b/playwright/README.md index 249108b9..c8bcceda 100644 --- a/playwright/README.md +++ b/playwright/README.md @@ -91,17 +91,25 @@ When creating new scenario use the recorder to more easily identify elements This does not start the server, you will need to start it manually. ```bash -npx playwright codegen "http://127.0.0.1:8000" +DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env up Vaultwarden +npx playwright codegen "http://127.0.0.1:8003" ``` ## Override web-vault It is possible to change the `web-vault` used by referencing a different `bw_web_builds` commit. +Simplest is to set and uncomment `PW_WV_REPO_URL` and `PW_WV_COMMIT_HASH` in the `test.env`. +Ensure that the image is built with: + +```bash +DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env build Vaultwarden +``` + +You can check the result running: + ```bash -export PW_WV_REPO_URL=https://github.com/Timshel/oidc_web_builds.git -export PW_WV_COMMIT_HASH=8707dc76df3f0cceef2be5bfae37bb29bd17fae6 -DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env build Playwright +DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env up Vaultwarden ``` # OpenID Connect test setup diff --git a/playwright/compose/warden/Dockerfile b/playwright/compose/warden/Dockerfile index afa33858..e472d207 100644 --- a/playwright/compose/warden/Dockerfile +++ b/playwright/compose/warden/Dockerfile @@ -1,6 +1,6 @@ FROM playwright_oidc_vaultwarden_prebuilt AS prebuilt -FROM node:22-bookworm AS build +FROM node:22-trixie AS build ARG REPO_URL ARG COMMIT_HASH @@ -14,7 +14,7 @@ COPY build.sh /build.sh RUN /build.sh ######################## RUNTIME IMAGE ######################## -FROM docker.io/library/debian:bookworm-slim +FROM docker.io/library/debian:trixie-slim ENV DEBIAN_FRONTEND=noninteractive @@ -24,7 +24,7 @@ RUN mkdir /data && \ --no-install-recommends \ ca-certificates \ curl \ - libmariadb-dev-compat \ + libmariadb-dev \ libpq5 \ openssl && \ rm -rf /var/lib/apt/lists/* diff --git a/playwright/compose/warden/build.sh b/playwright/compose/warden/build.sh index da354112..a29067c8 100755 --- a/playwright/compose/warden/build.sh +++ b/playwright/compose/warden/build.sh @@ -16,7 +16,6 @@ if [[ ! -z "$REPO_URL" ]] && [[ ! -z "$COMMIT_HASH" ]] ; then export VAULT_VERSION=$(cat Dockerfile | grep "ARG VAULT_VERSION" | cut -d "=" -f2) ./scripts/checkout_web_vault.sh - ./scripts/patch_web_vault.sh ./scripts/build_web_vault.sh printf '{"version":"%s"}' "$COMMIT_HASH" > ./web-vault/apps/web/build/vw-version.json diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index 0f0df9c2..de721aa3 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -26,9 +26,9 @@ export default defineConfig({ * But short action/nav/expect timeouts to fail on specific step (raise locally if not enough). */ timeout: 120 * 1000, - actionTimeout: 10 * 1000, - navigationTimeout: 10 * 1000, - expect: { timeout: 10 * 1000 }, + actionTimeout: 20 * 1000, + navigationTimeout: 20 * 1000, + expect: { timeout: 20 * 1000 }, /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { diff --git a/playwright/test.env b/playwright/test.env index 300e0d55..d97c08d1 100644 --- a/playwright/test.env +++ b/playwright/test.env @@ -66,6 +66,10 @@ SSO_CLIENT_SECRET=warden SSO_AUTHORITY=http://${KC_HTTP_HOST}:${KC_HTTP_PORT}/realms/${TEST_REALM} SSO_DEBUG_TOKENS=true +# Custom web-vault build +# PW_WV_REPO_URL=https://github.com/dani-garcia/bw_web_builds.git +# PW_WV_COMMIT_HASH=a5f5390895516bce2f48b7baadb6dc399e5fe75a + ########################### # Docker MariaDb container# ########################### diff --git a/playwright/tests/setups/sso.ts b/playwright/tests/setups/sso.ts index 65e337f3..8998b6c7 100644 --- a/playwright/tests/setups/sso.ts +++ b/playwright/tests/setups/sso.ts @@ -12,7 +12,7 @@ export async function logNewUser( test: Test, page: Page, user: { email: string, name: string, password: string }, - options: { mailBuffer?: MailBuffer, override?: boolean } = {} + options: { mailBuffer?: MailBuffer } = {} ) { await test.step(`Create user ${user.name}`, async () => { await page.context().clearCookies(); @@ -20,12 +20,8 @@ export async function logNewUser( await test.step('Landing page', async () => { await utils.cleanLanding(page); - if( options.override ) { - await page.getByRole('button', { name: 'Continue' }).click(); - } else { - await page.getByLabel(/Email address/).fill(user.email); - await page.getByRole('button', { name: /Use single sign-on/ }).click(); - } + await page.locator("input[type=email].vw-email-sso").fill(user.email); + await page.getByRole('button', { name: /Use single sign-on/ }).click(); }); await test.step('Keycloak login', async () => { @@ -69,7 +65,6 @@ export async function logUser( user: { email: string, password: string }, options: { mailBuffer ?: MailBuffer, - override?: boolean, totp?: OTPAuth.TOTP, mail2fa?: boolean, } = {} @@ -82,12 +77,8 @@ export async function logUser( await test.step('Landing page', async () => { await utils.cleanLanding(page); - if( options.override ) { - await page.getByRole('button', { name: 'Continue' }).click(); - } else { - await page.getByLabel(/Email address/).fill(user.email); - await page.getByRole('button', { name: /Use single sign-on/ }).click(); - } + await page.locator("input[type=email].vw-email-sso").fill(user.email); + await page.getByRole('button', { name: /Use single sign-on/ }).click(); }); await test.step('Keycloak login', async () => { diff --git a/playwright/tests/sso_login.spec.ts b/playwright/tests/sso_login.spec.ts index b4817bed..8a1bb9ab 100644 --- a/playwright/tests/sso_login.spec.ts +++ b/playwright/tests/sso_login.spec.ts @@ -29,8 +29,8 @@ test('SSO login', async ({ page }) => { test('Non SSO login', async ({ page }) => { // Landing page await page.goto('/'); - await page.getByLabel(/Email address/).fill(users.user1.email); - await page.getByRole('button', { name: 'Continue' }).click(); + await page.locator("input[type=email].vw-email-sso").fill(users.user1.email); + await page.getByRole('button', { name: 'Other' }).click(); // Unlock page await page.getByLabel('Master password').fill(users.user1.password); @@ -58,20 +58,12 @@ test('Non SSO login impossible', async ({ page, browser }, testInfo: TestInfo) = // Landing page await page.goto('/'); - await page.getByLabel(/Email address/).fill(users.user1.email); // Check that SSO login is available await expect(page.getByRole('button', { name: /Use single sign-on/ })).toHaveCount(1); - await page.getByLabel(/Email address/).fill(users.user1.email); - await page.getByRole('button', { name: 'Continue' }).click(); - - // Unlock page - await page.getByLabel('Master password').fill(users.user1.password); - await page.getByRole('button', { name: 'Log in with master password' }).click(); - - // An error should appear - await page.getByLabel('SSO sign-in is required') + // No Continue/Other + await expect(page.getByRole('button', { name: 'Other' })).toHaveCount(0); }); @@ -82,13 +74,12 @@ test('No SSO login', async ({ page }, testInfo: TestInfo) => { // Landing page await page.goto('/'); - await page.getByLabel(/Email address/).fill(users.user1.email); // No SSO button (rely on a correct selector checked in previous test) - await page.getByLabel('Master password'); await expect(page.getByRole('button', { name: /Use single sign-on/ })).toHaveCount(0); // Can continue to Master password + await page.getByLabel(/Email address/).fill(users.user1.email); await page.getByRole('button', { name: 'Continue' }).click(); - await expect(page.getByRole('button', { name: /Log in with master password/ })).toHaveCount(1); + await expect(page.getByRole('button', { name: 'Log in with master password' })).toHaveCount(1); }); diff --git a/playwright/tests/sso_organization.spec.ts b/playwright/tests/sso_organization.spec.ts index c215ce3b..c1238d45 100644 --- a/playwright/tests/sso_organization.spec.ts +++ b/playwright/tests/sso_organization.spec.ts @@ -65,7 +65,7 @@ test('Enforce password policy', async ({ page }) => { await utils.logout(test, page, users.user1); await test.step(`Unlock trigger policy`, async () => { - await page.getByRole('textbox', { name: 'Email address (required)' }).fill(users.user1.email); + await page.locator("input[type=email].vw-email-sso").fill(users.user1.email); await page.getByRole('button', { name: 'Use single sign-on' }).click(); await page.getByRole('textbox', { name: 'Master password (required)' }).fill(users.user1.password);