Skip to content

Commit 54df576

Browse files
authored
test: cover diff pane windowing integration (#72)
1 parent e3cc2f7 commit 54df576

1 file changed

Lines changed: 159 additions & 0 deletions

File tree

test/ui-components.test.tsx

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,95 @@ function createDiffFile(
7878
};
7979
}
8080

81+
function lines(...values: string[]) {
82+
return `${values.join("\n")}\n`;
83+
}
84+
85+
function createWindowingFiles(count: number) {
86+
return Array.from({ length: count }, (_, index) =>
87+
createDiffFile(
88+
`window-${index + 1}`,
89+
`window-${index + 1}.ts`,
90+
lines(`export const file${index + 1} = ${index + 1};`),
91+
lines(
92+
`export const file${index + 1} = ${index + 10};`,
93+
`export const file${index + 1}Extra = true;`,
94+
),
95+
),
96+
);
97+
}
98+
99+
function createMultiHunkDiffFile(id: string, path: string) {
100+
const before = lines(
101+
"export const line1 = 1;",
102+
"export const line2 = 2;",
103+
"export const line3 = 3;",
104+
"export const line4 = 4;",
105+
"export const line5 = 5;",
106+
"export const line6 = 6;",
107+
"export const line7 = 7;",
108+
"export const line8 = 8;",
109+
"export const line9 = 9;",
110+
"export const line10 = 10;",
111+
"export const line11 = 11;",
112+
"export const line12 = 12;",
113+
);
114+
const after = lines(
115+
"export const line1 = 1;",
116+
"export const line2 = 200;",
117+
"export const line3 = 3;",
118+
"export const line4 = 4;",
119+
"export const line5 = 5;",
120+
"export const line6 = 6;",
121+
"export const line7 = 7;",
122+
"export const line8 = 8;",
123+
"export const line9 = 9;",
124+
"export const line10 = 10;",
125+
"export const line11 = 1100;",
126+
"export const line12 = 12;",
127+
);
128+
129+
return createDiffFile(id, path, before, after);
130+
}
131+
132+
function createDiffPaneProps(
133+
files: DiffFile[],
134+
theme = resolveTheme("midnight", null),
135+
overrides: Partial<Parameters<typeof DiffPane>[0]> = {},
136+
) {
137+
return {
138+
activeAnnotations: [],
139+
diffContentWidth: 72,
140+
dismissedAgentNoteIds: [],
141+
files,
142+
headerLabelWidth: 40,
143+
headerStatsWidth: 16,
144+
layout: "split" as const,
145+
scrollRef: createRef(),
146+
selectedFileId: files[0]?.id,
147+
selectedHunkIndex: 0,
148+
separatorWidth: 68,
149+
showAgentNotes: false,
150+
showLineNumbers: true,
151+
showHunkHeaders: true,
152+
wrapLines: false,
153+
theme,
154+
width: 76,
155+
onDismissAgentNote: () => {},
156+
onOpenAgentNotesAtHunk: () => {},
157+
onSelectFile: () => {},
158+
...overrides,
159+
};
160+
}
161+
162+
function settleDiffPane(setup: Awaited<ReturnType<typeof testRender>>) {
163+
return act(async () => {
164+
await setup.renderOnce();
165+
await Bun.sleep(100);
166+
await setup.renderOnce();
167+
});
168+
}
169+
81170
function createBootstrap(): AppBootstrap {
82171
return {
83172
input: {
@@ -256,6 +345,76 @@ describe("UI components", () => {
256345
expect(frame.indexOf("alpha.ts")).toBeLessThan(frame.indexOf("beta.ts"));
257346
});
258347

348+
test("DiffPane scrolls a later selected file into view in the windowed path", async () => {
349+
const files = createWindowingFiles(6);
350+
const theme = resolveTheme("midnight", null);
351+
const props = createDiffPaneProps(files, theme, {
352+
diffContentWidth: 88,
353+
selectedFileId: files[5]?.id,
354+
separatorWidth: 84,
355+
width: 92,
356+
});
357+
const setup = await testRender(<DiffPane {...props} />, {
358+
width: 96,
359+
height: 12,
360+
});
361+
362+
try {
363+
await settleDiffPane(setup);
364+
const frame = setup.captureCharFrame();
365+
366+
expect(frame).toContain("window-6.ts");
367+
expect(frame).toContain("export const file6Extra = true;");
368+
expect(frame).not.toContain("window-1.ts");
369+
} finally {
370+
await act(async () => {
371+
setup.renderer.destroy();
372+
});
373+
}
374+
});
375+
376+
test("DiffPane scrolls to the selected later hunk when hunk headers are hidden", async () => {
377+
const theme = resolveTheme("midnight", null);
378+
const files = [
379+
createDiffFile(
380+
"intro",
381+
"intro.ts",
382+
lines("export const intro = 1;"),
383+
lines("export const intro = 2;", "export const introExtra = true;"),
384+
),
385+
createMultiHunkDiffFile("target", "target.ts"),
386+
];
387+
const props = createDiffPaneProps(files, theme, {
388+
diffContentWidth: 96,
389+
headerLabelWidth: 48,
390+
selectedFileId: "target",
391+
selectedHunkIndex: 1,
392+
separatorWidth: 92,
393+
showHunkHeaders: false,
394+
width: 100,
395+
});
396+
const setup = await testRender(<DiffPane {...props} />, {
397+
width: 104,
398+
height: 12,
399+
});
400+
401+
try {
402+
await settleDiffPane(setup);
403+
const frame = setup.captureCharFrame();
404+
405+
expect(frame).toContain("11 - export const line11 = 11;");
406+
expect(frame).toContain("11 + export const line11 = 1100;");
407+
expect(frame).not.toContain("2 - export const line2 = 2;");
408+
expect(frame).not.toContain("2 + export const line2 = 200;");
409+
expect(frame).not.toContain("intro.ts");
410+
expect(frame).not.toContain("@@ -1,3 +1,3 @@");
411+
} finally {
412+
await act(async () => {
413+
setup.renderer.destroy();
414+
});
415+
}
416+
});
417+
259418
test("AgentCard removes top and bottom padding while keeping the footer inside the frame", async () => {
260419
const theme = resolveTheme("midnight", null);
261420
const frame = await captureFrame(

0 commit comments

Comments
 (0)