Skip to content

Commit 7c42099

Browse files
authored
Refactor git integration tests as unit tests (#104)
1 parent 8bd7229 commit 7c42099

2 files changed

Lines changed: 129 additions & 593 deletions

File tree

tests/git.test.ts

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,38 @@ async function setupGit(cwd: string) {
2929
describe("getFileChanges", () => {
3030
it("should get changes since a specific ref", async () => {
3131
await using fixture = await createFixture({
32-
"foo.txt": "Hello, world!",
32+
".gitignore": ".env\nignored",
33+
"a.txt": "Hello, world!",
34+
"b.txt": "Hello, world!",
3335
});
3436
await setupGit(fixture.path);
3537

36-
await fixture.rm("foo.txt");
37-
await fixture.writeFile("bar.txt", "This is a new file!");
38+
await fixture.writeFile("a.txt", "This is an updated file!");
39+
await fixture.rm("b.txt");
40+
await fixture.writeFile("c.txt", "This is a new file!");
41+
await fixture.mkdir("nested");
42+
await fixture.writeFile("nested/file.txt", "This is a nested file");
43+
await fixture.mkdir("ignored");
44+
await fixture.writeFile("ignored/file.txt", "This file should be ignored");
45+
await fixture.writeFile(".env", "This file should be ignored");
3846

3947
const result = await getFileChanges(fixture.path, fixture.path, "HEAD");
4048
expect(result).toEqual({
4149
additions: [
4250
{
43-
path: "bar.txt",
44-
contents: await fixture.readFile("bar.txt", "base64"),
51+
path: "a.txt",
52+
contents: await fixture.readFile("a.txt", "base64"),
53+
},
54+
{
55+
path: "c.txt",
56+
contents: await fixture.readFile("c.txt", "base64"),
57+
},
58+
{
59+
path: "nested/file.txt",
60+
contents: await fixture.readFile("nested/file.txt", "base64"),
4561
},
4662
],
47-
deletions: [{ path: "foo.txt" }],
63+
deletions: [{ path: "b.txt" }],
4864
});
4965
});
5066

@@ -105,4 +121,111 @@ describe("getFileChanges", () => {
105121
deletions: [{ path: "nested/foo.txt" }],
106122
});
107123
});
124+
125+
it("should allow existing symlinks", async () => {
126+
await using fixture = await createFixture({
127+
"foo.txt": "Hello, world!",
128+
"bar.txt": "Hello, world!",
129+
});
130+
await setupGit(fixture.path);
131+
132+
await fixture.mkdir("some-dir");
133+
await fs.symlink(
134+
fixture.getPath("foo.txt"),
135+
fixture.getPath("some-dir/nested"),
136+
);
137+
await exec("git", ["add", "."], { nodeOptions: { cwd: fixture.path } });
138+
await exec("git", ["commit", "-m", "Add symlink"], {
139+
nodeOptions: { cwd: fixture.path },
140+
});
141+
142+
// Since we committed, HEAD points to the last commit and there's no change since then
143+
const result = await getFileChanges(fixture.path, fixture.path, "HEAD");
144+
expect(result).toEqual({ additions: [], deletions: [] });
145+
146+
await fixture.rm("some-dir/nested");
147+
await fs.symlink(
148+
fixture.getPath("bar.txt"),
149+
fixture.getPath("some-dir/nested"),
150+
);
151+
152+
// We made symlink changes since the last commit, so this should error now
153+
await expect(
154+
getFileChanges(fixture.path, fixture.path, "HEAD"),
155+
).rejects.toThrow(
156+
"Unexpected symlink at some-dir/nested, GitHub API only supports files and directories. You may need to add this file to .gitignore",
157+
);
158+
});
159+
160+
it("should not error when symlink is present but ignored", async () => {
161+
await using fixture = await createFixture({
162+
"foo.txt": "Hello, world!",
163+
});
164+
await setupGit(fixture.path);
165+
166+
await fixture.writeFile(".gitignore", "some-dir");
167+
await exec("git", ["add", "."], { nodeOptions: { cwd: fixture.path } });
168+
await exec("git", ["commit", "-m", "Add gitignore"], {
169+
nodeOptions: { cwd: fixture.path },
170+
});
171+
172+
await fixture.mkdir("some-dir");
173+
await fs.symlink(
174+
fixture.getPath("foo.txt"),
175+
fixture.getPath("some-dir/nested"),
176+
);
177+
178+
const result = await getFileChanges(fixture.path, fixture.path, "HEAD");
179+
expect(result).toEqual({ additions: [], deletions: [] });
180+
});
181+
182+
it("should throw error when symlink is present with non-existent path", async () => {
183+
await using fixture = await createFixture();
184+
await setupGit(fixture.path);
185+
186+
await fixture.mkdir("some-dir");
187+
await fs.symlink(
188+
fixture.getPath("non-existent"),
189+
fixture.getPath("some-dir/nested"),
190+
);
191+
192+
await expect(
193+
getFileChanges(fixture.path, fixture.path, "HEAD"),
194+
).rejects.toThrow(
195+
"Unexpected symlink at some-dir/nested, GitHub API only supports files and directories. You may need to add this file to .gitignore",
196+
);
197+
});
198+
199+
it("should throw error when symlink is present with existing path", async () => {
200+
await using fixture = await createFixture({
201+
"foo.txt": "Hello, world!",
202+
});
203+
await setupGit(fixture.path);
204+
205+
await fixture.mkdir("some-dir");
206+
await fs.symlink(
207+
fixture.getPath("foo.txt"),
208+
fixture.getPath("some-dir/nested"),
209+
);
210+
211+
await expect(
212+
getFileChanges(fixture.path, fixture.path, "HEAD"),
213+
).rejects.toThrow(
214+
"Unexpected symlink at some-dir/nested, GitHub API only supports files and directories. You may need to add this file to .gitignore",
215+
);
216+
});
217+
218+
it("should throw error when executable file is present", async () => {
219+
await using fixture = await createFixture();
220+
await setupGit(fixture.path);
221+
222+
await fixture.writeFile("executable-file.sh", "#!/bin/bash\necho hello");
223+
await fs.chmod(fixture.getPath("executable-file.sh"), 0o755);
224+
225+
await expect(
226+
getFileChanges(fixture.path, fixture.path, "HEAD"),
227+
).rejects.toThrow(
228+
"Unexpected executable file at executable-file.sh, GitHub API only supports non-executable files and directories. You may need to add this file to .gitignore",
229+
);
230+
});
108231
});

0 commit comments

Comments
 (0)