import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { render, screen, cleanup } from "@testing-library/react"; import { ErrorBoundary } from "../ErrorBoundary"; function ThrowingChild(): never { throw new Error("synthetic render-time failure for GRO-2094"); } function GoodChild() { return
ok
; } describe("ErrorBoundary (GRO-2094)", () => { let errorSpy: ReturnType; beforeEach(() => { // React 18+ logs caught render errors to console.error via React's own // instrumentation; suppress it so test output is clean but capture it // for an assertion below. errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); }); afterEach(() => { errorSpy.mockRestore(); cleanup(); }); it("renders children when nothing throws", () => { render( ); expect(screen.getByTestId("good-child")).toBeInTheDocument(); expect(screen.queryByTestId("error-boundary")).not.toBeInTheDocument(); }); it("renders the error visibly when a child throws during render", () => { render( ); const fallback = screen.getByTestId("error-boundary"); expect(fallback).toBeInTheDocument(); const message = screen.getByTestId("error-boundary-message"); // The actual exception is shown — no more silent blank root. expect(message.textContent).toContain("synthetic render-time failure for GRO-2094"); // The boundary also calls console.error so it shows up in the Playwright // console log even if the DOM-rendered fallback is somehow missed. expect(errorSpy).toHaveBeenCalled(); }); });