@openally/github.sdk 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/rawFile.d.ts +20 -0
- package/dist/api/rawFile.d.ts.map +1 -0
- package/dist/api/rawFile.js +25 -0
- package/dist/api/rawFile.js.map +1 -0
- package/dist/api/repos.d.ts +21 -0
- package/dist/api/repos.d.ts.map +1 -0
- package/dist/api/repos.js +32 -0
- package/dist/api/repos.js.map +1 -0
- package/dist/api/users.d.ts +21 -0
- package/dist/api/users.d.ts.map +1 -0
- package/dist/api/users.js +20 -0
- package/dist/api/users.js.map +1 -0
- package/dist/class/ApiEndpoint.d.ts +20 -0
- package/dist/class/ApiEndpoint.d.ts.map +1 -0
- package/dist/class/ApiEndpoint.js +60 -0
- package/dist/class/ApiEndpoint.js.map +1 -0
- package/dist/class/GithubClient.d.ts +22 -0
- package/dist/class/GithubClient.d.ts.map +1 -0
- package/dist/class/GithubClient.js +21 -0
- package/dist/class/GithubClient.js.map +1 -0
- package/dist/class/HttpLinkParser.d.ts +4 -0
- package/dist/class/HttpLinkParser.d.ts.map +1 -0
- package/dist/class/HttpLinkParser.js +14 -0
- package/dist/class/HttpLinkParser.js.map +1 -0
- package/dist/class/createApiProxy.d.ts +2 -0
- package/dist/class/createApiProxy.d.ts.map +1 -0
- package/dist/class/createApiProxy.js +8 -0
- package/dist/class/createApiProxy.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -0
- package/{src/constants.ts → dist/constants.js} +1 -0
- package/dist/constants.js.map +1 -0
- package/{src/index.ts → dist/index.d.ts} +2 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/{src/types.ts → dist/types.d.ts} +14 -27
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +5 -2
- package/.all-contributorsrc +0 -16
- package/.editorconfig +0 -14
- package/.github/dependabot.yml +0 -25
- package/.github/workflows/codeql.yml +0 -78
- package/.github/workflows/node.js.yml +0 -52
- package/.github/workflows/publish.yml +0 -29
- package/.github/workflows/scorecards.yml +0 -76
- package/SECURITY.md +0 -5
- package/docs/api/ApiEndpoint.md +0 -66
- package/docs/api/GithubClient.md +0 -50
- package/docs/api/fetchRawFile.md +0 -106
- package/docs/api/repos.md +0 -97
- package/docs/api/users.md +0 -76
- package/eslint.config.mjs +0 -3
- package/src/api/rawFile.ts +0 -73
- package/src/api/repos.ts +0 -88
- package/src/api/users.ts +0 -51
- package/src/class/ApiEndpoint.ts +0 -108
- package/src/class/GithubClient.ts +0 -62
- package/src/class/HttpLinkParser.ts +0 -17
- package/src/class/createApiProxy.ts +0 -9
- package/test/ApiEndpoint.spec.ts +0 -362
- package/test/GithubClient.spec.ts +0 -185
- package/test/HttpLinkParser.spec.ts +0 -78
- package/test/createApiProxy.spec.ts +0 -58
- package/test/rawFile.spec.ts +0 -382
- package/test/repos.spec.ts +0 -221
- package/test/tsconfig.json +0 -11
- package/test/users.spec.ts +0 -159
- package/tsconfig.json +0 -11
package/test/ApiEndpoint.spec.ts
DELETED
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
// Import Node.js Dependencies
|
|
2
|
-
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
3
|
-
import assert from "node:assert/strict";
|
|
4
|
-
|
|
5
|
-
// Import Third-party Dependencies
|
|
6
|
-
import { MockAgent, setGlobalDispatcher, getGlobalDispatcher, type Dispatcher } from "undici";
|
|
7
|
-
|
|
8
|
-
// Import Internal Dependencies
|
|
9
|
-
import { ApiEndpoint } from "../src/class/ApiEndpoint.ts";
|
|
10
|
-
|
|
11
|
-
// CONSTANTS
|
|
12
|
-
const kGithubOrigin = "https://api.github.com";
|
|
13
|
-
|
|
14
|
-
describe("ApiEndpoint", () => {
|
|
15
|
-
let mockAgent: MockAgent;
|
|
16
|
-
let originalDispatcher: Dispatcher;
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
originalDispatcher = getGlobalDispatcher();
|
|
20
|
-
mockAgent = new MockAgent();
|
|
21
|
-
mockAgent.disableNetConnect();
|
|
22
|
-
setGlobalDispatcher(mockAgent);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(async() => {
|
|
26
|
-
await mockAgent.close();
|
|
27
|
-
setGlobalDispatcher(originalDispatcher);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("constructor", () => {
|
|
31
|
-
it("should accept a string endpoint", () => {
|
|
32
|
-
const endpoint = new ApiEndpoint("/users/foo/repos");
|
|
33
|
-
|
|
34
|
-
assert.ok(endpoint instanceof ApiEndpoint);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("should accept a URL endpoint", () => {
|
|
38
|
-
const endpoint = new ApiEndpoint(new URL("https://api.github.com/users/foo/repos"));
|
|
39
|
-
|
|
40
|
-
assert.ok(endpoint instanceof ApiEndpoint);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe("setBearerToken()", () => {
|
|
45
|
-
it("should return this for chaining", () => {
|
|
46
|
-
const endpoint = new ApiEndpoint("/users/foo/repos");
|
|
47
|
-
|
|
48
|
-
assert.strictEqual(endpoint.setBearerToken("mytoken"), endpoint);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("setAgent()", () => {
|
|
53
|
-
it("should return this for chaining", () => {
|
|
54
|
-
const endpoint = new ApiEndpoint("/users/foo/repos");
|
|
55
|
-
|
|
56
|
-
assert.strictEqual(endpoint.setAgent("my-agent/1.0"), endpoint);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe("all()", () => {
|
|
61
|
-
it("should fetch a single page and return all items", async() => {
|
|
62
|
-
mockAgent
|
|
63
|
-
.get(kGithubOrigin)
|
|
64
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
65
|
-
.reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
|
|
66
|
-
headers: { "content-type": "application/json" }
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const result = await new ApiEndpoint("/users/foo/repos").all();
|
|
70
|
-
|
|
71
|
-
assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("should return an empty array when the response is empty", async() => {
|
|
75
|
-
mockAgent
|
|
76
|
-
.get(kGithubOrigin)
|
|
77
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
78
|
-
.reply(200, JSON.stringify([]), {
|
|
79
|
-
headers: { "content-type": "application/json" }
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const result = await new ApiEndpoint("/users/foo/repos").all();
|
|
83
|
-
|
|
84
|
-
assert.deepEqual(result, []);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("should follow pagination using the link header", async() => {
|
|
88
|
-
const pool = mockAgent.get(kGithubOrigin);
|
|
89
|
-
|
|
90
|
-
pool
|
|
91
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
92
|
-
.reply(200, JSON.stringify([{ id: 1 }]), {
|
|
93
|
-
headers: {
|
|
94
|
-
"content-type": "application/json",
|
|
95
|
-
link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
pool
|
|
100
|
-
.intercept({ path: "/users/foo/repos?page=2", method: "GET" })
|
|
101
|
-
.reply(200, JSON.stringify([{ id: 2 }]), {
|
|
102
|
-
headers: { "content-type": "application/json" }
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const result = await new ApiEndpoint("/users/foo/repos").all();
|
|
106
|
-
|
|
107
|
-
assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("should follow multiple pages until no next link", async() => {
|
|
111
|
-
const pool = mockAgent.get(kGithubOrigin);
|
|
112
|
-
|
|
113
|
-
pool
|
|
114
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
115
|
-
.reply(200, JSON.stringify([{ id: 1 }]), {
|
|
116
|
-
headers: {
|
|
117
|
-
"content-type": "application/json",
|
|
118
|
-
link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
pool
|
|
123
|
-
.intercept({ path: "/users/foo/repos?page=2", method: "GET" })
|
|
124
|
-
.reply(200, JSON.stringify([{ id: 2 }]), {
|
|
125
|
-
headers: {
|
|
126
|
-
"content-type": "application/json",
|
|
127
|
-
link: '<https://api.github.com/users/foo/repos?page=3>; rel="next"'
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
pool
|
|
132
|
-
.intercept({ path: "/users/foo/repos?page=3", method: "GET" })
|
|
133
|
-
.reply(200, JSON.stringify([{ id: 3 }]), {
|
|
134
|
-
headers: { "content-type": "application/json" }
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const result = await new ApiEndpoint("/users/foo/repos").all();
|
|
138
|
-
|
|
139
|
-
assert.deepEqual(result, [{ id: 1 }, { id: 2 }, { id: 3 }]);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe("all() with thenable", () => {
|
|
144
|
-
it("should fetch a single page and return all items", async() => {
|
|
145
|
-
mockAgent
|
|
146
|
-
.get(kGithubOrigin)
|
|
147
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
148
|
-
.reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
|
|
149
|
-
headers: { "content-type": "application/json" }
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const result = await new ApiEndpoint("/users/foo/repos");
|
|
153
|
-
|
|
154
|
-
assert.deepEqual(result, [{ id: 1 }, { id: 2 }]);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe("iterate()", () => {
|
|
159
|
-
it("should yield items one at a time", async() => {
|
|
160
|
-
mockAgent
|
|
161
|
-
.get(kGithubOrigin)
|
|
162
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
163
|
-
.reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
|
|
164
|
-
headers: { "content-type": "application/json" }
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
const items: unknown[] = [];
|
|
168
|
-
for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
|
|
169
|
-
items.push(item);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
assert.deepEqual(items, [{ id: 1 }, { id: 2 }]);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("should yield items across paginated pages", async() => {
|
|
176
|
-
const pool = mockAgent.get(kGithubOrigin);
|
|
177
|
-
|
|
178
|
-
pool
|
|
179
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
180
|
-
.reply(200, JSON.stringify([{ id: 1 }]), {
|
|
181
|
-
headers: {
|
|
182
|
-
"content-type": "application/json",
|
|
183
|
-
link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
pool
|
|
188
|
-
.intercept({ path: "/users/foo/repos?page=2", method: "GET" })
|
|
189
|
-
.reply(200, JSON.stringify([{ id: 2 }, { id: 3 }]), {
|
|
190
|
-
headers: { "content-type": "application/json" }
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const items: unknown[] = [];
|
|
194
|
-
for await (const item of new ApiEndpoint("/users/foo/repos").iterate()) {
|
|
195
|
-
items.push(item);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
assert.deepEqual(items, [{ id: 1 }, { id: 2 }, { id: 3 }]);
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
describe("Symbol.asyncIterator", () => {
|
|
203
|
-
it("should yield items one at a time", async() => {
|
|
204
|
-
mockAgent
|
|
205
|
-
.get(kGithubOrigin)
|
|
206
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
207
|
-
.reply(200, JSON.stringify([{ id: 1 }, { id: 2 }]), {
|
|
208
|
-
headers: { "content-type": "application/json" }
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
const items: unknown[] = [];
|
|
212
|
-
for await (const item of new ApiEndpoint("/users/foo/repos")) {
|
|
213
|
-
items.push(item);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
assert.deepEqual(items, [{ id: 1 }, { id: 2 }]);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("should yield items across paginated pages", async() => {
|
|
220
|
-
const pool = mockAgent.get(kGithubOrigin);
|
|
221
|
-
|
|
222
|
-
pool
|
|
223
|
-
.intercept({ path: "/users/foo/repos", method: "GET" })
|
|
224
|
-
.reply(200, JSON.stringify([{ id: 1 }]), {
|
|
225
|
-
headers: {
|
|
226
|
-
"content-type": "application/json",
|
|
227
|
-
link: '<https://api.github.com/users/foo/repos?page=2>; rel="next"'
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
pool
|
|
232
|
-
.intercept({ path: "/users/foo/repos?page=2", method: "GET" })
|
|
233
|
-
.reply(200, JSON.stringify([{ id: 2 }, { id: 3 }]), {
|
|
234
|
-
headers: { "content-type": "application/json" }
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
const items: unknown[] = [];
|
|
238
|
-
for await (const item of new ApiEndpoint("/users/foo/repos")) {
|
|
239
|
-
items.push(item);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
assert.deepEqual(items, [{ id: 1 }, { id: 2 }, { id: 3 }]);
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
describe("headers", () => {
|
|
247
|
-
it("should send the default User-Agent header", async() => {
|
|
248
|
-
mockAgent
|
|
249
|
-
.get(kGithubOrigin)
|
|
250
|
-
.intercept({
|
|
251
|
-
path: "/users/foo/repos",
|
|
252
|
-
method: "GET",
|
|
253
|
-
headers: { "user-agent": "@openally/github.sdk/1.0.0" }
|
|
254
|
-
})
|
|
255
|
-
.reply(200, JSON.stringify([]), {
|
|
256
|
-
headers: { "content-type": "application/json" }
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
// If header doesn't match, undici will throw — this is the assertion
|
|
260
|
-
await assert.doesNotReject(
|
|
261
|
-
new ApiEndpoint("/users/foo/repos").all()
|
|
262
|
-
);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("should send a custom User-Agent when set via setAgent()", async() => {
|
|
266
|
-
mockAgent
|
|
267
|
-
.get(kGithubOrigin)
|
|
268
|
-
.intercept({
|
|
269
|
-
path: "/users/foo/repos",
|
|
270
|
-
method: "GET",
|
|
271
|
-
headers: { "user-agent": "custom-agent/2.0" }
|
|
272
|
-
})
|
|
273
|
-
.reply(200, JSON.stringify([]), {
|
|
274
|
-
headers: { "content-type": "application/json" }
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
await assert.doesNotReject(
|
|
278
|
-
new ApiEndpoint("/users/foo/repos").setAgent("custom-agent/2.0").all()
|
|
279
|
-
);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("should send the Authorization header when a token is provided", async() => {
|
|
283
|
-
mockAgent
|
|
284
|
-
.get(kGithubOrigin)
|
|
285
|
-
.intercept({
|
|
286
|
-
path: "/users/foo/repos",
|
|
287
|
-
method: "GET",
|
|
288
|
-
headers: { authorization: "token secret123" }
|
|
289
|
-
})
|
|
290
|
-
.reply(200, JSON.stringify([]), {
|
|
291
|
-
headers: { "content-type": "application/json" }
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
await assert.doesNotReject(
|
|
295
|
-
new ApiEndpoint("/users/foo/repos", { token: "secret123" }).all()
|
|
296
|
-
);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it("should send the Authorization header when set via setBearerToken()", async() => {
|
|
300
|
-
mockAgent
|
|
301
|
-
.get(kGithubOrigin)
|
|
302
|
-
.intercept({
|
|
303
|
-
path: "/users/foo/repos",
|
|
304
|
-
method: "GET",
|
|
305
|
-
headers: { authorization: "token runtime-token" }
|
|
306
|
-
})
|
|
307
|
-
.reply(200, JSON.stringify([]), {
|
|
308
|
-
headers: { "content-type": "application/json" }
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
await assert.doesNotReject(
|
|
312
|
-
new ApiEndpoint("/users/foo/repos").setBearerToken("runtime-token").all()
|
|
313
|
-
);
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
describe("extractor", () => {
|
|
318
|
-
it("should apply the extractor to transform the raw response", async() => {
|
|
319
|
-
const workflows = [{ id: 10 }, { id: 20 }];
|
|
320
|
-
|
|
321
|
-
mockAgent
|
|
322
|
-
.get(kGithubOrigin)
|
|
323
|
-
.intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
|
|
324
|
-
.reply(200, JSON.stringify({ total_count: 2, workflows }), {
|
|
325
|
-
headers: { "content-type": "application/json" }
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
const result = await new ApiEndpoint(
|
|
329
|
-
"/repos/foo/bar/actions/workflows",
|
|
330
|
-
{ extractor: (raw) => raw.workflows }
|
|
331
|
-
).all();
|
|
332
|
-
|
|
333
|
-
assert.deepEqual(result, workflows);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it("should apply the extractor on every page when paginating", async() => {
|
|
337
|
-
const pool = mockAgent.get(kGithubOrigin);
|
|
338
|
-
|
|
339
|
-
pool
|
|
340
|
-
.intercept({ path: "/repos/foo/bar/actions/workflows", method: "GET" })
|
|
341
|
-
.reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 10 }] }), {
|
|
342
|
-
headers: {
|
|
343
|
-
"content-type": "application/json",
|
|
344
|
-
link: '<https://api.github.com/repos/foo/bar/actions/workflows?page=2>; rel="next"'
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
pool
|
|
349
|
-
.intercept({ path: "/repos/foo/bar/actions/workflows?page=2", method: "GET" })
|
|
350
|
-
.reply(200, JSON.stringify({ total_count: 3, workflows: [{ id: 20 }, { id: 30 }] }), {
|
|
351
|
-
headers: { "content-type": "application/json" }
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
const result = await new ApiEndpoint(
|
|
355
|
-
"/repos/foo/bar/actions/workflows",
|
|
356
|
-
{ extractor: (raw) => raw.workflows }
|
|
357
|
-
).all();
|
|
358
|
-
|
|
359
|
-
assert.deepEqual(result, [{ id: 10 }, { id: 20 }, { id: 30 }]);
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
});
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
// Import Node.js Dependencies
|
|
2
|
-
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
3
|
-
import assert from "node:assert/strict";
|
|
4
|
-
|
|
5
|
-
// Import Third-party Dependencies
|
|
6
|
-
import { MockAgent, setGlobalDispatcher, getGlobalDispatcher, type Dispatcher } from "undici";
|
|
7
|
-
|
|
8
|
-
// Import Internal Dependencies
|
|
9
|
-
import { GithubClient } from "../src/class/GithubClient.ts";
|
|
10
|
-
import { ApiEndpoint } from "../src/class/ApiEndpoint.ts";
|
|
11
|
-
|
|
12
|
-
// CONSTANTS
|
|
13
|
-
const kGithubOrigin = "https://api.github.com";
|
|
14
|
-
|
|
15
|
-
describe("GithubClient", () => {
|
|
16
|
-
let mockAgent: MockAgent;
|
|
17
|
-
let originalDispatcher: Dispatcher;
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
originalDispatcher = getGlobalDispatcher();
|
|
21
|
-
mockAgent = new MockAgent();
|
|
22
|
-
mockAgent.disableNetConnect();
|
|
23
|
-
setGlobalDispatcher(mockAgent);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(async() => {
|
|
27
|
-
await mockAgent.close();
|
|
28
|
-
setGlobalDispatcher(originalDispatcher);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe("constructor", () => {
|
|
32
|
-
it("should instantiate with no options", () => {
|
|
33
|
-
const client = new GithubClient();
|
|
34
|
-
|
|
35
|
-
assert.ok(client instanceof GithubClient);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("should instantiate with a token", () => {
|
|
39
|
-
const client = new GithubClient({ token: "mytoken" });
|
|
40
|
-
|
|
41
|
-
assert.ok(client instanceof GithubClient);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("should instantiate with a custom userAgent", () => {
|
|
45
|
-
const client = new GithubClient({ userAgent: "my-app/1.0" });
|
|
46
|
-
|
|
47
|
-
assert.ok(client instanceof GithubClient);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("should expose a users proxy", () => {
|
|
51
|
-
const client = new GithubClient();
|
|
52
|
-
|
|
53
|
-
assert.ok(client.users !== undefined);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should expose a repos proxy", () => {
|
|
57
|
-
const client = new GithubClient();
|
|
58
|
-
|
|
59
|
-
assert.ok(client.repos !== undefined);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe("client.users", () => {
|
|
64
|
-
it("should return ApiEndpoints for user sub-resources", () => {
|
|
65
|
-
const client = new GithubClient();
|
|
66
|
-
|
|
67
|
-
assert.ok(client.users.foo.repos() instanceof ApiEndpoint);
|
|
68
|
-
assert.ok(client.users.foo.orgs() instanceof ApiEndpoint);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("should use the configured token when fetching user data", async() => {
|
|
72
|
-
const client = new GithubClient({ token: "clienttoken" });
|
|
73
|
-
|
|
74
|
-
mockAgent
|
|
75
|
-
.get(kGithubOrigin)
|
|
76
|
-
.intercept({
|
|
77
|
-
path: "/users/octocat/repos",
|
|
78
|
-
method: "GET",
|
|
79
|
-
headers: { authorization: "token clienttoken" }
|
|
80
|
-
})
|
|
81
|
-
.reply(200, JSON.stringify([{ id: 1 }]), {
|
|
82
|
-
headers: { "content-type": "application/json" }
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const result = await client.users.octocat.repos().all();
|
|
86
|
-
|
|
87
|
-
assert.deepEqual(result, [{ id: 1 }]);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("should fetch user data without a token", async() => {
|
|
91
|
-
const client = new GithubClient();
|
|
92
|
-
|
|
93
|
-
mockAgent
|
|
94
|
-
.get(kGithubOrigin)
|
|
95
|
-
.intercept({ path: "/users/octocat/followers", method: "GET" })
|
|
96
|
-
.reply(200, JSON.stringify([{ login: "user1" }]), {
|
|
97
|
-
headers: { "content-type": "application/json" }
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const result = await client.users.octocat.followers().all();
|
|
101
|
-
|
|
102
|
-
assert.deepEqual(result, [{ login: "user1" }]);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe("client.repos", () => {
|
|
107
|
-
it("should return ApiEndpoints for repo sub-resources", () => {
|
|
108
|
-
const client = new GithubClient();
|
|
109
|
-
|
|
110
|
-
assert.ok(
|
|
111
|
-
client.repos.owner.myrepo.tags() instanceof ApiEndpoint
|
|
112
|
-
);
|
|
113
|
-
assert.ok(
|
|
114
|
-
client.repos.owner.myrepo.pulls() instanceof ApiEndpoint
|
|
115
|
-
);
|
|
116
|
-
assert.ok(
|
|
117
|
-
client.repos.owner.myrepo.workflows() instanceof ApiEndpoint
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("should use the configured token when fetching repo data", async() => {
|
|
122
|
-
const client = new GithubClient({ token: "repotoken" });
|
|
123
|
-
|
|
124
|
-
mockAgent
|
|
125
|
-
.get(kGithubOrigin)
|
|
126
|
-
.intercept({
|
|
127
|
-
path: "/repos/octocat/hello-world/tags",
|
|
128
|
-
method: "GET",
|
|
129
|
-
headers: { authorization: "token repotoken" }
|
|
130
|
-
})
|
|
131
|
-
.reply(200, JSON.stringify([{ name: "v1.0.0" }]), {
|
|
132
|
-
headers: { "content-type": "application/json" }
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
const result = await client.repos.octocat["hello-world"]
|
|
136
|
-
.tags()
|
|
137
|
-
.all();
|
|
138
|
-
|
|
139
|
-
assert.deepEqual(result, [{ name: "v1.0.0" }]);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it("should use the configured userAgent when fetching", async() => {
|
|
143
|
-
const client = new GithubClient({ userAgent: "my-app/1.0" });
|
|
144
|
-
|
|
145
|
-
mockAgent
|
|
146
|
-
.get(kGithubOrigin)
|
|
147
|
-
.intercept({
|
|
148
|
-
path: "/repos/octocat/hello-world/tags",
|
|
149
|
-
method: "GET",
|
|
150
|
-
headers: { "user-agent": "my-app/1.0" }
|
|
151
|
-
})
|
|
152
|
-
.reply(200, JSON.stringify([]), {
|
|
153
|
-
headers: { "content-type": "application/json" }
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
await assert.doesNotReject(
|
|
157
|
-
client.repos.octocat["hello-world"].tags().all()
|
|
158
|
-
);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("should fetch workflows with the envelope extractor", async() => {
|
|
162
|
-
const client = new GithubClient();
|
|
163
|
-
const workflows = [{ id: 7, name: "CI" }];
|
|
164
|
-
|
|
165
|
-
mockAgent
|
|
166
|
-
.get(kGithubOrigin)
|
|
167
|
-
.intercept({
|
|
168
|
-
path: "/repos/octocat/hello-world/actions/workflows",
|
|
169
|
-
method: "GET"
|
|
170
|
-
})
|
|
171
|
-
.reply(200, JSON.stringify({ total_count: 1, workflows }), {
|
|
172
|
-
headers: { "content-type": "application/json" }
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const result = await client.repos.octocat["hello-world"]
|
|
176
|
-
.workflows()
|
|
177
|
-
.all();
|
|
178
|
-
|
|
179
|
-
assert.deepEqual(
|
|
180
|
-
result,
|
|
181
|
-
workflows
|
|
182
|
-
);
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// Import Node.js Dependencies
|
|
2
|
-
import { describe, it } from "node:test";
|
|
3
|
-
import assert from "node:assert/strict";
|
|
4
|
-
|
|
5
|
-
// Import Internal Dependencies
|
|
6
|
-
import { HttpLinkParser } from "../src/class/HttpLinkParser.ts";
|
|
7
|
-
|
|
8
|
-
describe("HttpLinkParser", () => {
|
|
9
|
-
describe("parse()", () => {
|
|
10
|
-
it("should return a Map instance", () => {
|
|
11
|
-
const result = HttpLinkParser.parse("");
|
|
12
|
-
|
|
13
|
-
assert.ok(result instanceof Map);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("should return an empty map for an empty string", () => {
|
|
17
|
-
const result = HttpLinkParser.parse("");
|
|
18
|
-
|
|
19
|
-
assert.equal(result.size, 0);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("should return an empty map for a malformed header", () => {
|
|
23
|
-
const result = HttpLinkParser.parse("not a link header");
|
|
24
|
-
|
|
25
|
-
assert.equal(result.size, 0);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("should parse a single link relation", () => {
|
|
29
|
-
const header = '<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"';
|
|
30
|
-
const result = HttpLinkParser.parse(header);
|
|
31
|
-
|
|
32
|
-
assert.equal(result.size, 1);
|
|
33
|
-
assert.equal(result.get("next"), "https://api.github.com/repos/foo/bar/tags?page=2");
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should parse multiple link relations", () => {
|
|
37
|
-
const header = [
|
|
38
|
-
'<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"',
|
|
39
|
-
'<https://api.github.com/repos/foo/bar/tags?page=5>; rel="last"'
|
|
40
|
-
].join(", ");
|
|
41
|
-
const result = HttpLinkParser.parse(header);
|
|
42
|
-
|
|
43
|
-
assert.equal(result.size, 2);
|
|
44
|
-
assert.equal(result.get("next"), "https://api.github.com/repos/foo/bar/tags?page=2");
|
|
45
|
-
assert.equal(result.get("last"), "https://api.github.com/repos/foo/bar/tags?page=5");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("should parse all four standard link relations", () => {
|
|
49
|
-
const header = [
|
|
50
|
-
'<https://api.github.com/repos/foo/bar/tags?page=2>; rel="next"',
|
|
51
|
-
'<https://api.github.com/repos/foo/bar/tags?page=5>; rel="last"',
|
|
52
|
-
'<https://api.github.com/repos/foo/bar/tags?page=1>; rel="first"',
|
|
53
|
-
'<https://api.github.com/repos/foo/bar/tags?page=1>; rel="prev"'
|
|
54
|
-
].join(", ");
|
|
55
|
-
const result = HttpLinkParser.parse(header);
|
|
56
|
-
|
|
57
|
-
assert.equal(result.size, 4);
|
|
58
|
-
assert.ok(result.has("next"));
|
|
59
|
-
assert.ok(result.has("last"));
|
|
60
|
-
assert.ok(result.has("first"));
|
|
61
|
-
assert.ok(result.has("prev"));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("should ignore parts that have no URL match", () => {
|
|
65
|
-
const header = 'no-url; rel="next"';
|
|
66
|
-
const result = HttpLinkParser.parse(header);
|
|
67
|
-
|
|
68
|
-
assert.equal(result.size, 0);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("should ignore parts that have no rel match", () => {
|
|
72
|
-
const header = "<https://api.github.com/repos/foo/bar/tags?page=2>";
|
|
73
|
-
const result = HttpLinkParser.parse(header);
|
|
74
|
-
|
|
75
|
-
assert.equal(result.size, 0);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-unused-expressions */
|
|
2
|
-
// Import Node.js Dependencies
|
|
3
|
-
import { describe, it } from "node:test";
|
|
4
|
-
import assert from "node:assert/strict";
|
|
5
|
-
|
|
6
|
-
// Import Internal Dependencies
|
|
7
|
-
import { createApiProxy } from "../src/class/createApiProxy.ts";
|
|
8
|
-
|
|
9
|
-
describe("createApiProxy", () => {
|
|
10
|
-
it("should call the factory with the accessed property key", () => {
|
|
11
|
-
const proxy = createApiProxy((key) => key.toUpperCase());
|
|
12
|
-
|
|
13
|
-
assert.equal(proxy.hello, "HELLO");
|
|
14
|
-
assert.equal(proxy.world, "WORLD");
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("should call the factory on each property access", () => {
|
|
18
|
-
let callCount = 0;
|
|
19
|
-
const proxy = createApiProxy((key) => {
|
|
20
|
-
callCount++;
|
|
21
|
-
|
|
22
|
-
return key;
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
proxy.a;
|
|
26
|
-
proxy.b;
|
|
27
|
-
proxy.a;
|
|
28
|
-
|
|
29
|
-
assert.equal(callCount, 3);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("should return different values for different keys", () => {
|
|
33
|
-
const proxy = createApiProxy((key) => {
|
|
34
|
-
return { name: key };
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
assert.notDeepEqual(proxy.foo, proxy.bar);
|
|
38
|
-
assert.equal(proxy.foo.name, "foo");
|
|
39
|
-
assert.equal(proxy.bar.name, "bar");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should support nested proxies", () => {
|
|
43
|
-
const proxy = createApiProxy(
|
|
44
|
-
(owner: string) => createApiProxy(
|
|
45
|
-
(repo: string) => `${owner}/${repo}`
|
|
46
|
-
)
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
assert.equal(proxy.myorg.myrepo, "myorg/myrepo");
|
|
50
|
-
assert.equal(proxy.another.sdk, "another/sdk");
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("should return a plain object (no prototype)", () => {
|
|
54
|
-
const proxy = createApiProxy((key) => key);
|
|
55
|
-
|
|
56
|
-
assert.equal(Object.getPrototypeOf(proxy), null);
|
|
57
|
-
});
|
|
58
|
-
});
|