| type | Work Queue | |||
|---|---|---|---|---|
| title | Playwright example e2e smoke | |||
| description | Phased, orchestrator-processable backlog to add Playwright smoke tests for every monorepo example, run them locally and in CI, then harden dependencies. | |||
| tags |
|
|||
| timestamp | 2026-07-03 00:00:00 UTC | |||
| status | active |
A fully automated e2e framework that validates each monorepo example loads and responds to basic interaction, runnable by local invocation and in CI, with one minimum-viable smoke per example. Normative scope: AD-3. Execution model: AD-4. Production-artifact validation is deferred: AD-8.
Ephemeral tracker; policy: documentation-policy.md. This queue records state (gates, next step) using neutral OKF work-queue field conventions — not agent roles, dispatch, or session choreography.
Work types (next_work_type): gap-analysis (read-only feasibility) · implementation (author code + tests) · independent-review (verify a frozen diff) · documentation (durable doc/OKF updates) · commit (one focused commit).
Validation tiers (validation_tier), mapped to this repo:
| Tier | Meaning here |
|---|---|
unit-focused |
Fast local check while authoring: pnpm build:packages, the targeted example's spec (pnpm test:e2e:<example>), pnpm lint:check on the diff |
area-focused |
Full smoke for the changed example(s) on a frozen tree, plus pnpm test / lint / format as applicable |
full |
pnpm build + pnpm test + whole pnpm test:e2e across all examples before merge |
Gates (open | closed | deferred): implementation_gate (implementation complete + unit-focused green) · review_gate (independent review complete on frozen tree + area-focused green) · commit_gate (durable commit exists whose subject matches commit_subject). deferred = optional work parked until a trigger (e.g. flakiness) re-opens it. Code with review_gate: open is untrusted until review closes it. commit_subject is the planned Conventional Commit subject, set before git commit and staged in the same commit; never record SHAs.
Per UI example, one shared spec (parameterized per project). Assert on rendered UI, not exact URLs — the forgot-password route differs per example (examples-inventory.md); AD-3.
| Step | Action | Pass criterion |
|---|---|---|
| S1 | goto sign-in-with-handlers path |
Email + password fields and submit button visible |
| S2 | Click submit (empty) | Validation feedback (no successful auth required) |
| S3 | Click forgot-password control | Forgot-password screen renders (assert heading/email field, not a fixed path) |
custom-auth-server is not a browser flow: boot the built Express server on :4001 and assert an HTTP response (AD-6).
Playwright manages each example's dev server; no hand-rolled preflight/postflight/PID scripts (AD-4).
scripts/e2e-run.mjs (pnpm test:e2e)
→ build:packages once (assert dist/)
→ start Auth emulator once (:9099, shared)
→ for each example in [react, shadcn, nextjs, nextjs-ssr, angular-example, custom-auth-server]:
playwright test (E2E_PROJECT=<example>, E2E_KEEP_EMULATOR=1)
→ globalSetup: assert packages built + ensure Auth emulator on :9099 (start if needed)
→ top-level webServer selected by E2E_PROJECT (UI examples only; custom-auth-server boots in spec)
→ run smoke spec(s) for the project
→ webServer: stop dev server (UI examples)
→ globalTeardown: keep emulator alive when E2E_KEEP_EMULATOR=1
→ stop emulator if globalSetup started it (e2e-run.mjs postflight)
- Serial:
workers: 1;E2E_PROJECTselects both the single Playwright project and the top-levelwebServer, so one dev server is up at a time. - Emulator:
globalSetupensures:9099is reachable (starts vianpx firebase-toolswhen not already running); serial runner setsE2E_KEEP_EMULATOR=1so teardown does not stop it between examples;pnpm emulatorsremains the first-class manual target (LOCAL_DEVELOPMENT.md). - Per-example debug:
pnpm test:e2e:reactbuilds packages before Playwright starts Vite, then runs one project;globalSetupassertsdist/and starts the emulator with reuse if not already running.
Owner: architecture/examples-inventory.md (human reference) and e2e/fixtures/example-meta.ts (runtime). Root package.json defines test:e2e (serial runner) and test:e2e:<example> debug entrypoints.
See architecture/testing-strategy.md and .github/workflows/e2e.yaml. Workflow runs pnpm test:e2e with broad path triggers — AD-7.
Each item runs one serial loop; the queue records the outcome after each step.
| Step | Work type | Closes gate |
|---|---|---|
| 1 | implementation |
implementation_gate (unit-focused green) |
| 2 | independent-review |
review_gate (frozen tree, area-focused green; blocking findings → back to step 1) |
| 3 | documentation |
— (only if durable docs/OKF changed) |
| 4 | commit |
commit_gate (set commit_subject, stage queue with product change) |
Prove the whole model end-to-end on one example before generalizing (review finding #13).
| ID | Task | Depends | Done when |
|---|---|---|---|
| 1.1 | e2e/ workspace package; @playwright/test pinned via pnpm catalog; skeleton playwright.config.ts |
— | Package installs; empty config runs |
| 1.2 | globalSetup/globalTeardown: run build:packages and assert dist/; ensure/start shared Auth emulator on :9099; stop what it started |
1.1 | Setup fails fast with clear errors; emulator reused if already up |
| 1.3 | e2e/fixtures/example-meta.ts: seed react (baseURL, sign-in path, trailing-slash rule, forgot-password target) |
1.1 | Per-example path rules centralized |
| 1.4 | react project webServer (vite --port 5173 --strictPort); harness page.route block of accounts.google.com with a comment explaining why (One Tap external/flaky — AD-5) |
1.2, 1.3 | react dev server managed by Playwright; One Tap script never loaded |
| 1.5 | e2e/tests/sign-in-handlers.spec.ts S1–S3, asserting rendered UI, parameterized per project |
1.4 | react smoke green locally |
| 1.6 | Minimal CI job proving react e2e runs green (browser install + emulator + test:e2e:react) |
1.5 | react smoke green in CI |
| ID | Task | Depends | Done when |
|---|---|---|---|
| 2.1 | shadcn project + meta (vite --port 5174; forgot-password → /screens/forgot-password-screen) |
1.5 | shadcn smoke green |
| 2.2 | nextjs project + meta (next dev -p 3000; trailingSlash) |
1.5 | nextjs smoke green |
| 2.3 | nextjs-ssr project + meta (next dev -p 3001; generous webServer.timeout) |
1.5 | nextjs-ssr smoke green |
| 2.5 | scripts/e2e-run.mjs serial runner + root test:e2e / test:e2e:<example> scripts; CI runs pnpm test:e2e |
2.1–2.3 | pnpm test:e2e covers all wired UI examples locally and in CI |
Split from Phase 2 when bootstrap failed under workspace linking; resolved via peer-resolved injected workspace dependency and provider factory cleanup in @firebase-oss/ui-angular.
| ID | Task | Depends | Done when |
|---|---|---|---|
| 2b.1 | angular-example project + meta (reuse run start -- --port 4200, i.e. clean && ng serve) |
2.5 | meta + test:e2e:angular wired |
| 2b.2 | Fix client bootstrap so sign-in form renders in Playwright | 2b.1 | S1–S3 pass locally |
| 2b.3 | Add angular-example to e2e-run.mjs + pnpm test:e2e |
2b.2 | serial runner includes angular (five UI examples) |
| 2b.4 | Confirm pnpm test:e2e in CI includes angular |
2b.3 | CI serial smoke includes angular |
Depends on Phase 2 CI baseline (2.5).
| ID | Task | Depends | Done when |
|---|---|---|---|
| 3.1 | E2e workflow hardening: playwright install --with-deps chromium with browser cache keyed on resolved Playwright version; confirm pnpm test:e2e green in CI |
2.5 | e2e green on PRs; browsers cached across runs |
| 3.2 | Broad path triggers: packages/**, examples/**, root package.json, pnpm-lock.yaml, pnpm-workspace.yaml, e2e/**, workflow file (AD-7) |
3.1 | Relevant PRs trigger e2e; shared-dependency changes not missed |
| ID | Task | Depends | Done when |
|---|---|---|---|
| 4.1 | Bind custom-auth-server to :4001 for e2e; boot built server + assert HTTP response (non-browser); wire into runner + CI (AD-6) |
2.5, 3.1 | custom-auth-server smoke in pnpm test:e2e locally and in CI |
Deferred — no flakiness observed; page.route One Tap block is sufficient (AD-5). Re-open only if smoke becomes unstable.
| ID | Task | Depends | Done when |
|---|---|---|---|
| 5.1 | react + shadcn: skip oneTapSignIn when VITE_E2E=1 |
2.1 | Only if page.route block insufficient |
| 5.2 | nextjs + nextjs-ssr: skip autoAnonymousLogin when NEXT_PUBLIC_E2E=1 |
2.3 | Only if anon sign-in destabilizes smoke |
Includes package/catalog deps and CI workflow deps (Node version, GitHub Actions pins) in one bump pass — not package deps alone.
| ID | Task | Depends | Done when |
|---|---|---|---|
| 6.1 | Align catalog/example deps, root packageManager, and CI workflow toolchain (Node LTS, pinned actions in test/lint/e2e) to current stable |
3.1 | CVE audit improved; one Node version across workflows |
| 6.2 | Run dependency-update-verification.md including test:e2e |
6.1 | Smoke passes on dep PR |
| 6.3 | Optional pnpm audit --audit-level=high in CI |
6.2 | Team decision |
| 6.4 | Instrumented e2e coverage: Istanbul-instrumented package/example builds, line-resolved NYC/LCOV report, CI artifact | 6.2 | Per-package line coverage from smoke; guides test gap analysis |
Update immediately after each step closes a gate. All items start open / implementation.
| Phase | Item | implementation_gate |
review_gate |
commit_gate |
commit_subject |
next_work_type |
validation_tier |
Notes |
|---|---|---|---|---|---|---|---|---|
| 1 | 1.1–1.6 Phase 1 (react vertical slice) | closed | closed | closed | test(e2e): install/configure playwright, implement react e2e smoke test | — | — | |
| 2 | 2.1–2.3 shadcn, nextjs, nextjs-ssr | closed | closed | closed | test: working e2e tests for shadcn, nextjs, and nextjs-ssr | — | — | |
| 2 | 2.5 serial runner + root scripts | closed | closed | closed | test: working e2e tests for shadcn, nextjs, and nextjs-ssr | — | — | |
| 2b | 2b.1–2b.4 angular-example e2e | closed | closed | closed | test(angular): e2e test for angular example | — | — | |
| 3 | 3.1–3.2 CI hardening | closed | closed | closed | ci(e2e): harden workflow triggers and browser cache | — | — | |
| 4 | 4.1 custom-auth-server HTTP smoke (:4001) | closed | closed | closed | test(e2e): add custom-auth-server HTTP smoke on :4001 | — | — | |
| 5 | 5.1 VITE_E2E skip oneTapSignIn | deferred | deferred | deferred | — | — | — | optional; no flakiness observed |
| 5 | 5.2 NEXT_PUBLIC_E2E skip autoAnonymousLogin | deferred | deferred | deferred | — | — | — | optional; no flakiness observed |
| 6 | 6.1 align catalog + CI workflow deps | open | open | open | — | implementation | area-focused | Node/actions with package bump |
| 6 | 6.2 dep-update playbook incl. test:e2e | open | open | open | — | implementation | full | |
| 6 | 6.3 optional audit gate | open | open | open | — | implementation | unit-focused | team decision |
| 6 | 6.4 instrumented e2e line coverage | open | open | open | — | implementation | area-focused | Istanbul + LCOV artifact |
e2e/
├── package.json
├── playwright.config.ts # projects + top-level webServer selected by E2E_PROJECT; globalSetup/teardown
├── global-setup.ts # build:packages assert + start/reuse emulator
├── global-teardown.ts # stop emulator if started here
├── fixtures/
│ └── example-meta.ts # per-example routing and server metadata (ui | http kind)
└── tests/
├── sign-in-handlers.spec.ts
└── custom-auth-server.spec.ts
scripts/
└── e2e-run.mjs # serial per-example runner for `pnpm test:e2e`
| Item | Reason |
|---|---|
Auth-behavior E2E flags (VITE_E2E, NEXT_PUBLIC_E2E) |
No flakiness observed; page.route block sufficient — AD-5 |
| Istanbul line coverage from e2e smoke | Phase 6.4; interim V8 byte metrics in e2e/coverage-report/ |
Production-artifact e2e (SSG export, SSR next start, Angular prod build, hosting rewrites) |
Future design phase; MVP is dev-server only — AD-8 |
| Parallel multi-example e2e | Unique ports make it possible later; serial sufficient for MVP — AD-4 |
| Real emulator sign-in flows | Post-MVP user scenarios |
| Multi-browser matrix | Chromium only for MVP |
| Angular-SSR smoke | Angular tested via CSR ng serve; SSR path deferred |
Feasibility review (verified against code) that shaped this queue:
- Deep-link
/screens/sign-in-auth-screen-w-handlersexists in all five UI examples; forgot-password target differs (shadcn/screens/forgot-password-screenvs react/angular/screens/forgot-password-auth-screen) → S3 asserts rendered UI. SignInAuthScreenrenders the form regardless of auth state → auth-behavior flags decoupled (Phase 5, optional).- Playwright top-level
webServerselected byE2E_PROJECT+globalSetupreplace hand-rolled orchestration (biggest simplification). custom-auth-serverdefault:4000collides with Emulator UI →:4001.- CI path-filtering must be broad (examples depend on
packages/**, root manifests, lockfile, catalog). - #13: react-only vertical slice first, to validate the model cheaply.