mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-10-24 05:50:35 +08:00
Code review is the app's core workflow and had almost no coverage. A mutation run checked that each test fails when the logic it covers breaks.
124 lines
3.0 KiB
TypeScript
124 lines
3.0 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
|
|
import { sliceForRange } from "@app/lib/patchSlice";
|
|
|
|
const preamble = [
|
|
"diff --git a/f.txt b/f.txt",
|
|
"index 1111111..2222222 100644",
|
|
"--- a/f.txt",
|
|
"+++ b/f.txt",
|
|
];
|
|
|
|
// Old side: l1..l10 on lines 1-10. New side: l1-l4, L5, L5b, l6-l10 on lines
|
|
// 1-11.
|
|
const hunk = [
|
|
"@@ -1,10 +1,11 @@ fn main",
|
|
" l1",
|
|
" l2",
|
|
" l3",
|
|
" l4",
|
|
"-l5",
|
|
"+L5",
|
|
"+L5b",
|
|
" l6",
|
|
" l7",
|
|
" l8",
|
|
" l9",
|
|
" l10",
|
|
];
|
|
|
|
function patch(...lines: string[]): string {
|
|
return [...preamble, ...lines, ""].join("\n");
|
|
}
|
|
|
|
describe("sliceForRange", () => {
|
|
test("cuts a new-side range down to its context and renumbers the hunk", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 5, 6, 1)).toBe(
|
|
patch("@@ -5,1 +5,2 @@", "-l5", "+L5", "+L5b"),
|
|
);
|
|
});
|
|
|
|
test("keeps three lines of context by default", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 5, 6)).toBe(
|
|
patch(
|
|
"@@ -3,5 +3,6 @@",
|
|
" l3",
|
|
" l4",
|
|
"-l5",
|
|
"+L5",
|
|
"+L5b",
|
|
" l6",
|
|
" l7",
|
|
),
|
|
);
|
|
});
|
|
|
|
test("cuts an old-side range", () => {
|
|
expect(sliceForRange(patch(...hunk), "old", 5, 6, 1)).toBe(
|
|
patch("@@ -4,2 +4,2 @@", " l4", "-l5", "+L5"),
|
|
);
|
|
});
|
|
|
|
test("covers a multi-line range with context on both ends", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 7, 9, 1)).toBe(
|
|
patch("@@ -6,3 +6,4 @@", "+L5b", " l6", " l7", " l8"),
|
|
);
|
|
});
|
|
|
|
test("keeps the hunk verbatim when the window covers all of it", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 5, 6, 20)).toBe(patch(...hunk));
|
|
});
|
|
|
|
test("writes 0 for a side the slice has no lines on", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 5, 7, 0)).toBe(
|
|
patch("@@ -0,0 +5,2 @@", "+L5", "+L5b"),
|
|
);
|
|
});
|
|
|
|
test("returns undefined when no hunk covers the range", () => {
|
|
expect(sliceForRange(patch(...hunk), "new", 50, 51)).toBeUndefined();
|
|
expect(sliceForRange(patch(...hunk), "old", 11, 12)).toBeUndefined();
|
|
});
|
|
|
|
test("uses the hunk that covers the range and keeps the preamble", () => {
|
|
const twoHunks = patch(
|
|
"@@ -1,2 +1,2 @@",
|
|
"-a",
|
|
"+A",
|
|
" b",
|
|
"@@ -20,3 +20,3 @@ fn second",
|
|
" x",
|
|
"-y",
|
|
"+Y",
|
|
" z",
|
|
);
|
|
|
|
expect(sliceForRange(twoHunks, "new", 21, 22, 0)).toBe(
|
|
patch("@@ -0,0 +21,1 @@", "+Y"),
|
|
);
|
|
expect(sliceForRange(twoHunks, "new", 21, 22, 5)).toBe(
|
|
patch("@@ -20,3 +20,3 @@ fn second", " x", "-y", "+Y", " z"),
|
|
);
|
|
});
|
|
|
|
test("reads a hunk header without counts", () => {
|
|
expect(sliceForRange(patch("@@ -3 +3 @@", "-c", "+C"), "new", 3, 4)).toBe(
|
|
patch("@@ -3 +3 @@", "-c", "+C"),
|
|
);
|
|
});
|
|
|
|
test("a no-newline marker doesn't shift the line numbers", () => {
|
|
const noNewline = patch(
|
|
"@@ -1,2 +1,2 @@",
|
|
"-a",
|
|
"\\ No newline at end of file",
|
|
"+A",
|
|
" b",
|
|
);
|
|
|
|
expect(sliceForRange(noNewline, "new", 2, 3, 0)).toBe(
|
|
patch("@@ -2,1 +2,1 @@", " b"),
|
|
);
|
|
});
|
|
});
|