This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / api / rawdiff.test.ts
8.6 kB 353 lines
1import { describe, expect, it } from "vitest"; 2import { LineOp, type NiceDiff } from "./diff"; 3import { renderFormatPatch, renderUnifiedDiff } from "./rawdiff"; 4 5const modifiedFile: NiceDiff = { 6 diff: [ 7 { 8 name: { old: "foo.go", new: "foo.go" }, 9 text_fragments: [ 10 { 11 Comment: "func main()", 12 OldPosition: 1, 13 OldLines: 3, 14 NewPosition: 1, 15 NewLines: 3, 16 Lines: [ 17 { Op: LineOp.Context, Line: "package main\n" }, 18 { Op: LineOp.Delete, Line: "// old comment\n" }, 19 { Op: LineOp.Add, Line: "// new comment\n" }, 20 { Op: LineOp.Context, Line: "func main() {}\n" } 21 ] 22 } 23 ] 24 } 25 ] 26}; 27 28describe("renderUnifiedDiff", () => { 29 it("renders nothing for a missing diff", () => { 30 expect(renderUnifiedDiff(null)).toBe(""); 31 expect(renderUnifiedDiff(undefined)).toBe(""); 32 }); 33 34 it("renders a modified file with the hunk comment", () => { 35 expect(renderUnifiedDiff(modifiedFile)).toBe( 36 "diff --git a/foo.go b/foo.go\n" + 37 "--- a/foo.go\n" + 38 "+++ b/foo.go\n" + 39 "@@ -1,3 +1,3 @@ func main()\n" + 40 " package main\n" + 41 "-// old comment\n" + 42 "+// new comment\n" + 43 " func main() {}\n" 44 ); 45 }); 46 47 it("renders a new file", () => { 48 const got = renderUnifiedDiff({ 49 diff: [ 50 { 51 name: { old: "", new: "new.go" }, 52 is_new: true, 53 text_fragments: [ 54 { 55 OldPosition: 0, 56 OldLines: 0, 57 NewPosition: 1, 58 NewLines: 2, 59 Lines: [ 60 { Op: LineOp.Add, Line: "package main\n" }, 61 { Op: LineOp.Add, Line: "func main() {}\n" } 62 ] 63 } 64 ] 65 } 66 ] 67 }); 68 expect(got).toBe( 69 "diff --git a/new.go b/new.go\n" + 70 "new file mode 100644\n" + 71 "--- /dev/null\n" + 72 "+++ b/new.go\n" + 73 "@@ -0,0 +1,2 @@\n" + 74 "+package main\n" + 75 "+func main() {}\n" 76 ); 77 }); 78 79 it("renders a deleted file", () => { 80 const got = renderUnifiedDiff({ 81 diff: [ 82 { 83 name: { old: "old.go", new: "" }, 84 is_delete: true, 85 text_fragments: [ 86 { 87 OldPosition: 1, 88 OldLines: 2, 89 NewPosition: 0, 90 NewLines: 0, 91 Lines: [ 92 { Op: LineOp.Delete, Line: "package main\n" }, 93 { Op: LineOp.Delete, Line: "func main() {}\n" } 94 ] 95 } 96 ] 97 } 98 ] 99 }); 100 expect(got).toBe( 101 "diff --git a/old.go b/old.go\n" + 102 "deleted file mode 100644\n" + 103 "--- a/old.go\n" + 104 "+++ /dev/null\n" + 105 "@@ -1,2 +0,0 @@\n" + 106 "-package main\n" + 107 "-func main() {}\n" 108 ); 109 }); 110 111 it("renders a renamed file with multiple fragments", () => { 112 const got = renderUnifiedDiff({ 113 diff: [ 114 { 115 name: { old: "old.go", new: "renamed.go" }, 116 is_rename: true, 117 text_fragments: [ 118 { 119 OldPosition: 1, 120 OldLines: 2, 121 NewPosition: 1, 122 NewLines: 2, 123 Lines: [ 124 { Op: LineOp.Context, Line: "package main\n" }, 125 { Op: LineOp.Delete, Line: "func old() {}\n" }, 126 { Op: LineOp.Add, Line: "func renamed() {}\n" } 127 ] 128 }, 129 { 130 Comment: "func init()", 131 OldPosition: 10, 132 OldLines: 1, 133 NewPosition: 10, 134 NewLines: 1, 135 Lines: [{ Op: LineOp.Context, Line: "var x = 1\n" }] 136 } 137 ] 138 } 139 ] 140 }); 141 expect(got).toBe( 142 "diff --git a/old.go b/renamed.go\n" + 143 "rename from old.go\n" + 144 "rename to renamed.go\n" + 145 "--- a/old.go\n" + 146 "+++ b/renamed.go\n" + 147 "@@ -1,2 +1,2 @@\n" + 148 " package main\n" + 149 "-func old() {}\n" + 150 "+func renamed() {}\n" + 151 "@@ -10,1 +10,1 @@ func init()\n" + 152 " var x = 1\n" 153 ); 154 }); 155 156 it("renders multiple files", () => { 157 const file = (name: string, oldLine: string, newLine: string) => ({ 158 name: { old: name, new: name }, 159 text_fragments: [ 160 { 161 OldPosition: 1, 162 OldLines: 1, 163 NewPosition: 1, 164 NewLines: 1, 165 Lines: [ 166 { Op: LineOp.Delete, Line: `${oldLine}\n` }, 167 { Op: LineOp.Add, Line: `${newLine}\n` } 168 ] 169 } 170 ] 171 }); 172 const got = renderUnifiedDiff({ 173 diff: [file("a.go", "old a", "new a"), file("b.go", "old b", "new b")] 174 }); 175 expect(got).toBe( 176 "diff --git a/a.go b/a.go\n" + 177 "--- a/a.go\n" + 178 "+++ b/a.go\n" + 179 "@@ -1,1 +1,1 @@\n" + 180 "-old a\n" + 181 "+new a\n" + 182 "diff --git a/b.go b/b.go\n" + 183 "--- a/b.go\n" + 184 "+++ b/b.go\n" + 185 "@@ -1,1 +1,1 @@\n" + 186 "-old b\n" + 187 "+new b\n" 188 ); 189 }); 190 191 it("marks a missing trailing newline on delete and context lines", () => { 192 const got = renderUnifiedDiff({ 193 diff: [ 194 { 195 name: { old: "foo.go", new: "foo.go" }, 196 text_fragments: [ 197 { 198 OldPosition: 1, 199 OldLines: 2, 200 NewPosition: 1, 201 NewLines: 2, 202 Lines: [ 203 { Op: LineOp.Delete, Line: "old" }, 204 { Op: LineOp.Add, Line: "new\n" }, 205 { Op: LineOp.Context, Line: "tail" } 206 ] 207 } 208 ] 209 } 210 ] 211 }); 212 expect(got).toBe( 213 "diff --git a/foo.go b/foo.go\n" + 214 "--- a/foo.go\n" + 215 "+++ b/foo.go\n" + 216 "@@ -1,2 +1,2 @@\n" + 217 "-old\n" + 218 "\\ No newline at end of file\n" + 219 "+new\n" + 220 " tail\n" + 221 "\\ No newline at end of file\n" 222 ); 223 }); 224}); 225 226describe("renderFormatPatch", () => { 227 it("renders nothing for a missing diff", () => { 228 expect(renderFormatPatch(null)).toBe(""); 229 expect(renderFormatPatch(undefined)).toBe(""); 230 }); 231 232 it("renders the full patch for a rename and a delete", () => { 233 const got = renderFormatPatch({ 234 commit: { 235 hash: [0xab, 0xc1, 0x23, 0x45, 0x67, 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 236 message: "Fix the bug\n\nThis patch resolves the long-standing issue.\n\n\n", 237 author: { Name: "Alice Dev", Email: "alice@example.com", When: "2024-03-15T10:30:00Z" } 238 }, 239 stat: { files_changed: 2, insertions: 1, deletions: 3 }, 240 diff: [ 241 { 242 name: { old: "old.go", new: "renamed.go" }, 243 is_rename: true, 244 text_fragments: [ 245 { 246 OldPosition: 1, 247 OldLines: 2, 248 NewPosition: 1, 249 NewLines: 2, 250 LinesAdded: 1, 251 LinesDeleted: 1, 252 Lines: [ 253 { Op: LineOp.Context, Line: "package main\n" }, 254 { Op: LineOp.Delete, Line: "func old() {}\n" }, 255 { Op: LineOp.Add, Line: "func renamed() {}\n" } 256 ] 257 } 258 ] 259 }, 260 { 261 name: { old: "gone.go", new: "" }, 262 is_delete: true, 263 text_fragments: [ 264 { 265 OldPosition: 1, 266 OldLines: 2, 267 NewPosition: 0, 268 NewLines: 0, 269 LinesAdded: 0, 270 LinesDeleted: 2, 271 Lines: [ 272 { Op: LineOp.Delete, Line: "package main\n" }, 273 { Op: LineOp.Delete, Line: "func main() {}\n" } 274 ] 275 } 276 ] 277 } 278 ] 279 }); 280 expect(got).toBe( 281 "From abc1234567890000000000000000000000000000 Mon Sep 17 00:00:00 2001\n" + 282 "From: Alice Dev <alice@example.com>\n" + 283 "Date: Fri, 15 Mar 2024 10:30:00 +0000\n" + 284 "Subject: [PATCH] Fix the bug\n" + 285 "\n" + 286 "This patch resolves the long-standing issue.\n" + 287 "---\n" + 288 " renamed.go | 2 +-\n" + 289 " gone.go | 2 --\n" + 290 " 2 file(s) changed, 1 insertion(s)(+), 3 deletion(s)(-)\n" + 291 "\n" + 292 "diff --git a/old.go b/renamed.go\n" + 293 "rename from old.go\n" + 294 "rename to renamed.go\n" + 295 "--- a/old.go\n" + 296 "+++ b/renamed.go\n" + 297 "@@ -1,2 +1,2 @@\n" + 298 " package main\n" + 299 "-func old() {}\n" + 300 "+func renamed() {}\n" + 301 "diff --git a/gone.go b/gone.go\n" + 302 "deleted file mode 100644\n" + 303 "--- a/gone.go\n" + 304 "+++ /dev/null\n" + 305 "@@ -1,2 +0,0 @@\n" + 306 "-package main\n" + 307 "-func main() {}\n" + 308 "\n--\ntangled.sh\n" 309 ); 310 }); 311 312 it("omits the body for a single-line message and uses the zero time for a missing When", () => { 313 const got = renderFormatPatch({ 314 commit: { 315 message: "Single line commit", 316 author: { Name: "", Email: "", When: "" } 317 } 318 }); 319 expect(got).toBe( 320 "From Mon Sep 17 00:00:00 2001\n" + 321 "From: <>\n" + 322 "Date: Mon, 01 Jan 0001 00:00:00 +0000\n" + 323 "Subject: [PATCH] Single line commit\n" + 324 "\n" + 325 "---\n" + 326 " 0 file(s) changed, 0 insertion(s)(+), 0 deletion(s)(-)\n" + 327 "\n" + 328 "\n--\ntangled.sh\n" 329 ); 330 }); 331 332 it("uses the zero time for an unparseable When", () => { 333 const got = renderFormatPatch({ 334 commit: { 335 this: "abc123", 336 message: "x", 337 author: { Name: "A", Email: "a@b.c", When: "not a date" } 338 } 339 }); 340 expect(got).toContain("Date: Mon, 01 Jan 0001 00:00:00 +0000\n"); 341 }); 342 343 it("pads the year to four digits", () => { 344 const got = renderFormatPatch({ 345 commit: { 346 this: "abc123", 347 message: "x", 348 author: { Name: "A", Email: "a@b.c", When: "0999-06-15T10:30:00Z" } 349 } 350 }); 351 expect(got).toContain("Date: Sat, 15 Jun 0999 10:30:00 +0000\n"); 352 }); 353});