Skip to main content

Architecture

This page describes the internal design of the PACE E2E framework: how the layers fit together, how a scenario travels from English prose to a running test, and where the key files live.

For the original design rationale see docs/superpowers/specs/2026-06-29-pace-e2e-docs-site-design.md and the framework overview in tests/README.md.


Repository layout

pace-e2e/ ← this repo (test-only; no app source)
tests/
e2e/ ← executable Playwright .spec.ts files
specs/ ← markdown scenario specs (Planner output)
page-objects/ ← Page Object Models
BasePage.ts ← root base class
features/ ← one sub-folder per domain
utils/ ← FormHelper, WaitHelper, TabHelper, AgGridHelper
fixtures/ ← auth.fixture.ts, data.fixture.ts, test-config.ts
data/ ← JSONC test-data manifests (Zod-validated)
agents/ ← canonical host-neutral agent prompts
rules/ ← playwright-rules.md (single source of conventions)
ci/
run-e2e.sh ← the shared CI runner script
playwright.config.ts
package.json
docs/ ← this Docusaurus site

The application source (React components, form configs, route definitions) lives in the sibling repo pace-ui-application, resolved via the PACE_APP_REPO environment variable (default ../pace-ui-application). No src/ exists here. When you need a field name or colId, grep that path directly.


The spec-to-test pipeline

A scenario moves through four stages, each owned by a dedicated agent:

English / recording


[Stabilizer] ──► tests/specs/{feature}/{name}.md (structured spec)


[Planner] ──► tests/specs/{feature}/{name}.md (new spec from scratch)


[Generator] ──► tests/e2e/{feature}/{name}.spec.ts
tests/page-objects/features/{domain}/ (if new POM needed)
tests/fixtures/auth.fixture.ts (if new fixture needed)


[Reviewer] ──► PASS / FAIL verdict + line-precise findings


Playwright runner ──► HTML report (test-results/)

Stage 1 — Stabilizer

Takes a raw VS Code Playwright recording (.spec.ts) plus a paired English step file (.steps.md) from tests/recordings/ and produces a canonical spec markdown file at tests/specs/. It does not emit a .spec.ts — that is the Generator's job.

Stage 2 — Planner

Writes a new spec from a free-form scenario description (English, user story, PRD excerpt). It reads the existing POMs and helpers first so that the step method: references in the spec resolve to real methods.

Stage 3 — Generator

Consumes one spec file and produces an executable .spec.ts plus any required POM/helper extensions. It runs the test once before reporting back. If a spec references a method that does not yet exist on the POM, the Generator creates it and marks it [NEW: ClassName.method()].

Stage 4 — Reviewer

Reviews the generated test (and any POM changes) against tests/agents/rules/playwright-rules.md. Emits a structured PASS/FAIL verdict with line-precise findings.


The four agents

All four canonical prompts live under tests/agents/:

FileRole
tests/agents/playwright-planner.mdSpec authoring from English
tests/agents/playwright-generator.md.spec.ts generation from spec
tests/agents/playwright-reviewer.mdRulebook-based review
tests/agents/playwright-stabilizer.mdRecording → spec conversion

Thin per-host adapters (.claude/, .codex/, .gemini/, .agent/) point at these canonical files. See Agents & the rulebook for details.


Data layer

Test data lives in tests/data/*.jsonc (one file per domain). The resolver (tests/utils/data-resolver.ts) loads, merges, and resolves {{env:VAR}} placeholders. Per-environment overrides are placed in tests/data/env/. Zod schemas in tests/data/schemas.ts enforce the shape; violations are caught by pnpm run test:validate-data. The typed surface exposed to tests is testConfig from tests/fixtures/test-config.ts.


Class hierarchy

BasePage
├── LoginPage
├── PlanDetailsFullscreenDialogPage
│ ├── FinancialEstimatesPage
│ └── ChangeOrdersPage
├── ProjectCreationPage
├── ProjectTeamPage
├── ClientsAgreementsPage
├── ProjectDeliverablesPage
└── PortfolioPage

Every page object extends BasePage — directly, or via an intermediate domain base class such as PlanDetailsFullscreenDialogPage — which wires up the four helper instances (WaitHelper, TabHelper, FormHelper, plus AgGridHelper instantiated per-grid by the feature POM). Tests never touch raw Playwright locators directly — all selector logic lives in page object locators constants or helper methods.


Environment selection

playwright.config.ts reads TEST_ENV (default dev2) to resolve baseURL from a built-in map. Set BASE_URL to bypass the map entirely for ad-hoc targets. PW_CHANNEL selects the browser: omit for branded Chrome (local dev), set to chromium for the official Playwright CI image.