import { act, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { CodeBlock } from "@/components/CodeBlock"; import { ThemeProvider } from "@/hooks/useTheme"; const mockedStyles = vi.hoisted(() => ({ dark: { pre: { background: "#111" } }, light: { pre: { background: "#fff" } }, })); vi.mock("react-syntax-highlighter/dist/esm/prism-async-light", () => ({ default: ({ children, style, }: { children: string; style: Record; }) => (
      {children}
    
), })); vi.mock("react-syntax-highlighter/dist/esm/styles/prism/one-dark", () => ({ default: mockedStyles.dark, })); vi.mock("react-syntax-highlighter/dist/esm/styles/prism/one-light", () => ({ default: mockedStyles.light, })); describe("CodeBlock", () => { it("renders plain code without mounting the highlighter when highlighting is disabled", () => { render( , ); expect(screen.queryByTestId("highlighted-code")).not.toBeInTheDocument(); expect(screen.getByText("const value = 1;")).toBeInTheDocument(); expect(screen.getByText("ts")).toBeInTheDocument(); }); it("reads theme from context without creating per-block observers", async () => { const originalMutationObserver = globalThis.MutationObserver; const observer = vi.fn(); class MockMutationObserver { constructor(callback: MutationCallback) { observer(callback); } observe = vi.fn(); disconnect = vi.fn(); takeRecords() { return []; } } vi.stubGlobal("MutationObserver", MockMutationObserver); try { const { rerender } = render( , ); await act(async () => { await Promise.resolve(); await Promise.resolve(); }); expect(screen.getByTestId("highlighted-code")).toHaveAttribute( "data-theme", "dark", ); rerender( , ); await act(async () => { await Promise.resolve(); }); expect(screen.getByTestId("highlighted-code")).toHaveAttribute( "data-theme", "light", ); expect(observer).not.toHaveBeenCalled(); } finally { vi.stubGlobal("MutationObserver", originalMutationObserver); } }); });