diff --git a/frontend/src/components/Chat.test.tsx b/frontend/src/components/Chat.test.tsx index 4cb53be..e98f590 100644 --- a/frontend/src/components/Chat.test.tsx +++ b/frontend/src/components/Chat.test.tsx @@ -529,6 +529,57 @@ describe("Chat localStorage persistence (Story 145)", () => { confirmSpy.mockRestore(); }); + it("Bug 245: messages survive unmount/remount cycle (page refresh)", async () => { + // Step 1: Render Chat and populate messages via WebSocket onUpdate + const { unmount } = render( + , + ); + + await waitFor(() => expect(capturedWsHandlers).not.toBeNull()); + + const history: Message[] = [ + { role: "user", content: "Persist me across refresh" }, + { role: "assistant", content: "I should survive a reload" }, + ]; + + act(() => { + capturedWsHandlers?.onUpdate(history); + }); + + // Verify messages are persisted to localStorage + expect(localStorage.getItem(STORAGE_KEY)).not.toBeNull(); + const storedBefore = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]"); + expect(storedBefore).toEqual(history); + + // Step 2: Unmount the Chat component (simulates page unload) + unmount(); + + // Verify localStorage was NOT cleared by unmount + expect(localStorage.getItem(STORAGE_KEY)).not.toBeNull(); + const storedAfterUnmount = JSON.parse( + localStorage.getItem(STORAGE_KEY) ?? "[]", + ); + expect(storedAfterUnmount).toEqual(history); + + // Step 3: Remount the Chat component (simulates page reload) + capturedWsHandlers = null; + render(); + + // Verify messages are restored from localStorage + expect( + await screen.findByText("Persist me across refresh"), + ).toBeInTheDocument(); + expect( + await screen.findByText("I should survive a reload"), + ).toBeInTheDocument(); + + // Verify localStorage still has the messages + const storedAfterRemount = JSON.parse( + localStorage.getItem(STORAGE_KEY) ?? "[]", + ); + expect(storedAfterRemount).toEqual(history); + }); + it("AC5: uses project-scoped storage key", async () => { const otherKey = "storykit-chat-history:/other/project"; localStorage.setItem(