Skip to content

feat(frontend): Playwright e2e harness gated on ui label (#556)#571

Merged
vybe merged 2 commits into
devfrom
feature/556-playwright-harness
Apr 29, 2026
Merged

feat(frontend): Playwright e2e harness gated on ui label (#556)#571
vybe merged 2 commits into
devfrom
feature/556-playwright-harness

Conversation

@oleksandr-korin

Copy link
Copy Markdown
Contributor

Summary

Phase 2 of #556. Adds Playwright as the frontend e2e test layer with a minimal smoke-test suite. CI runs only on PRs that carry the `ui` label (this PR has it, so the workflow exercises itself).

What this adds

File Purpose
`src/frontend/playwright.config.js` Chromium-only, configurable `E2E_BASE_URL`, HTML+list reporter, on-failure screenshots/videos/traces
`src/frontend/e2e/auth.setup.js` Storage-state pattern: login once via the admin form, reuse session across all specs
`src/frontend/e2e/smoke.spec.js` 4 smoke tests — dashboard, /agents, /operating-room, /templates
`src/frontend/e2e/README.md` How to run locally + add new tests
`src/frontend/.gitignore` Excludes session JSON + test artifacts
`src/frontend/package.json` `@playwright/test` dev dep + `test:e2e[:ui
`.github/workflows/frontend-e2e.yml` Label-gated CI workflow

CI strategy: opt-in via `ui` label

The workflow runs only when a PR has the `ui` label. Each run:

  1. Starts the full Trinity docker-compose stack (~3–5 min)
  2. Waits for backend health
  3. Runs Playwright against `http://localhost\`
  4. Uploads HTML report + failure artifacts

This avoids spending ~5 min on every backend-only PR. To exercise e2e on a frontend PR, just add the `ui` label.

Naming choice

Label is `ui` (single word, matches existing style like `enhancement`). Chosen over `e2e` / `frontend` / `needs-visual-test` for brevity and because it covers any UI change, not just visual regression.

Out of scope (tracked in #556)

How to run locally

```bash
./scripts/deploy/start.sh # bring up Trinity
cd src/frontend
ADMIN_PASSWORD= npm run test:e2e # run smoke
npm run test:e2e:headed # with visible browser
npm run test:e2e:ui # interactive mode
```

CI secrets needed (one-time setup)

  • `E2E_ADMIN_PASSWORD` — admin password for the CI Trinity stack (falls back to `ci-test-password` if unset)
  • `E2E_ANTHROPIC_API_KEY` — placeholder is acceptable since smoke tests don't exercise agent execution

Test plan

  • `npm install -D @playwright/test` succeeds
  • `npx playwright install chromium` succeeds
  • `npm run test:e2e` runs and reaches the login page (auth flow exercised; full pass requires stable backend — flaky locally due to docker-port-binding bug unrelated to this PR)
  • CI runs the workflow on this PR with the `ui` label and reports green

Refs #556

🤖 Generated with Claude Code

Phase 2 of #556 (frontend test infrastructure). Adds @playwright/test as a
dev dependency and a minimal smoke-test harness covering login, dashboard,
agents, operating room, and templates pages.

Files:
  src/frontend/playwright.config.js     Chromium-only, baseURL configurable
  src/frontend/e2e/auth.setup.js        Storage-state pattern (login once,
                                        reuse session across specs)
  src/frontend/e2e/smoke.spec.js        4 cross-page smoke tests
  src/frontend/e2e/README.md            How to run + add tests
  src/frontend/.gitignore               Excludes session state + reports
  src/frontend/package.json             test:e2e[:ui|:headed|:update] scripts
  .github/workflows/frontend-e2e.yml    Runs only on PRs with `ui` label

CI strategy: e2e is opt-in via the `ui` label rather than running on every
frontend PR — the workflow stands up the full Trinity docker-compose stack
and adds ~5 min runtime per PR. Backend-only PRs skip it.

Out of scope (separate slices of #556):
  - Vitest unit / component tests (Phase 1)
  - vue-tsc type checking (Phase 3)
  - Visual regression baseline for the design system (added per-component
    in #569 follow-ups)

Local verification: `cd src/frontend && ADMIN_PASSWORD=<pwd> npm run test:e2e`
against a running ./scripts/deploy/start.sh stack. CI is the canonical
verification path.

Refs #556

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@oleksandr-korin oleksandr-korin added the ui PR touches the frontend UI — triggers Playwright e2e tests label Apr 28, 2026
)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vybe
vybe merged commit 747d156 into dev Apr 29, 2026
vybe pushed a commit that referenced this pull request Apr 29, 2026
* fix(e2e): make Playwright auth setup actually authenticate (#556)

The harness landed in #571 but its auth.setup.js had two bugs that
prevented every downstream test from being authenticated. Both surfaced
on the first CI run.

  1. Admin-login toggle button text is "🔐 Admin Login" — Playwright's
     getByRole accessible-name match doesn't normalize the emoji prefix
     reliably. Switch to `button:has-text("Admin Login")`.

  2. Saving storageState immediately after the password field is hidden
     captured an empty state (0 cookies, 0 localStorage entries). The
     auth store's `localStorage.setItem('token', ...)` write happens
     async after the form unmounts. Poll until the token actually lands
     in localStorage before saving.

Also tighten supporting selectors:
  - Submit button → `form button[type="submit"]` (no copy dependency)
  - Smoke nav check → `getByRole('link', { name: 'X', exact: true })`

Verified locally against a live ./scripts/deploy/start.sh stack:
  5 passed (5.1s) — auth setup + 4 smoke specs.

Refs #556

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(e2e-ci): skip first-time setup wizard on fresh DBs

CI was failing the auth.setup because the frontend redirected to /setup —
the first-time setup wizard. On a fresh install:

  1. Migration #19 (setup_completed_backfill) runs *before* admin user
     creation, finds no admin, skips the backfill
  2. _ensure_admin_user creates the admin from ADMIN_PASSWORD env var
  3. Nothing ever sets setup_completed=true → wizard appears

Production avoids this because admin already exists when migrations run.
For CI we explicitly mark setup complete via docker exec right after
backend health.

Also bump the fallback ADMIN_PASSWORD from `ci-test-password` (no upper,
no digit, no special — fails OWASP ASVS 2.1) to `CiTestPassword!1` so
the backend doesn't warn / silently misbehave on startup.

Refs #556

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vybe pushed a commit that referenced this pull request Apr 29, 2026
…#582)

Frontend equivalent of /test-runner. Existing /test-runner only knows
about pytest; nothing covered the Playwright suite added in #571 / #579.

The skill encodes:
  - Pre-flight checks (backend + frontend health, admin password sanity)
  - npm run test:e2e orchestration with --update-snapshots / --headed /
    --ui / --grep variants
  - Failure classification with concrete recovery commands for the six
    patterns we hit while building the harness:
      A. Stack down (port-zombie diagnostics + Docker Desktop restart)
      B. Stuck on /setup wizard (fresh-DB CI scenario, fix via
         db.set_setting('setup_completed','true'))
      C. Invalid username/password (env drift between shell and container)
      D. Submit button disabled (form precondition issue, not stack)
      E. Auth setup passes but smoke specs land on /login (storageState
         saved before localStorage.token write — known issue fixed in #579)
      F. Visual regression baseline mismatch (intentional vs unintentional
         decision tree)
  - Reminder to add the `ui` PR label so frontend-e2e CI runs

Refs #556

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui PR touches the frontend UI — triggers Playwright e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants