-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathremoteSource.spec.ts
More file actions
128 lines (110 loc) · 4.69 KB
/
remoteSource.spec.ts
File metadata and controls
128 lines (110 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { expect } from "chai";
import * as sinon from "sinon";
import * as fs from "fs";
import * as remoteSourceModule from "./remoteSource";
import { cloneRemoteSource, GitClient } from "./remoteSource";
import { FirebaseError } from "../../error";
describe("remoteSource", () => {
describe("cloneRemoteSource", () => {
let existsSyncStub: sinon.SinonStub;
let isGitAvailableStub: sinon.SinonStub;
let cloneStub: sinon.SinonStub;
let fetchStub: sinon.SinonStub;
let checkoutStub: sinon.SinonStub;
let mockGitClient: GitClient;
beforeEach(() => {
existsSyncStub = sinon.stub(fs, "existsSync");
isGitAvailableStub = sinon.stub(remoteSourceModule, "isGitAvailable");
cloneStub = sinon.stub().returns({ status: 0 });
fetchStub = sinon.stub().returns({ status: 0 });
checkoutStub = sinon.stub().returns({ status: 0 });
mockGitClient = {
clone: cloneStub,
fetch: fetchStub,
checkout: checkoutStub,
} as unknown as GitClient;
});
afterEach(() => {
existsSyncStub.restore();
isGitAvailableStub.restore();
});
it("should handle clone failures with meaningful errors", async () => {
isGitAvailableStub.returns(true);
cloneStub.returns({
status: 1,
stderr: "fatal: unable to access 'https://github.com/org/repo': Could not resolve host",
});
await expect(
cloneRemoteSource("https://github.com/org/repo", "main", undefined, mockGitClient),
).to.be.rejectedWith(FirebaseError, /Unable to access repository/);
});
it("should handle fetch failures for invalid refs", async () => {
isGitAvailableStub.returns(true);
fetchStub.returns({
status: 1,
stderr: "error: pathspec 'bad-ref' did not match any file(s) known to git",
});
await expect(
cloneRemoteSource("https://github.com/org/repo", "bad-ref", undefined, mockGitClient),
).to.be.rejectedWith(FirebaseError, /Git ref 'bad-ref' not found/);
});
it("should validate subdirectory exists after clone", async () => {
isGitAvailableStub.returns(true);
// Simulate that the subdirectory does not exist
existsSyncStub.callsFake((p: fs.PathLike) => {
const s = String(p);
if (/[/\\]subdir$/.test(s)) return false; // dir missing
if (s.endsWith("functions.yaml")) return true; // avoid manifest error masking
return true;
});
await expect(
cloneRemoteSource("https://github.com/org/repo", "main", "subdir", mockGitClient),
).to.be.rejectedWith(FirebaseError, /Directory 'subdir' not found/);
});
it("should validate functions.yaml exists", async () => {
isGitAvailableStub.returns(true);
// Everything exists except the manifest file
existsSyncStub.callsFake((p: fs.PathLike) => !String(p).endsWith("functions.yaml"));
await expect(
cloneRemoteSource("https://github.com/org/repo", "main", undefined, mockGitClient),
).to.be.rejectedWith(FirebaseError, /missing a required deployment manifest/);
});
it("should successfully clone a repository without a subdirectory", async () => {
isGitAvailableStub.returns(true);
// Pass manifest check by returning true for any path ending with functions.yaml
existsSyncStub.callsFake((p: fs.PathLike) => String(p).endsWith("functions.yaml"));
const sourceDir = await cloneRemoteSource(
"https://github.com/org/repo",
"main",
undefined,
mockGitClient,
);
expect(cloneStub.calledOnceWith("https://github.com/org/repo", sinon.match.string)).to.be
.true;
expect(fetchStub.calledOnceWith("main", sinon.match.string)).to.be.true;
expect(checkoutStub.calledOnceWith("FETCH_HEAD", sinon.match.string)).to.be.true;
// No sparse-checkout in MVP path
expect(sourceDir).to.be.a("string");
});
it("should successfully clone a repository with a subdirectory", async () => {
isGitAvailableStub.returns(true);
existsSyncStub.callsFake((p: fs.PathLike) => {
const s = String(p);
if (/[/\\]functions$/.test(s)) return true; // subdir exists
if (s.endsWith("functions.yaml")) return true; // manifest exists
return false;
});
const dir = "functions";
const sourceDir = await cloneRemoteSource(
"https://github.com/org/repo",
"main",
dir,
mockGitClient,
);
expect(fetchStub.calledOnceWith("main", sinon.match.string)).to.be.true;
expect(checkoutStub.calledOnceWith("FETCH_HEAD", sinon.match.string)).to.be.true;
expect(sourceDir).to.be.a("string");
expect(/[/\\]functions$/.test(sourceDir)).to.be.true;
});
});
});