diff --git a/test/ui-components.test.tsx b/test/ui-components.test.tsx index 444f0fc1..732900d1 100644 --- a/test/ui-components.test.tsx +++ b/test/ui-components.test.tsx @@ -121,6 +121,24 @@ function createWrapBootstrap(): AppBootstrap { }; } +function createEmptyDiffFile(type: "rename-pure" | "new" | "deleted"): DiffFile { + return { + id: `empty:${type}`, + path: `${type}.ts`, + patch: "", + language: "typescript", + stats: { + additions: 0, + deletions: 0, + }, + metadata: { + hunks: [], + type, + } as never, + agent: null, + }; +} + async function captureFrame(node: ReactNode, width = 120, height = 24) { const setup = await testRender(node, { width, height }); @@ -486,6 +504,106 @@ describe("UI components", () => { expect(frame).toContain("1 + export const alpha = 2;"); }); + test("PierreDiffView renders stack-mode wrapped continuation rows", async () => { + const file = createWrapBootstrap().changeset.files[0]!; + const theme = resolveTheme("midnight", null); + const frame = await captureFrame( + , + 52, + 18, + ); + + expect(frame).toContain("1 - export const message = 'short';"); + expect(frame).toContain("1 + export const message = 'this is a very l"); + expect(frame).toContain("ong wrapped line for diff rendering cove"); + expect(frame).toContain("rage';"); + }); + + test("PierreDiffView anchors range-less notes to the first visible row when hunk headers are hidden", async () => { + const file = createDiffFile( + "note-fallback", + "note-fallback.ts", + "export const value = 1;\n", + "export const value = 2;\nexport const added = true;\n", + ); + const theme = resolveTheme("midnight", null); + const frame = await captureFrame( + , + 92, + 18, + ); + + expect(frame).not.toContain("@@ -1,1 +1,2 @@"); + expect(frame).toContain("Ungrounded note"); + expect(frame).toContain("Falls back to the first visible row."); + expect(frame).toContain("note-fallback.ts"); + expect(frame).toContain("1 - export const value = 1;"); + }); + + test("PierreDiffView shows contextual messages when there is no selected file or no textual hunks", async () => { + const theme = resolveTheme("midnight", null); + + const noFileFrame = await captureFrame( + , + 76, + 6, + ); + expect(noFileFrame).toContain("No file selected."); + + const renameOnlyFrame = await captureFrame( + , + 76, + 6, + ); + expect(renameOnlyFrame).toContain("This change only renames the file."); + + const newFileFrame = await captureFrame( + , + 76, + 6, + ); + expect(newFileFrame).toContain("The file is marked as new."); + + const deletedFileFrame = await captureFrame( + , + 76, + 6, + ); + expect(deletedFileFrame).toContain("The file is marked as deleted."); + }); + test("PierreDiffView reuses highlighted rows after unmounting and remounting a file section", async () => { const file = createDiffFile( "cache",