# QA: Accept invite screen ## Automated (Vitest + Vue Test Utils, `task test:web`) Mock `useApi` for GET `/v1/auth/invite` and POST `/v1/auth/invite/accept` per case; mount AcceptInvitePage inside AuthShell with a test router at `/invite/accept?c=abc123`. Use fake timers for the 800 ms redirect only; never freeze the date. 1. Checking the link: GET unresolved -> "Checking your invite…" spinner. 2. Default: GET 200 `{email:"lea.martin@renew.example"}` -> heading, description, read-only Email with help, Username "0 / 20" and its help, Password checklist unmet, button "Accept invite", footer "Log in" -> /login. 3. Validation errors: Username "ma", Password "lime", blur + submit -> no POST, "Use 3 to 20 characters.", counter "2 / 20" error, checklist error. 4. Filled, valid: "lea" / "limewash2026" shown -> "3 / 20", checklist met. 5. Submitting: POST unresolved -> fields disabled, "Creating account…" loading. 6. Username taken: POST 409 body "That username is taken. Try another." -> value "marta" kept, "5 / 20", focus on Username, error copy, password kept, form re-enabled. 7. Link does not work (table): no `c` (no request at all), GET 404, POST 404, POST 409 with `This address already has an account.` -> ResultPanel link-2-off with the title, text, note and one primary "Go to log in"; click navigates to /login. 8. Expired (table): GET 410, POST 410 -> ResultPanel clock, title, text, one secondary "Go to log in". 9. Server error (table): POST 500, POST 429, rejected fetch -> Alert "Couldn't create the account" + description, form kept. 10. Success: POST 200 -> ResultPanel "Your account is ready", Toast "Welcome to RenewCMS" / "You're logged in as lea."; advance 800 ms -> router path is /home. 11. Logged-in visitor: session store holds a verified user; mounting shows the Default state, no redirect. ## Open questions (no design state, not invented) - GET /v1/auth/invite failing on load with a 500 or a network error: the design has no state for it. ## Visual (`task visual:check -- accept-invite`, desktop and mobile, light and dark; hard gate 10 %) Sample data from the board frame: email `lea.martin@renew.example`; username `lea` (taken state: `marta`); password `limewash2026`; validation state username `ma`, password `lime`. States: Checking the link, Default, Validation errors, Filled valid, Submitting, Username taken (409), Invalid or used link (404), Expired link (410), Server error, Success. `skip: clock-sensitive`: none (expiry is driven by the 410 status, not the clock). Layout placement comes from the board frame markup, not from components.md prose. ## Manual checks (not covered by screenshots) - Keyboard: Tab order Username -> Password -> show/hide -> Accept invite -> Log in; Username is focused after a 409; the ResultPanel title takes focus on 404/410. - Password show/hide and hover states; the 800 ms hand-off; the Toast disappearing. - Real e2e: open the emailed link against `task dev`.