Chat E2E Testing Notes
Goal
Make chat routing and persistence regressions quick to verify without manually signing in, sending real Claude requests, or creating database rows. The Playwright coverage ine2e/tests/chat-routing-and-persistence.spec.ts mocks the chat APIs at the browser boundary. This keeps the tests fast and deterministic while still exercising the real chat page, React Query cache, route updates, and historical-session rendering.
What Was Manually Verified
- Opening
/chatwhile signed in renders the chat page and chat history. - Submitting a new message adds a history row immediately.
- When
/api/claudesendssession_id, the URL changes to/chat/:sessionId. - The assistant response renders in the selected chat.
- Refreshing
/chat/:sessionIdrestores the selected chat instead of showing the new-chat empty state. - The shared history row had invalid nested
<button>markup; this produced a React hydration warning and was fixed by making the row container a keyboard-accessiblerole="button"wrapper. - Chat completion was refetching
/api/chat/sessionsmultiple times; this was reduced to a single React Query invalidation for the chat sessions key.
Automated Coverage
Run the focused tests:- New chat optimistic history row appears before the mocked Claude stream resolves.
- The mocked
session_idevent moves the browser from/chatto/chat/:sessionId. - The assistant response renders after the SSE stream completes.
- Chat sessions are invalidated exactly once after completion.
- Reloading
/chat/:sessionIdrenders the persisted historical prompt and response. - Switching from one chat to another fetches only the selected session detail, preventing the previous current-session refetch pattern.
How The Mock Works
GET /api/chat/sessionsreturns an in-memory session list.GET /api/chat/sessions/:sessionIdreturns in-memory messages.POST /api/claudewaits until the test releases it, then returns a custom SSE payload:
session_id.
Recommended Scenarios To Add Next
- Running historical session:
GET /api/chat/sessions/:idreturnsstatus="running"with partial response, and the chat body shows the generating indicator without falling back to a full skeleton. - Failed session:
status="failed"renders the prompt plus recoverable error copy. - New Chat during active stream: verify the stale stream cannot write into the newly visible session.
- Mobile viewport: submit on a small viewport and verify tab/background-style stream recovery behavior as far as Playwright can simulate.
- Rename/delete: verify mixed
running,completed, andfailedrows still rename/delete all rows for a session.
Manual Smoke Checklist
Use this when validating with a real account and real Claude stream:- Open
/chat. - Submit a short prompt.
- Confirm the history row appears immediately.
- Confirm the URL changes to
/chat/:sessionId. - Refresh that exact URL and confirm the selected chat returns.
- Click a different history row and confirm the page changes to that chat without flashing back to the previous chat or a skeleton.
- Start a chat, click
New Chat, send another prompt, and confirm the sessions do not mix. - Watch the terminal for repeated
/api/chat/sessions/:idor excessive/api/chat/sessionscalls.