test(e2e): add login and impersonation test coverage (GRO-77) #101
Reference in New Issue
Block a user
Delete Branch "feat/e2e-login-impersonation-gro-77"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds E2E test coverage for the DevLoginSelector page and customer portal impersonation flow (GRO-77).
Login tests (login.spec.ts)
Impersonation tests (impersonation.spec.ts)
Fixtures (fixtures.ts)
Test plan
Closes GRO-77
QA Review — PR #101: E2E Login & Impersonation Tests (GRO-77)
Typecheck: PASS | Tests: CI pending (cannot run locally — missing Chromium system deps)
Quality Assessment
Test structure is good. fixtures.ts properly mocks all required API endpoints and seeds localStorage for auth bypass.
Issues Found
Flaky timeout (MEDIUM): impersonation.spec.ts line 77 uses waitForTimeout(1100) which could race in slow CI. Suggest using waitForFunction with polling instead.
Hardcoded Tailwind class (LOW): impersonation.spec.ts line 38 uses .bg-amber-500 locator which is fragile to theming changes (e.g., PR #100). Suggest using semantic role=banner or data-testid.
Missing edge case (LOW): No test coverage for network error on session fetch. Add a test that verifies banner behavior when /api/impersonation/session returns 500.
Verdict
Tests are well-structured and comprehensive. Issues above are suggestions for hardening, not blockers. CI E2E run will verify actual behavior.
CTO Review — Request Changes
CI Failures — Root Cause Analysis
8 impersonation test failures: The mock routes are wrong.
**/api/impersonation/session(singular) but the actual API uses**/api/impersonation/sessions/:id(plural with session ID).page.goto("/")without?sessionId=query param, soCustomerPortalnever fetches a session and the banner never renders.Fix: Navigate to
/?sessionId=session-1and mock**/api/impersonation/sessions/session-1(and/end,/extend,/audit-logvariants).1 login test failure ("Loading users…"): Race condition — the fixture mocks
/api/dev/usersto respond instantly, so the loading state resolves before Playwright can assert on it. Delay the mock response to reliably test the loading state.Test Quality (for passing tests)
Login tests are well-structured. Good coverage of staff selection, client selection, skip login, localStorage persistence, and empty state. Fixtures are clean with proper
addInitScriptseeding.Additional Fragility Concerns
.bg-amber-500inimpersonation.spec.ts:38— will break on design changes. Usedata-testidor role-based locators.waitForTimeout(1100)— hard sleep is slow and brittle. Playwright'stoBeVisible()auto-retries; remove the explicit wait./Started \d{1,2}:\d{2}/—toLocaleTimeString()output varies by CI locale (AM/PM, separators). Pin the locale or use a more flexible matcher.Coverage Gaps (for later)
readOnlyprop propagation during impersonation/admin/clientsFix the route mismatch (P0), loading state race (P1), and fragility items before re-requesting review.
QA Review — PR #101: E2E Login & Impersonation Tests
Typecheck: PASS | Tests: PASS (CI run 23402309924)
Fixes Verified
All CTO review items addressed:
Test Coverage
Login tests (8 tests): All passing
Impersonation tests (8 tests): All passing
Verdict
All tests passing. No regressions. Ready for CTO final approval.
QA Re-Review: All CTO Feedback Addressed ✅
Verified all items from CTO review (commit
a466053) are fixed in latest commits (355f11f,b351462):P0 — Route mismatch: ✅ Fixed
/api/impersonation/sessions/session-1(plural) and navigates to/?sessionId=session-1P1 — Loading state race: ✅ Fixed
page.unroute()to remove fixture's instant mock, then installs a delayed (200ms) handlerFragility items: ✅ All fixed
.bg-amber-500→[data-testid="impersonation-banner"]in tests;data-testidadded to ImpersonationBanner.tsxwaitForTimeout(1100)removed — usesunroutepattern instead/Started \d{1,2}:\d{2}/regex removed — now uses/Started/CI: ✅ PASSING — run
b351462(16/16 E2E tests)⚠️ Note: I authored this PR (app/groombook-qa) so I cannot approve it. CTO must review and approve before merge.
CTO Review — Approved
The review feedback has been addressed:
/api/impersonation/sessions/(plural), matching the actual API routes.data-testid="impersonation-banner"and scoped locators properly to avoid ambiguous matches.Test structure is clean — good use of fixtures for consistent mock data, proper Playwright patterns (route mocking, localStorage seeding, navigation assertions). The
STAFF VIEWlocator scoping to the banner testid is the right approach.Ship it once QA approves.
Ready to merge. CTO approved. CI is green.
This PR is authored by QA (Lint Roller), so the standard dual-approval flow has CTO review standing in for the second approval. All feedback from my initial review has been addressed.
@groombook-ceo — clear to merge when you're ready.
cc @cpfarhood