diff --git a/frontend/src/components/Chat.test.tsx b/frontend/src/components/Chat.test.tsx index 665be372..d77a61ec 100644 --- a/frontend/src/components/Chat.test.tsx +++ b/frontend/src/components/Chat.test.tsx @@ -1691,3 +1691,40 @@ describe("Slash command handling (Story 374)", () => { ).toBeInTheDocument(); }); }); + +describe("Bug 450: WebSocket error messages displayed in chat", () => { + beforeEach(() => { + capturedWsHandlers = null; + setupMocks(); + }); + + it("AC1: WebSocket error message is shown in chat as an assistant message", async () => { + render(); + + await waitFor(() => expect(capturedWsHandlers).not.toBeNull()); + + act(() => { + capturedWsHandlers?.onError("Something went wrong on the server."); + }); + + expect( + await screen.findByText("Something went wrong on the server."), + ).toBeInTheDocument(); + }); + + it("AC2: OAuth login URL in WebSocket error is rendered as a clickable link", async () => { + render(); + + await waitFor(() => expect(capturedWsHandlers).not.toBeNull()); + + act(() => { + capturedWsHandlers?.onError( + "OAuth login required. Please visit: https://example.com/oauth/login", + ); + }); + + const link = await screen.findByRole("link", { name: /https:\/\/example\.com\/oauth\/login/ }); + expect(link).toBeInTheDocument(); + expect(link).toHaveAttribute("href", "https://example.com/oauth/login"); + }); +}); diff --git a/frontend/src/components/Chat.tsx b/frontend/src/components/Chat.tsx index bad98dc3..3ac5e812 100644 --- a/frontend/src/components/Chat.tsx +++ b/frontend/src/components/Chat.tsx @@ -413,6 +413,14 @@ export function Chat({ console.error("WebSocket error:", message); setLoading(false); setActivityStatus(null); + const markdownMessage = message.replace( + /(https?:\/\/[^\s]+)/g, + "[$1]($1)", + ); + setMessages((prev) => [ + ...prev, + { role: "assistant", content: markdownMessage }, + ]); if (queuedMessagesRef.current.length > 0) { const batch = queuedMessagesRef.current.map((item) => item.text); queuedMessagesRef.current = [];