This repository has no description
1import { processFile, type FileDiffMetadata } from "@pierre/diffs";
2import { describe, expect, it } from "vitest";
3import { LineOp, type DiffFile } from "$lib/api/diff";
4import { renderUnifiedDiff } from "$lib/api/rawdiff";
5import { toFileDiffMetadata } from "./fileDiff";
6
7// the mapper must produce exactly what pierre's own parser
8// produces from the rendered text!
9//
10// excluded: type/prevName, the parser
11// can only get it from git header lines the renderer doesn't emit (mode too),
12// cacheKey, only worker pools use it, and hunkSpecs
13const matchesParsedPatch = (file: DiffFile) => {
14 const parsed = processFile(renderUnifiedDiff({ diff: [file] }));
15 expect(parsed).toBeDefined();
16 const stripKeys = (value: object, keys: string[]): Record<string, unknown> =>
17 Object.fromEntries(Object.entries(value).filter(([key]) => !keys.includes(key)));
18 const strip = (meta: FileDiffMetadata) => ({
19 ...stripKeys(meta, ["type", "prevName", "mode", "cacheKey"]),
20 hunks: meta.hunks.map((hunk) => stripKeys(hunk, ["hunkSpecs"]))
21 });
22 expect(strip(toFileDiffMetadata(file))).toEqual(strip(parsed!));
23};
24
25describe("toFileDiffMetadata", () => {
26 it("maps a modified file", () => {
27 matchesParsedPatch({
28 name: { old: "foo.go", new: "foo.go" },
29 text_fragments: [
30 {
31 Comment: "func main()",
32 OldPosition: 1,
33 OldLines: 3,
34 NewPosition: 1,
35 NewLines: 3,
36 Lines: [
37 { Op: LineOp.Context, Line: "package main\n" },
38 { Op: LineOp.Delete, Line: "// old comment\n" },
39 { Op: LineOp.Add, Line: "// new comment\n" },
40 { Op: LineOp.Context, Line: "func main() {}\n" }
41 ]
42 }
43 ]
44 });
45 });
46
47 it("maps a new file", () => {
48 matchesParsedPatch({
49 name: { old: "", new: "new.go" },
50 is_new: true,
51 text_fragments: [
52 {
53 OldPosition: 0,
54 OldLines: 0,
55 NewPosition: 1,
56 NewLines: 2,
57 Lines: [
58 { Op: LineOp.Add, Line: "package main\n" },
59 { Op: LineOp.Add, Line: "func main() {}\n" }
60 ]
61 }
62 ]
63 });
64 });
65
66 it("maps a deleted file", () => {
67 matchesParsedPatch({
68 name: { old: "old.go", new: "" },
69 is_delete: true,
70 text_fragments: [
71 {
72 OldPosition: 1,
73 OldLines: 2,
74 NewPosition: 0,
75 NewLines: 0,
76 Lines: [
77 { Op: LineOp.Delete, Line: "package main\n" },
78 { Op: LineOp.Delete, Line: "func main() {}\n" }
79 ]
80 }
81 ]
82 });
83 });
84
85 it("maps a renamed file with multiple fragments", () => {
86 matchesParsedPatch({
87 name: { old: "old.go", new: "renamed.go" },
88 is_rename: true,
89 text_fragments: [
90 {
91 OldPosition: 1,
92 OldLines: 2,
93 NewPosition: 1,
94 NewLines: 2,
95 Lines: [
96 { Op: LineOp.Context, Line: "package main\n" },
97 { Op: LineOp.Delete, Line: "func old() {}\n" },
98 { Op: LineOp.Add, Line: "func renamed() {}\n" }
99 ]
100 },
101 {
102 Comment: "func init()",
103 OldPosition: 10,
104 OldLines: 1,
105 NewPosition: 10,
106 NewLines: 1,
107 Lines: [{ Op: LineOp.Context, Line: "var x = 1\n" }]
108 }
109 ]
110 });
111 });
112
113 it("maps a missing trailing newline", () => {
114 matchesParsedPatch({
115 name: { old: "foo.go", new: "foo.go" },
116 text_fragments: [
117 {
118 OldPosition: 1,
119 OldLines: 2,
120 NewPosition: 1,
121 NewLines: 2,
122 Lines: [
123 { Op: LineOp.Delete, Line: "old" },
124 { Op: LineOp.Add, Line: "new\n" },
125 { Op: LineOp.Context, Line: "tail" }
126 ]
127 }
128 ]
129 });
130 });
131
132 it("marks the file type from the wire flags", () => {
133 expect(toFileDiffMetadata({ name: { old: "", new: "n.go" }, is_new: true }).type).toBe("new");
134 expect(toFileDiffMetadata({ name: { old: "o.go", new: "" }, is_delete: true }).type).toBe(
135 "deleted"
136 );
137 const renamed = toFileDiffMetadata({ name: { old: "o.go", new: "n.go" }, is_rename: true });
138 expect(renamed.type).toBe("rename-changed");
139 expect(renamed.prevName).toBe("o.go");
140 expect(toFileDiffMetadata({ name: { old: "n.go", new: "n.go" } }).prevName).toBeUndefined();
141 });
142});