import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { ErrorBoundary } from "./ErrorBoundary.component"; const ThrowError = ({ shouldThrow }: { shouldThrow: boolean }) => { if (shouldThrow) { throw new Error("Test error"); } return
No error
; }; describe("ErrorBoundary", () => { // Suppress console.error for these tests const originalError = console.error; beforeEach(() => { console.error = vi.fn(); }); afterEach(() => { console.error = originalError; }); it("renders children when there is no error", () => { render( Error occurred}> ); expect(screen.getByText("No error")).toBeInTheDocument(); }); it("renders fallback when there is an error", () => { render( Error occurred}> ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); }); it("calls onError when an error occurs", () => { const onError = vi.fn(); render( Error occurred} onError={onError}> ); expect(onError).toHaveBeenCalledWith( expect.any(Error), expect.objectContaining({ componentStack: expect.any(String), }) ); }); it("renders function fallback with error and reset", () => { const fallback = vi.fn((error, reset) => (
Function fallback
)); render( ); expect(screen.getByText("Function fallback")).toBeInTheDocument(); expect(fallback).toHaveBeenCalledWith( expect.any(Error), expect.any(Function) ); }); it("resets when resetKeys change", () => { const onReset = vi.fn(); const { rerender } = render( Error occurred} resetKeys={[1]} onReset={onReset} > ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); rerender( Error occurred} resetKeys={[2]} onReset={onReset} > ); expect(screen.getByText("No error")).toBeInTheDocument(); expect(onReset).toHaveBeenCalled(); }); it("calls onReset when reset function is called", () => { const onReset = vi.fn(); render( ( )} onReset={onReset} > ); const resetButton = screen.getByText("Reset"); fireEvent.click(resetButton); expect(onReset).toHaveBeenCalled(); }); it("actually resets the error boundary when reset is called", () => { const TestComponent = () => { const [shouldThrow, setShouldThrow] = React.useState(true); return ( (
Error: {error.message}
)} >
); }; render(); // Should show error initially expect(screen.getByText("Error: Test error")).toBeInTheDocument(); // Click reset fireEvent.click(screen.getByText("Reset and Fix")); // Should now show the working component expect(screen.getByText("No error")).toBeInTheDocument(); }); it("handles resetKeys array changes correctly", () => { const onReset = vi.fn(); const { rerender } = render( Error occurred} resetKeys={["key1", "key2"]} onReset={onReset} > ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); // Change one key in the array rerender( Error occurred} resetKeys={["key1", "key3"]} onReset={onReset} > ); expect(screen.getByText("No error")).toBeInTheDocument(); expect(onReset).toHaveBeenCalled(); }); it("handles empty resetKeys properly", () => { const onReset = vi.fn(); const { rerender } = render( Error occurred} resetKeys={[]} onReset={onReset} > ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); // Change from empty to populated rerender( Error occurred} resetKeys={["key1"]} onReset={onReset} > ); expect(screen.getByText("No error")).toBeInTheDocument(); expect(onReset).toHaveBeenCalled(); }); it("does not reset when resetKeys array is the same", () => { const onReset = vi.fn(); const { rerender } = render( Error occurred} resetKeys={["key1", "key2"]} onReset={onReset} > ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); // Rerender with same keys rerender( Error occurred} resetKeys={["key1", "key2"]} onReset={onReset} > ); expect(screen.getByText("Error occurred")).toBeInTheDocument(); expect(onReset).not.toHaveBeenCalled(); }); });