Skip to content

Commit e90a723

Browse files
committed
feat(diff): add line-level composer actions in diff viewer
1 parent b7aaad3 commit e90a723

10 files changed

Lines changed: 600 additions & 231 deletions

File tree

src/features/design-system/diff/diffViewerTheme.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ export const DIFF_VIEWER_SCROLL_CSS = `
1010
background-image: none !important;
1111
}
1212
13+
[data-hover-slot] {
14+
left: 0 !important;
15+
right: auto !important;
16+
justify-content: flex-start !important;
17+
}
18+
1319
diffs-container,
1420
[data-diffs],
1521
[data-diffs-header],

src/features/git/components/DiffBlock.tsx

Lines changed: 0 additions & 130 deletions
This file was deleted.

src/features/git/components/GitDiffViewer.test.tsx

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @vitest-environment jsdom */
2-
import { render, screen } from "@testing-library/react";
2+
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
33
import type { ReactNode } from "react";
4-
import { beforeAll, describe, expect, it, vi } from "vitest";
4+
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
55
import { GitDiffViewer } from "./GitDiffViewer";
66

77
vi.mock("@tanstack/react-virtual", () => ({
@@ -18,11 +18,41 @@ vi.mock("@tanstack/react-virtual", () => ({
1818
}));
1919

2020
vi.mock("@pierre/diffs", () => ({
21-
parsePatchFiles: () => [],
21+
parsePatchFiles: (diff: string) =>
22+
diff.includes("@@")
23+
? [
24+
{
25+
files: [
26+
{
27+
name: "src/main.ts",
28+
prevName: undefined,
29+
type: "change",
30+
hunks: [],
31+
splitLineCount: 0,
32+
unifiedLineCount: 0,
33+
},
34+
],
35+
},
36+
]
37+
: [],
2238
}));
2339

2440
vi.mock("@pierre/diffs/react", () => ({
25-
FileDiff: () => null,
41+
FileDiff: ({
42+
renderHoverUtility,
43+
}: {
44+
renderHoverUtility?: (
45+
getHoveredLine: () =>
46+
| { lineNumber: number; side?: "additions" | "deletions" }
47+
| undefined,
48+
) => ReactNode;
49+
}) => (
50+
<div>
51+
{renderHoverUtility
52+
? renderHoverUtility(() => ({ lineNumber: 2, side: "additions" }))
53+
: null}
54+
</div>
55+
),
2656
WorkerPoolContextProvider: ({ children }: { children: ReactNode }) => children,
2757
}));
2858

@@ -38,7 +68,42 @@ beforeAll(() => {
3868
ResizeObserverMock;
3969
});
4070

71+
afterEach(() => {
72+
cleanup();
73+
});
74+
4175
describe("GitDiffViewer", () => {
76+
it("inserts a diff line reference into composer when the line '+' action is clicked", () => {
77+
const onInsertComposerText = vi.fn();
78+
79+
render(
80+
<GitDiffViewer
81+
diffs={[
82+
{
83+
path: "src/main.ts@@item-change-1@@change-0",
84+
displayPath: "src/main.ts",
85+
status: "M",
86+
diff: "@@ -1,1 +1,2 @@\n line one\n+added line",
87+
},
88+
]}
89+
selectedPath="src/main.ts@@item-change-1@@change-0"
90+
isLoading={false}
91+
error={null}
92+
diffStyle="unified"
93+
onInsertComposerText={onInsertComposerText}
94+
/>,
95+
);
96+
97+
fireEvent.click(
98+
screen.getByRole("button", { name: "Ask for changes on hovered line" }),
99+
);
100+
101+
expect(onInsertComposerText).toHaveBeenCalledTimes(1);
102+
expect(onInsertComposerText).toHaveBeenCalledWith(
103+
"src/main.ts:L2\n```diff\n+added line\n```\n\n",
104+
);
105+
});
106+
42107
it("renders raw fallback lines instead of Diff unavailable for non-patch diffs", () => {
43108
render(
44109
<GitDiffViewer

0 commit comments

Comments
 (0)