Skip to content

fix(e2e): make Playwright auth setup actually authenticate (#556)#579

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

fix(e2e): make Playwright auth setup actually authenticate (#556)#579
vybe merged 2 commits into
devfrom
feature/556-playwright-auth-fix

Conversation

@oleksandr-korin

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #571 (PR #571 / merged commit `747d156e`). The harness landed but its `auth.setup.js` had two bugs that meant every downstream smoke test landed on `/login` and failed. Both surfaced on the first CI run on `dev`.

What was wrong

Bug Symptom Fix
Emoji prefix in admin-login button — "🔐 Admin Login" — broke Playwright's `getByRole` accessible-name normalization `isVisible({ timeout: 5000 })` returned false even though the button was visible; admin form was never opened Switch to `button:has-text("Admin Login")` (substring text match)
storageState saved before localStorage write — Trinity's auth store calls `localStorage.setItem('token', ...)` async after the password form unmounts; my "password hidden → save" check fired first Saved `admin.json` had 0 cookies / 0 localStorage entries; smoke specs landed on `/login` Poll until `localStorage.token` is non-null, then save storageState

Also tightened supporting selectors:

  • Submit button → `form button[type="submit"]` (no copy dependency)
  • Smoke nav assertions → `getByRole('link', { name: 'X', exact: true })` instead of fuzzy `getByText`

Verification

Verified locally against a fresh `./scripts/deploy/start.sh` stack:

```
[setup] authenticate as admin (2.5s) ✓
[chromium] dashboard renders for authenticated admin (860ms) ✓
[chromium] agents page loads (917ms) ✓
[chromium] operating room page loads (897ms) ✓
[chromium] templates page loads (842ms) ✓

5 passed (5.1s)
```

CI on this PR (`ui` label set) will confirm the same in a clean environment.

Files

```
src/frontend/e2e/auth.setup.js | 31 ++++++++++++++++++-------------
src/frontend/e2e/smoke.spec.js | 6 +++---
2 files changed, 28 insertions(+), 16 deletions(-)
```

Refs #556

🤖 Generated with Claude Code

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>
@oleksandr-korin oleksandr-korin added the ui PR touches the frontend UI — triggers Playwright e2e tests label Apr 29, 2026
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

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — both bugs well-diagnosed (emoji selector + localStorage race), locally verified 5/5 passing.

@vybe
vybe merged commit 13612bb into dev Apr 29, 2026
2 checks passed
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