import { cleanup, render, screen } from "@testing-library/react"; import { afterEach, describe, expect, it } from "vitest"; import type { RegexExecutionResult, RegexReplacementResult, } from "../regex/model/match"; import { ReplacementPanel } from "./ReplacementPanel"; afterEach(cleanup); const execution: RegexExecutionResult = { accepted: true, engine: { flavour: "ecmascript", adapterVersion: "test", engineName: "Test ECMAScript engine", engineVersion: "test", offsetUnit: "utf16", capabilities: { compilation: true, matching: true, replacement: true, namedCaptures: true, captureHistory: false, actualTrace: false, benchmark: false, }, }, flags: { userFlags: "g", effectiveFlags: "dg", internallyAddedIndicesFlag: true, internallyAddedGlobalFlag: false, }, matches: [], diagnostics: [], elapsedMs: 1, truncated: false, }; function renderResult(result: RegexReplacementResult) { return render( undefined} result={result} onSelectToken={() => undefined} onSelectContribution={() => undefined} />, ); } describe("ReplacementPanel completeness", () => { it("labels a match-limited replacement as partial", () => { renderResult({ execution: { ...execution, truncated: true }, output: "xa", outputBytes: 2, outputTruncated: false, truncated: true, }); expect( screen.getByRole("heading", { name: "Replacement output" }), ).toBeInTheDocument(); expect(screen.queryByText("Complete output")).not.toBeInTheDocument(); expect( screen.getByText(/partial ยท match\/capture limit reached/u), ).toBeInTheDocument(); expect(screen.getByTestId("replacement-match-limit")).toHaveTextContent( "later subject text remains unchanged", ); }); it("distinguishes byte-truncated output from match incompleteness", () => { renderResult({ execution, output: "prefix", outputBytes: 6, outputTruncated: true, truncated: true, }); expect(screen.getByText(/output preview truncated/u)).toBeInTheDocument(); expect( screen.queryByTestId("replacement-match-limit"), ).not.toBeInTheDocument(); }); });