Browse Source

Fix Playwright docker (#6206)

pull/6166/head
Timshel 4 days ago
committed by GitHub
parent
commit
de808c5ad9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 16
      playwright/README.md
  2. 6
      playwright/compose/warden/Dockerfile
  3. 1
      playwright/compose/warden/build.sh
  4. 6
      playwright/playwright.config.ts
  5. 4
      playwright/test.env
  6. 19
      playwright/tests/setups/sso.ts
  7. 21
      playwright/tests/sso_login.spec.ts
  8. 2
      playwright/tests/sso_organization.spec.ts

16
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. This does not start the server, you will need to start it manually.
```bash ```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 ## Override web-vault
It is possible to change the `web-vault` used by referencing a different `bw_web_builds` commit. 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 ```bash
export PW_WV_REPO_URL=https://github.com/Timshel/oidc_web_builds.git DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env up Vaultwarden
export PW_WV_COMMIT_HASH=8707dc76df3f0cceef2be5bfae37bb29bd17fae6
DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env build Playwright
``` ```
# OpenID Connect test setup # OpenID Connect test setup

6
playwright/compose/warden/Dockerfile

@ -1,6 +1,6 @@
FROM playwright_oidc_vaultwarden_prebuilt AS prebuilt FROM playwright_oidc_vaultwarden_prebuilt AS prebuilt
FROM node:22-bookworm AS build FROM node:22-trixie AS build
ARG REPO_URL ARG REPO_URL
ARG COMMIT_HASH ARG COMMIT_HASH
@ -14,7 +14,7 @@ COPY build.sh /build.sh
RUN /build.sh RUN /build.sh
######################## RUNTIME IMAGE ######################## ######################## RUNTIME IMAGE ########################
FROM docker.io/library/debian:bookworm-slim FROM docker.io/library/debian:trixie-slim
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
@ -24,7 +24,7 @@ RUN mkdir /data && \
--no-install-recommends \ --no-install-recommends \
ca-certificates \ ca-certificates \
curl \ curl \
libmariadb-dev-compat \ libmariadb-dev \
libpq5 \ libpq5 \
openssl && \ openssl && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*

1
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) export VAULT_VERSION=$(cat Dockerfile | grep "ARG VAULT_VERSION" | cut -d "=" -f2)
./scripts/checkout_web_vault.sh ./scripts/checkout_web_vault.sh
./scripts/patch_web_vault.sh
./scripts/build_web_vault.sh ./scripts/build_web_vault.sh
printf '{"version":"%s"}' "$COMMIT_HASH" > ./web-vault/apps/web/build/vw-version.json printf '{"version":"%s"}' "$COMMIT_HASH" > ./web-vault/apps/web/build/vw-version.json

6
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). * But short action/nav/expect timeouts to fail on specific step (raise locally if not enough).
*/ */
timeout: 120 * 1000, timeout: 120 * 1000,
actionTimeout: 10 * 1000, actionTimeout: 20 * 1000,
navigationTimeout: 10 * 1000, navigationTimeout: 20 * 1000,
expect: { timeout: 10 * 1000 }, expect: { timeout: 20 * 1000 },
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: { use: {

4
playwright/test.env

@ -66,6 +66,10 @@ SSO_CLIENT_SECRET=warden
SSO_AUTHORITY=http://${KC_HTTP_HOST}:${KC_HTTP_PORT}/realms/${TEST_REALM} SSO_AUTHORITY=http://${KC_HTTP_HOST}:${KC_HTTP_PORT}/realms/${TEST_REALM}
SSO_DEBUG_TOKENS=true 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# # Docker MariaDb container#
########################### ###########################

19
playwright/tests/setups/sso.ts

@ -12,7 +12,7 @@ export async function logNewUser(
test: Test, test: Test,
page: Page, page: Page,
user: { email: string, name: string, password: string }, user: { email: string, name: string, password: string },
options: { mailBuffer?: MailBuffer, override?: boolean } = {} options: { mailBuffer?: MailBuffer } = {}
) { ) {
await test.step(`Create user ${user.name}`, async () => { await test.step(`Create user ${user.name}`, async () => {
await page.context().clearCookies(); await page.context().clearCookies();
@ -20,12 +20,8 @@ export async function logNewUser(
await test.step('Landing page', async () => { await test.step('Landing page', async () => {
await utils.cleanLanding(page); await utils.cleanLanding(page);
if( options.override ) { await page.locator("input[type=email].vw-email-sso").fill(user.email);
await page.getByRole('button', { name: 'Continue' }).click(); await page.getByRole('button', { name: /Use single sign-on/ }).click();
} else {
await page.getByLabel(/Email address/).fill(user.email);
await page.getByRole('button', { name: /Use single sign-on/ }).click();
}
}); });
await test.step('Keycloak login', async () => { await test.step('Keycloak login', async () => {
@ -69,7 +65,6 @@ export async function logUser(
user: { email: string, password: string }, user: { email: string, password: string },
options: { options: {
mailBuffer ?: MailBuffer, mailBuffer ?: MailBuffer,
override?: boolean,
totp?: OTPAuth.TOTP, totp?: OTPAuth.TOTP,
mail2fa?: boolean, mail2fa?: boolean,
} = {} } = {}
@ -82,12 +77,8 @@ export async function logUser(
await test.step('Landing page', async () => { await test.step('Landing page', async () => {
await utils.cleanLanding(page); await utils.cleanLanding(page);
if( options.override ) { await page.locator("input[type=email].vw-email-sso").fill(user.email);
await page.getByRole('button', { name: 'Continue' }).click(); await page.getByRole('button', { name: /Use single sign-on/ }).click();
} else {
await page.getByLabel(/Email address/).fill(user.email);
await page.getByRole('button', { name: /Use single sign-on/ }).click();
}
}); });
await test.step('Keycloak login', async () => { await test.step('Keycloak login', async () => {

21
playwright/tests/sso_login.spec.ts

@ -29,8 +29,8 @@ test('SSO login', async ({ page }) => {
test('Non SSO login', async ({ page }) => { test('Non SSO login', async ({ page }) => {
// Landing page // Landing page
await page.goto('/'); await page.goto('/');
await page.getByLabel(/Email address/).fill(users.user1.email); await page.locator("input[type=email].vw-email-sso").fill(users.user1.email);
await page.getByRole('button', { name: 'Continue' }).click(); await page.getByRole('button', { name: 'Other' }).click();
// Unlock page // Unlock page
await page.getByLabel('Master password').fill(users.user1.password); 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 // Landing page
await page.goto('/'); await page.goto('/');
await page.getByLabel(/Email address/).fill(users.user1.email);
// Check that SSO login is available // Check that SSO login is available
await expect(page.getByRole('button', { name: /Use single sign-on/ })).toHaveCount(1); await expect(page.getByRole('button', { name: /Use single sign-on/ })).toHaveCount(1);
await page.getByLabel(/Email address/).fill(users.user1.email); // No Continue/Other
await page.getByRole('button', { name: 'Continue' }).click(); await expect(page.getByRole('button', { name: 'Other' })).toHaveCount(0);
// 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')
}); });
@ -82,13 +74,12 @@ test('No SSO login', async ({ page }, testInfo: TestInfo) => {
// Landing page // Landing page
await page.goto('/'); await page.goto('/');
await page.getByLabel(/Email address/).fill(users.user1.email);
// No SSO button (rely on a correct selector checked in previous test) // 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); await expect(page.getByRole('button', { name: /Use single sign-on/ })).toHaveCount(0);
// Can continue to Master password // Can continue to Master password
await page.getByLabel(/Email address/).fill(users.user1.email);
await page.getByRole('button', { name: 'Continue' }).click(); 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);
}); });

2
playwright/tests/sso_organization.spec.ts

@ -65,7 +65,7 @@ test('Enforce password policy', async ({ page }) => {
await utils.logout(test, page, users.user1); await utils.logout(test, page, users.user1);
await test.step(`Unlock trigger policy`, async () => { 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('button', { name: 'Use single sign-on' }).click();
await page.getByRole('textbox', { name: 'Master password (required)' }).fill(users.user1.password); await page.getByRole('textbox', { name: 'Master password (required)' }).fill(users.user1.password);

Loading…
Cancel
Save