Playwright E2E Authoring — gc.platform
SkillWeb & browsingLets your agent scaffold Playwright E2E tests with this Playwright Claude skill, testing a real frontend and backend instead of mocks.
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Playwright E2E Authoring skill
About this skill
Scaffold and extend Playwright E2E tests for the gc.platform suite (tests/playwright), wiring every artifact to the real frontend (localhost:4200) + real .NET backend, never mocks. Use whenever the user wants to add or write E2E / end-to-end tests, cover a new frontend feature module or screen, cre
What this skill tells your AI
The instructions your AI receives, as published by fmflurry/settings-opencode in skills/playwright-e2e-authoring/SKILL.md and read by ahel’s review.
This suite tests the live gc.platform stack end-to-end: the real Angular frontend (http://localhost:4200) plus the real GcPlatform.Api .NET backend, orchestrated by docker-compose at the repo root. Tests drive the full stack — there are no mocks, no stubs, no fake data.
Path convention: All paths in this document are relative to tests/playwright/ (the test suite root).
Your job when this skill is active: turn a request like "add E2E tests for the <feature> screen" into a correct POM + module fixture + spec, colocated under tests/<module>/, that compiles under strict TypeScript and follows the conventions the existing auth and invoices modules already demonstrate.
When to activate
- Adding E2E coverage for a new frontend feature module or screen.
- Writing a new
.spec.ts, a Page Object Model, or a module fixture. - Extending an existing module with another screen/POM.
- Any "test the X page/flow with Playwright" request, even when the conventions aren't named.
The four rules (non-negotiable — they are project law)
These come from tests/playwright/CLAUDE.md. Everything this skill generates must honour them.
| # | Rule | What it means in practice |
|---|---|---|
| 1 | No mocks | Real frontend + real backend + real DB. No page.route()/context.route(), no MSW/sinon/nock, no fixture stubs, no page.waitForTimeout() or arbitrary sleeps. Create/clean test data via real API or UI. |
| 2 | Page Object Model | Every screen is a POM class under tests/<module>/pages/ extending BasePage. Specs never call raw page.locator() — all DOM access flows through a POM. |
| 3 | Work by fixture | POMs are injected via Playwright fixtures (test.extend). Specs import test/expect from their module fixture, never from @playwright/test. Never new SomePage() inside a spec. |
| 4 | Per application module | One test folder per frontend feature: frontend/src/app/modules/<module> → tests/<module>/. POM, fixtures, and specs stay colocated. Cross-module helpers live in support/. |
Before you start
- Confirm the stack is meant to be live. Tests assume
docker-compose upis running (frontend + backend healthy). You don't have to start it to author files, but never compensate for a missing backend with a mock. - Find the frontend module under
frontend/src/app/modules/<module>so the test folder name mirrors it exactly (Rule 4). If unsure of the name, ask or inspect the frontend tree. - Understand test accounts: The default authenticated session uses
tenant-a-user(seeded identity for tenant TEN-A via env varsPLAYWRIGHT_KC_USERNAME/PLAYWRIGHT_KC_PASSWORD, defaults:Nova-Delta-17!). Avoid reusing this account in password-reset specs — provision a disposable account viasupport/identity-accounts.ts. Thedev-useridentity has notenant_idclaim, so tenant-scoped screens (dunning, notifications, payments) render empty; use it only for session/logout tests. - Decide public vs authenticated — this picks which base fixture you extend. This is the single most important choice; see the table below and
references/fixtures.md.
| Route kind | Example | Module fixture extends | POMs bound to | Extra step |
|---|---|---|---|---|
Authenticated (behind authSessionGuard) | /invoices | support/fixtures/auth.fixture | authenticatedPage | Add the route to the warm-up loop in support/auth.setup.ts |
| Public | /login, /activer | support/fixtures/base.fixture | page | none |
Workflow
Create the folder structure, then the artifacts in dependency order (POM → fixture → spec). Read the matching reference file before writing each kind — they hold the exact templates and the reasoning behind each convention.
-
Scaffold the folders
tests/<module>/ ├─ pages/ # one <screen>.page.ts per screen ├─ fixtures/ # <module>.fixture.ts └─ <feature>.spec.ts -
Write the POM(s) — one per screen. → read
references/pom.md- Extend
BasePage(import { BasePage } from '../../../support/pages/base.page';). - Declare
private readonlyLocators, assign them in the constructor. - Prefer
getByRole()/getByLabel()/getByTestId()over CSS/XPath. - Expose actions (
goto, clicks, fills) and high-level assertions (expectLoaded,expect…).
- Extend
-
Write the module fixture —
fixtures/<module>.fixture.ts. → readreferences/fixtures.md- Extend
base(public) orauth(authenticated) per the table above. - Provide every POM as a fixture key.
- Re-export
expect.
- Extend
-
Write the spec(s) —
<feature>.spec.ts. → readreferences/spec.mdimport { test, expect } from './fixtures/<module>.fixture';- Group with
test.describe, share setup withtest.beforeEach. - Use web-first assertions only; no sleeps, no network interception.
- If the test creates data (not just reads seeded fixtures), read
references/data-setup.mdfor API-based setup/teardown patterns.
-
If the routes are authenticated, append them to the route warm-up loop in
support/auth.setup.tsso the dev server's lazy compile is paid once, serially, before workers fan out.
Shared helpers in support/
When setting up test data or managing test state across modules, reach for these helpers:
| Helper | Purpose |
|---|---|
keycloak-token.ts | Fetch a fresh access token via Authorization Code + PKCE flow for API calls from specs. |
identity-accounts.ts | Provision a disposable account (email + password + accountId) via POST /identity/accounts for password-reset flows. |
keycloak-admin.ts | Revoke a Keycloak session server-side (admin API); used to trigger session-loss tests. |
mailpit.ts | Poll Mailpit SMTP for password-reset emails and extract the reset link. |
dunning-report-supply.ts | Poll the dunning report generation status and check when lines appear. |
Time budgets
The config (playwright.config.ts) sets generous defaults for the real stack:
timeout: 90_000— per-test wall-clock limit (90s for frontend + backend round-trips + lazy compile).expect.timeout: 15_000— auto-retry window for assertions (15s for Transloco fetch + transforms).- CI:
retries: 1,workers: 2— one safety retry, two parallel workers.
Raise limits only for tests that legitimately need extra time (e.g., AI report generation: test.setTimeout(20 * 60 * 1000);) with a comment explaining why.
Admitted exceptions
See references/spec.md#admitted-exceptions for bounded fault injection, multi-context, and alternate-tenant patterns. All three are strict, justified-only uses; never extend beyond their examples.
Multiple fixtures per module
A module may hold several fixture files when specs need genuinely different base states. Example: tests/auth/fixtures/ has three:
auth.fixture.ts— unauthenticated journey (public routes like login, sign-up).session.fixture.ts— extends the sharedsupport/fixtures/auth.fixture, reusing the storageState.stay-connected.fixture.ts— simulates a browser restart by clearing storageState mid-flow.
Each fixture explains its purpose in a JSDoc; never duplicate a fixture without documenting why the separation is necessary.
Routing
The e2e-runner agent and /e2e command hand Playwright work to this skill. After implementation, the playwright-e2e-review skill audits the result against the four rules.
Reference files
Read the one that matches what you're writing — don't write from memory:
references/pom.md— Page Object Model template, locator strategy, theBasePagecontract, annotated real example.references/fixtures.md— base vs auth fixtures, theauthenticatedPagemechanism, theRecord<never, never>gotcha, module-fixture templates,mergeTests.references/spec.md— spec structure, web-first assertions, real-data setup/teardown, naming conventions.references/data-setup.md— creating and cleaning test data via the real API, seeded vs. transient data, extracting auth tokens, defensive teardown patterns.
Verify before done
The suite is strict TypeScript (tsc with strict: true, noImplicitAny) and the repo bans the any type. Before reporting success:
cd tests/playwright
npx tsc --noEmit --pretty false # must be clean
If the stack is up, you can also run the new module:
npm run test:e2e -- tests/<module>
Note: the suite runs against system Chrome (channel: 'chrome' in playwright.config.ts) because the Playwright browser CDN is firewall-blocked here. Don't add firefox/webkit projects expecting downloaded browsers.
Signals
- GitHub stars
- 171
- Forks
- 9
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
playwright-e2e-authoring- Source
- github.com/fmflurry/settings-opencode
github.com/fmflurry/settings-opencode
Related picks
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptcometchat-angular-v5-features
Skill · cometchat
The pick for Angularintegration-angular
Skill · posthog
The pick for Angulardotnet-test
Skill · nikiforovall
The pick for .NETdotnet-backend-patterns
Skill · wshobson
The pick for .NET