import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import posthog from "posthog-js"; import { trackError, showErrorToast, showChatError, } from "#/utils/error-handler"; import * as Actions from "#/services/actions"; import * as CustomToast from "#/utils/custom-toast-handlers"; vi.mock("posthog-js", () => ({ default: { captureException: vi.fn(), }, })); vi.mock("#/services/actions", () => ({ handleStatusMessage: vi.fn(), })); describe("Error Handler", () => { beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.clearAllMocks(); }); describe("trackError", () => { it("should send error to PostHog with basic info", () => { const error = { message: "Test error", source: "test", }; trackError(error); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Test error"), { error_source: "test", }, ); }); it("should include additional metadata in PostHog event", () => { const error = { message: "Test error", source: "test", metadata: { extra: "info", details: { foo: "bar" }, }, }; trackError(error); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Test error"), { error_source: "test", extra: "info", details: { foo: "bar" }, }, ); }); }); describe("showErrorToast", () => { const errorToastSpy = vi.spyOn(CustomToast, "displayErrorToast"); it("should log error and show toast", () => { const error = { message: "Toast error", source: "toast-test", }; showErrorToast(error); // Verify PostHog logging expect(posthog.captureException).toHaveBeenCalledWith( new Error("Toast error"), { error_source: "toast-test", }, ); // Verify toast was shown expect(errorToastSpy).toHaveBeenCalled(); }); it("should include metadata in PostHog event when showing toast", () => { const error = { message: "Toast error", source: "toast-test", metadata: { context: "testing" }, }; showErrorToast(error); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Toast error"), { error_source: "toast-test", context: "testing", }, ); }); it("should log errors from different sources with appropriate metadata", () => { // Test agent status error showErrorToast({ message: "Agent error", source: "agent-status", metadata: { id: "error.agent" }, }); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Agent error"), { error_source: "agent-status", id: "error.agent", }, ); showErrorToast({ message: "Server error", source: "server", metadata: { error_code: 500, details: "Internal error" }, }); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Server error"), { error_source: "server", error_code: 500, details: "Internal error", }, ); }); it("should log feedback submission errors with conversation context", () => { const error = new Error("Feedback submission failed"); showErrorToast({ message: error.message, source: "feedback", metadata: { conversationId: "123", error }, }); expect(posthog.captureException).toHaveBeenCalledWith( new Error("Feedback submission failed"), { error_source: "feedback", conversationId: "123", error, }, ); }); }); describe("showChatError", () => { it("should log error and show chat error message", () => { const error = { message: "Chat error", source: "chat-test", msgId: "123", }; showChatError(error); // Verify PostHog logging expect(posthog.captureException).toHaveBeenCalledWith( new Error("Chat error"), { error_source: "chat-test", }, ); // Verify error message was shown in chat expect(Actions.handleStatusMessage).toHaveBeenCalledWith({ type: "error", message: "Chat error", id: "123", status_update: true, }); }); }); });