fix(web): Remove re-throw from loadConversation to prevent unhandled rejections
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed

- Make loadConversation fully self-contained like sendMessage (handle
  errors internally via state, onError callback, and structured logging)
- Remove duplicate try/catch+log from Chat.tsx imperative handle
- Replace re-throw tests with delegation and no-throw tests
- Add hook-level loadConversation error path tests (getIdea rejection)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-06 20:33:52 -06:00
parent f64ca3871d
commit 69cc3f8e1e
4 changed files with 47 additions and 58 deletions

View File

@@ -377,6 +377,44 @@ describe("useChat", () => {
expect(result.current.messages).toHaveLength(1);
expect(result.current.messages[0]?.id).toBe("welcome");
});
it("should set sanitized error and call onError when getIdea rejects", async () => {
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => undefined);
mockGetIdea.mockRejectedValueOnce(new Error("Not found"));
const onError = vi.fn();
const { result } = renderHook(() => useChat({ onError }));
await act(async () => {
await result.current.loadConversation("conv-missing");
});
expect(result.current.error).toBe("Unable to load conversation. Please try again.");
expect(onError).toHaveBeenCalledWith(expect.any(Error));
expect(consoleSpy).toHaveBeenCalledWith(
"Failed to load conversation",
expect.objectContaining({
errorType: "LOAD_ERROR",
ideaId: "conv-missing",
timestamp: expect.any(String) as string,
})
);
expect(result.current.isLoading).toBe(false);
});
it("should not re-throw when getIdea rejects", async () => {
vi.spyOn(console, "error").mockImplementation(() => undefined);
mockGetIdea.mockRejectedValueOnce(new Error("Server error"));
const { result } = renderHook(() => useChat());
// Should resolve without throwing - errors are handled internally
await act(async () => {
await expect(result.current.loadConversation("conv-err")).resolves.toBeUndefined();
});
expect(result.current.error).toBe("Unable to load conversation. Please try again.");
});
});
describe("startNewConversation", () => {

View File

@@ -290,7 +290,6 @@ export function useChat(options: UseChatOptions = {}): UseChatReturn {
ideaId,
timestamp: new Date().toISOString(),
});
throw err;
} finally {
setIsLoading(false);
}