Skip to content

Overview

@saflib/playwright provides shared Playwright utilities for SAF products: typed string locators aligned with Vue copy, screenshot helpers for journey review, Vuetify conveniences, and a default config SPA packages extend.

E2E specs live in each client SPA under e2e/ (see @saflib/vue — e2e/). Product layout and client packages are described in base.

Writing tests

Tests are often authored manually or with agent help. A typical flow:

  1. Run the app against a production-like build (the prod-local script in the deploy/ folder). Production bundles behave more consistently under Playwright.
  2. Use Playwright codegen for a first pass.
  3. Refactor to fixtures and getByString using page .strings.ts exports. After vue/add-view, each page has a fixture stub to extend. This step is particularly good for an agent to do.

You can also use the vue/add-e2e-test workflow to create Playwright tests, though it's a good idea to have created the codegen tests to include in the prompts.

What this package provides

ExportRole
getByStringLocate elements from the same ElementString objects Vue binds (see String locators)
attachScreenshot / cleanScreenshotsVisual record of a user journey in the HTML report; Chromium copies land beside the spec for deploy bundling
chooseVuetifySelectOptionOpen a Vuetify combobox and pick an option (handles async items and truncated labels)
getUniqueEmail / getUniqueIdEphemeral test identities
tightAndroidViewportSmall mobile viewport for responsive checks
playwright.configDefault SAF config (browsers, health gate, timeouts)

Entrypoint: @saflib/playwright and @saflib/playwright/playwright.config.

Integration

SPA packages — each {product}/clients/{spa}/ holds e2e/**/*.spec.ts and a playwright.config.ts that re-exports the shared default (see base/clients/common/playwright.config.ts). Set DOMAIN and PROTOCOL for the stack under test (local dev uses docker.localhost / http).

Fixtures — page-level Playwright fixtures (PageName.fixture.ts) are scaffolded by vue/add-view. Cross-SPA flows compose fixtures from @saflib/ory-kratos-spa/fixtures, product common/fixtures, and page fixtures (example: base/clients/admin/e2e).

Security e2e — HTTP/browser security specs in @saflib/base-security use createSecurityPlaywrightConfig from @saflib/security/playwright/config (see @saflib/security), not this package's SPA default.

String locators

Playwright's built-in locators are flexible, but copy-heavy UIs break tests when strings drift. SAF shares the same string objects between Vue templates and Playwright via ElementString / ElementStringObject from @saflib/utils — see best-practices — shared strings.

Each page exports a .strings.ts file; the SPA re-exports them at ./strings so Playwright imports strings without pulling in Vite or Vue (see vue — strings.ts).

String objects use keys that map to HTML attributes (text, aria-label, data-testid, placeholder, label, …). Bind in Vue:

html
<button v-bind="elementStringObject" />

getByString picks the best matching Playwright locator for whichever keys are present (label → test id → placeholder → text). For i18n interpolation patterns in plain strings, it uses the same regex helper as @saflib/utils.

Define and organize strings in @saflib/vue — Components and i18n.

User journeys

Tests should cover the designed user journeys for the SPA they primarily exercise. Specs may cross subdomains (auth login, admin setup) when those dependencies are part of the journey — that is expected.

Organize specs under e2e/{journey}/ so screenshot artifacts stay grouped per flow.

Use attachScreenshot at key steps to document the journey in the HTML report. Call cleanScreenshots at the start of a spec so Chromium PNGs beside the test file reflect the latest run (gitignored; optional deploy bundling).

Default Playwright config

@saflib/playwright/playwright.config provides:

  • Projects — Chromium and Firefox, both depending on a server health setup project
  • Global health gateglobal.setup.ts polls {PROTOCOL}://api.{DOMAIN}/health until all configured API subdomains return 200 (matches product Caddy api.{DOMAIN})
  • Timeouts — 10s action and expect timeouts (Playwright defaults are 30s)
  • CIforbidOnly, two retries, single worker; local runs use parallel workers
  • Tracingon-first-retry; HTML reporter

Extend or replace in a SPA's playwright.config.ts when a product needs extra projects (mobile viewport, webkit, etc.).