import { act, render, screen } from "@testing-library/react"; import type { ReactNode } from "react"; import { describe, expect, it, vi } from "vitest"; import { DiffSyntaxHighlight } from "@/components/thread/activity/DiffSyntaxHighlight"; import { ThemeProvider } from "@/hooks/useTheme"; vi.mock("react-syntax-highlighter/dist/esm/prism-async-light", () => { const MockSyntaxHighlighter = ({ children, language, renderer, ...props }: { children: string; language: string; renderer: (args: { rows: Array<{ type: "element"; tagName: "span"; properties: { className: string[] }; children: Array<{ type: "text"; value: string }>; }>; stylesheet: Record; useInlineStyles: boolean; }) => ReactNode; [key: string]: unknown; }) => (
{renderer({ rows: children.split("\n").map((line) => ({ type: "element" as const, tagName: "span" as const, properties: { className: ["token", "keyword"] }, children: [{ type: "text" as const, value: `${line}\n` }], })), stylesheet: {}, useInlineStyles: true, })}
); return { default: MockSyntaxHighlighter }; }); vi.mock("react-syntax-highlighter/dist/esm/create-element", () => ({ default: ({ node }: { node: { children?: Array<{ value?: string }> } }) => ( {node.children?.[0]?.value} ), })); vi.mock("react-syntax-highlighter/dist/esm/styles/prism/one-dark", () => ({ default: { dark: { color: "#fff" } }, })); vi.mock("react-syntax-highlighter/dist/esm/styles/prism/one-light", () => ({ default: { light: { color: "#111" } }, })); describe("DiffSyntaxHighlight", () => { it("highlights a complete hunk while preserving diff rows and line numbers", async () => { render( , ); await act(async () => { await Promise.resolve(); await Promise.resolve(); await Promise.resolve(); }); const highlighted = await screen.findByTestId("syntax-highlighted-diff-hunk"); expect(highlighted).toHaveAttribute("data-language", "typescript"); expect(screen.getAllByTestId("syntax-token")).toHaveLength(3); expect(screen.getByText("return oldValue;", { exact: false }).closest("tr")).toHaveClass( "bg-rose-500/[0.09]", ); expect(screen.getByText("return newValue;", { exact: false }).closest("tr")).toHaveClass( "bg-emerald-500/[0.09]", ); expect(screen.getAllByText("5")).toHaveLength(2); expect(screen.getAllByTestId("syntax-token").some((node) => node.textContent?.endsWith("\n"))).toBe(false); }); });