Skip to content
Source
Sign inSign up
Open History to see the last commit

gitPatchPath.test.ts

84 lines3.1 KB

1import { describe, expect, it } from "vite-plus/test";
2​
3import { quoteGitPatchPath, unquoteGitPatchPath } from "./gitPatchPath.ts";
4​
5const BELL = "\u0007";
6const UNIT_SEPARATOR = "\u001f";
7const DELETE = "\u007f";
8​
9describe("quoteGitPatchPath", () => {
10 it("leaves a name a header can carry as itself", () => {
11 expect(quoteGitPatchPath("src/app.ts")).toBe("src/app.ts");
12 expect(quoteGitPatchPath("with space.txt")).toBe("with space.txt");
13 expect(quoteGitPatchPath("café/résumé.ts")).toBe("café/résumé.ts");
14 expect(quoteGitPatchPath("🚀.ts")).toBe("🚀.ts");
15 });
16​
17 it("writes git's escape for a character the header would read as its own", () => {
18 expect(quoteGitPatchPath("tab\tfile.txt")).toBe('"tab\\tfile.txt"');
19 expect(quoteGitPatchPath("line\nfile.txt")).toBe('"line\\nfile.txt"');
20 expect(quoteGitPatchPath('quo"te.txt')).toBe('"quo\\"te.txt"');
21 expect(quoteGitPatchPath("back\\slash.txt")).toBe('"back\\\\slash.txt"');
22 expect(quoteGitPatchPath(`ring${BELL}.txt`)).toBe('"ring\\a.txt"');
23 });
24​
25 it("writes the octal of a control character git has no name for", () => {
26 expect(quoteGitPatchPath(`unit${UNIT_SEPARATOR}.txt`)).toBe('"unit\\037.txt"');
27 expect(quoteGitPatchPath(`del${DELETE}.txt`)).toBe('"del\\177.txt"');
28 });
29});
30​
31describe("a name written into a header and read back out", () => {
32 const names = [
33 "src/app.ts",
34 "with space.txt",
35 "café/résumé.ts",
36 "🚀.ts",
37 "\uFEFFtab\tfile.txt",
38 "tab\tfile.txt",
39 "line\nfile.txt",
40 "carriage\rfile.txt",
41 'quo"te.txt',
42 "back\\slash.txt",
43 `ring${BELL}.txt`,
44 `unit${UNIT_SEPARATOR}.txt`,
45 `del${DELETE}.txt`,
46 `every\t\n\r"\\${BELL}.txt`,
47 ];
48​
49 it.each(names)("is the name that went in: %j", (name) => {
50 const written = quoteGitPatchPath(name);
51 expect(unquoteGitPatchPath(written)).toBe(name);
52 const unwrapped = written.startsWith('"') ? written.slice(1, -1) : written;
53 expect(unquoteGitPatchPath(unwrapped)).toBe(name);
54 });
55});
56​
57describe("unquoteGitPatchPath", () => {
58 it.each(['"\\357\\273\\277note.txt"', "\\357\\273\\277note.txt"])(
59 "preserves an escaped U+FEFF at the start of a filename: %j",
60 (token) => {
61 expect(unquoteGitPatchPath(token)).toBe("\uFEFFnote.txt");
62 },
63 );
64​
65 it("reads the octal escapes a host with core.quotePath on writes", () => {
66 expect(unquoteGitPatchPath('"caf\\303\\251/r\\303\\251sum\\303\\251.ts"')).toBe(
67 "café/résumé.ts",
68 );
69 expect(unquoteGitPatchPath('"\\360\\237\\232\\200.ts"')).toBe("🚀.ts");
70 });
71});
72​
73describe("a name a parser handed back with its quotes already off", () => {
74 it("is read for the escapes it still carries", () => {
75 expect(unquoteGitPatchPath("tab\\tfile.txt")).toBe("tab\tfile.txt");
76 expect(unquoteGitPatchPath("caf\\303\\251.ts")).toBe("café.ts");
77 });
78​
79 it("reads an escape git would never write the way C reads it", () => {
80 expect(unquoteGitPatchPath("odd\\zname.txt")).toBe("oddzname.txt");
81 expect(unquoteGitPatchPath("trailing\\")).toBe("trailing\\");
82 expect(unquoteGitPatchPath("short\\12.txt")).toBe("short12.txt");
83 });
84});