@beyonk/http 12.0.1 → 12.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/package.json +18 -12
- package/.github/workflows/publish.yml +0 -60
- package/lib/api/_just-compose.js +0 -12
- package/lib/api/index.js +0 -233
- package/lib/api/index.spec.js +0 -954
- package/lib/entrypoint.js +0 -19
- package/lib/error-handlers/access-denied.js +0 -12
- package/lib/error-handlers/bad-data.js +0 -12
- package/lib/error-handlers/conflict.js +0 -12
- package/lib/error-handlers/default.js +0 -8
- package/lib/error-handlers/expectation-failed.js +0 -12
- package/lib/error-handlers/forbidden.js +0 -12
- package/lib/error-handlers/gone.js +0 -12
- package/lib/error-handlers/handle.js +0 -25
- package/lib/error-handlers/not-acceptable.js +0 -12
- package/lib/error-handlers/not-found.js +0 -12
- package/lib/error-handlers/payment-required.js +0 -12
- package/lib/error-handlers/precondition-failed.js +0 -12
- package/lib/error-handlers/too-many-requests.js +0 -12
- package/lib/errors.js +0 -73
package/lib/api/index.spec.js
DELETED
|
@@ -1,954 +0,0 @@
|
|
|
1
|
-
import sinon from 'sinon'
|
|
2
|
-
import { expect } from '@hapi/code'
|
|
3
|
-
import { Api } from './index.js'
|
|
4
|
-
|
|
5
|
-
const { stub } = sinon
|
|
6
|
-
|
|
7
|
-
describe('util/api', () => {
|
|
8
|
-
describe('#get()', () => {
|
|
9
|
-
context('error handling', () => {
|
|
10
|
-
let clientStub
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
global.FormData = Map
|
|
14
|
-
clientStub = stub()
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('with unknown status code', async () => {
|
|
18
|
-
let error
|
|
19
|
-
const expectedError = 'hit default handler'
|
|
20
|
-
|
|
21
|
-
const api = new Api({
|
|
22
|
-
baseUrl: 'https://example.com/api/v1'
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
clientStub.resolves({
|
|
26
|
-
ok: false,
|
|
27
|
-
statusText: 'No',
|
|
28
|
-
json: stub().resolves({ error: 'no' }),
|
|
29
|
-
status: 419,
|
|
30
|
-
headers: new Map()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
await api
|
|
34
|
-
.context({ fetch: clientStub })
|
|
35
|
-
.endpoint('some/url')
|
|
36
|
-
.default(e => {
|
|
37
|
-
error = expectedError
|
|
38
|
-
})
|
|
39
|
-
.get()
|
|
40
|
-
|
|
41
|
-
expect(error).to.equal(expectedError)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('has specific error handler', async () => {
|
|
45
|
-
let error
|
|
46
|
-
const expectedError = 'hit local 401 handler'
|
|
47
|
-
|
|
48
|
-
const api = new Api({
|
|
49
|
-
baseUrl: 'https://example.com/api/v1'
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
clientStub.resolves({
|
|
53
|
-
ok: false,
|
|
54
|
-
statusText: 'No',
|
|
55
|
-
json: stub().resolves({ error: 'no' }),
|
|
56
|
-
status: 401,
|
|
57
|
-
headers: new Map()
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
await api
|
|
61
|
-
.context({ fetch: clientStub })
|
|
62
|
-
.endpoint('some/url')
|
|
63
|
-
.accessDenied(() => {
|
|
64
|
-
error = expectedError
|
|
65
|
-
})
|
|
66
|
-
.get()
|
|
67
|
-
|
|
68
|
-
expect(error).to.equal(expectedError)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('has global error handler', async () => {
|
|
72
|
-
let error
|
|
73
|
-
const expectedError = 'hit global 401 handler'
|
|
74
|
-
|
|
75
|
-
const api = new Api({
|
|
76
|
-
baseUrl: 'https://example.com/api/v1',
|
|
77
|
-
handlers: {
|
|
78
|
-
accessDenied: () => {
|
|
79
|
-
error = expectedError
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
clientStub.resolves({
|
|
85
|
-
ok: false,
|
|
86
|
-
statusText: 'No',
|
|
87
|
-
json: stub().resolves({ error: 'no' }),
|
|
88
|
-
status: 401,
|
|
89
|
-
headers: new Map()
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
await api
|
|
93
|
-
.context({ fetch: clientStub })
|
|
94
|
-
.endpoint('some/url')
|
|
95
|
-
.get()
|
|
96
|
-
|
|
97
|
-
expect(error).to.equal(expectedError)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('prefers local error handler to global error handler', async () => {
|
|
101
|
-
let globalCalled = false
|
|
102
|
-
let localCalled = false
|
|
103
|
-
|
|
104
|
-
const api = new Api({
|
|
105
|
-
baseUrl: 'https://example.com/api/v1',
|
|
106
|
-
handlers: {
|
|
107
|
-
accessDenied: () => {
|
|
108
|
-
globalCalled = true
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
clientStub.resolves({
|
|
114
|
-
ok: false,
|
|
115
|
-
statusText: 'No',
|
|
116
|
-
json: stub().resolves({ error: 'no' }),
|
|
117
|
-
status: 401,
|
|
118
|
-
headers: new Map()
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
await api
|
|
122
|
-
.context({ fetch: clientStub })
|
|
123
|
-
.endpoint('some/url')
|
|
124
|
-
.accessDenied(() => {
|
|
125
|
-
localCalled = true
|
|
126
|
-
})
|
|
127
|
-
.get()
|
|
128
|
-
|
|
129
|
-
expect(globalCalled).to.be.false()
|
|
130
|
-
expect(localCalled).to.be.true()
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('prefers global error handler to default error handler', async () => {
|
|
134
|
-
let globalCalled = false
|
|
135
|
-
let defaultCalled = false
|
|
136
|
-
|
|
137
|
-
const api = new Api({
|
|
138
|
-
baseUrl: 'https://example.com/api/v1',
|
|
139
|
-
handlers: {
|
|
140
|
-
accessDenied: () => {
|
|
141
|
-
globalCalled = true
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
clientStub.resolves({
|
|
147
|
-
ok: false,
|
|
148
|
-
statusText: 'No',
|
|
149
|
-
json: stub().resolves({ error: 'no' }),
|
|
150
|
-
status: 401,
|
|
151
|
-
headers: new Map()
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
await api
|
|
155
|
-
.context({ fetch: clientStub })
|
|
156
|
-
.endpoint('some/url')
|
|
157
|
-
.default(() => {
|
|
158
|
-
defaultCalled = true
|
|
159
|
-
})
|
|
160
|
-
.get()
|
|
161
|
-
|
|
162
|
-
expect(globalCalled).to.be.true()
|
|
163
|
-
expect(defaultCalled).to.be.false()
|
|
164
|
-
})
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
context('responds ok', () => {
|
|
168
|
-
let api
|
|
169
|
-
let clientStub
|
|
170
|
-
|
|
171
|
-
beforeEach(async () => {
|
|
172
|
-
global.FormData = Map
|
|
173
|
-
clientStub = stub()
|
|
174
|
-
api = new Api({
|
|
175
|
-
baseUrl: 'https://example.com/api/v1'
|
|
176
|
-
})
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
it('fetches data from url and passes it to a function', async () => {
|
|
180
|
-
clientStub.resolves({
|
|
181
|
-
status: 200,
|
|
182
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
183
|
-
headers: new Map()
|
|
184
|
-
})
|
|
185
|
-
expect(
|
|
186
|
-
await api
|
|
187
|
-
.context({ fetch: clientStub })
|
|
188
|
-
.endpoint('some/url')
|
|
189
|
-
.get(({ foo }) => foo)
|
|
190
|
-
).to.equal('bar')
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
it('fetches data from url and passes it to an async function', async () => {
|
|
194
|
-
clientStub.resolves({
|
|
195
|
-
status: 200,
|
|
196
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
197
|
-
headers: new Map()
|
|
198
|
-
})
|
|
199
|
-
expect(
|
|
200
|
-
await api
|
|
201
|
-
.context({ fetch: clientStub })
|
|
202
|
-
.endpoint('some/url')
|
|
203
|
-
.get(async ({ foo }) => {
|
|
204
|
-
await foo
|
|
205
|
-
return foo
|
|
206
|
-
})
|
|
207
|
-
).to.equal('bar')
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
it('fetches data from url and returns it', async () => {
|
|
211
|
-
clientStub.resolves({
|
|
212
|
-
status: 200,
|
|
213
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
214
|
-
headers: new Map()
|
|
215
|
-
})
|
|
216
|
-
expect(
|
|
217
|
-
await api
|
|
218
|
-
.context({ fetch: clientStub })
|
|
219
|
-
.endpoint('some/url')
|
|
220
|
-
.get()
|
|
221
|
-
).to.equal({ foo: 'bar' })
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
it('appends baseUrl if endpoint is relative', async () => {
|
|
225
|
-
clientStub.resolves({
|
|
226
|
-
status: 200,
|
|
227
|
-
json: stub(),
|
|
228
|
-
headers: new Map()
|
|
229
|
-
})
|
|
230
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').get()
|
|
231
|
-
expect(clientStub.firstCall.args[0]).to.equal('https://example.com/api/v1/some/url')
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
it('fetches data from url with query params', async () => {
|
|
235
|
-
clientStub.resolves({
|
|
236
|
-
status: 200,
|
|
237
|
-
json: stub(),
|
|
238
|
-
headers: new Map()
|
|
239
|
-
})
|
|
240
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').query({ foo: 'bar', baz: 'qux' }).get()
|
|
241
|
-
expect(clientStub.firstCall.args[0]).to.endWith('/some/url?foo=bar&baz=qux')
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
it('fetches data from url with query params', async () => {
|
|
245
|
-
clientStub.resolves({
|
|
246
|
-
status: 200,
|
|
247
|
-
json: stub(),
|
|
248
|
-
headers: new Map()
|
|
249
|
-
})
|
|
250
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').query({ foo: [ 'bar', 'qux' ] }).get()
|
|
251
|
-
expect(clientStub.firstCall.args[0]).to.endWith('/some/url?foo=bar&foo=qux')
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
it('fetches data from url ignoring undefined query params', async () => {
|
|
255
|
-
clientStub.resolves({
|
|
256
|
-
status: 200,
|
|
257
|
-
json: stub(),
|
|
258
|
-
headers: new Map()
|
|
259
|
-
})
|
|
260
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').query({ foo: 'bar', baz: undefined }).get()
|
|
261
|
-
expect(clientStub.firstCall.args[0]).to.endWith('/some/url?foo=bar')
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
it('passes status code as second parameter', async () => {
|
|
265
|
-
const httpStatusCode = 202
|
|
266
|
-
|
|
267
|
-
clientStub.resolves({
|
|
268
|
-
status: httpStatusCode,
|
|
269
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
270
|
-
statusText: 'Accepted',
|
|
271
|
-
headers: new Map()
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
const code = await api
|
|
275
|
-
.context({ fetch: clientStub })
|
|
276
|
-
.endpoint('some/url')
|
|
277
|
-
.get((json, statusCode) => {
|
|
278
|
-
return statusCode
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
expect(code).to.equal(httpStatusCode)
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
it('parses 3xx as successful', async () => {
|
|
285
|
-
const httpStatusCode = 304
|
|
286
|
-
|
|
287
|
-
clientStub.resolves({
|
|
288
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
289
|
-
statusText: 'Not Modified',
|
|
290
|
-
status: httpStatusCode,
|
|
291
|
-
headers: new Map()
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
const code = await api
|
|
295
|
-
.context({ fetch: clientStub })
|
|
296
|
-
.endpoint('some/url')
|
|
297
|
-
.get((json, statusCode) => {
|
|
298
|
-
return statusCode
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
expect(code).to.equal(httpStatusCode)
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
it('does not parse on 204 (no content)', async () => {
|
|
305
|
-
const httpStatusCode = 204
|
|
306
|
-
const jsonFunction = stub()
|
|
307
|
-
|
|
308
|
-
clientStub.resolves({
|
|
309
|
-
json: jsonFunction,
|
|
310
|
-
statusText: 'No Content',
|
|
311
|
-
status: httpStatusCode,
|
|
312
|
-
headers: new Map()
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
await api
|
|
316
|
-
.context({ fetch: clientStub })
|
|
317
|
-
.endpoint('some/url')
|
|
318
|
-
.get((json, statusCode) => {
|
|
319
|
-
return statusCode
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
expect(jsonFunction.callCount).to.equal(0)
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
it('does not parse on empty body', async () => {
|
|
326
|
-
const httpStatusCode = 200
|
|
327
|
-
const jsonFunction = stub()
|
|
328
|
-
|
|
329
|
-
const headers = new Map()
|
|
330
|
-
headers.set('content-length', '0')
|
|
331
|
-
|
|
332
|
-
clientStub.resolves({
|
|
333
|
-
json: jsonFunction,
|
|
334
|
-
headers,
|
|
335
|
-
statusText: 'OK',
|
|
336
|
-
status: httpStatusCode
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
await api
|
|
340
|
-
.context({ fetch: clientStub })
|
|
341
|
-
.endpoint('some/url')
|
|
342
|
-
.get((json, statusCode) => {
|
|
343
|
-
return statusCode
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
expect(jsonFunction.callCount).to.equal(0)
|
|
347
|
-
})
|
|
348
|
-
|
|
349
|
-
it('with known status code', async () => {
|
|
350
|
-
let error
|
|
351
|
-
const expectedErrorMessage = 'no'
|
|
352
|
-
|
|
353
|
-
clientStub.resolves({
|
|
354
|
-
text: stub().resolves('foo'),
|
|
355
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
356
|
-
statusText: expectedErrorMessage,
|
|
357
|
-
status: 401,
|
|
358
|
-
headers: new Map()
|
|
359
|
-
})
|
|
360
|
-
|
|
361
|
-
await api
|
|
362
|
-
.context({ fetch: clientStub })
|
|
363
|
-
.endpoint('some/url')
|
|
364
|
-
.accessDenied(e => {
|
|
365
|
-
error = e.message
|
|
366
|
-
})
|
|
367
|
-
.get()
|
|
368
|
-
|
|
369
|
-
expect(error).to.equal(expectedErrorMessage)
|
|
370
|
-
})
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
context('parses errors', () => {
|
|
374
|
-
let api
|
|
375
|
-
let clientStub
|
|
376
|
-
|
|
377
|
-
const jsonPayload = {
|
|
378
|
-
foo: 'bar'
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
beforeEach(async () => {
|
|
382
|
-
global.FormData = Map
|
|
383
|
-
clientStub = stub()
|
|
384
|
-
api = new Api({
|
|
385
|
-
baseUrl: 'https://example.com/api/v1',
|
|
386
|
-
parseErrors: true
|
|
387
|
-
})
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
it('with known status code', async () => {
|
|
391
|
-
let payload
|
|
392
|
-
const expectedErrorMessage = 'no'
|
|
393
|
-
|
|
394
|
-
clientStub.resolves({
|
|
395
|
-
ok: false,
|
|
396
|
-
json: stub().resolves(jsonPayload),
|
|
397
|
-
statusText: expectedErrorMessage,
|
|
398
|
-
status: 401,
|
|
399
|
-
headers: new Map()
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
await api
|
|
403
|
-
.context({ fetch: clientStub })
|
|
404
|
-
.endpoint('some/url')
|
|
405
|
-
.accessDenied(e => {
|
|
406
|
-
payload = e.body
|
|
407
|
-
})
|
|
408
|
-
.get()
|
|
409
|
-
|
|
410
|
-
expect(payload).to.equal(payload)
|
|
411
|
-
})
|
|
412
|
-
})
|
|
413
|
-
|
|
414
|
-
context('retries', async () => {
|
|
415
|
-
context('succeeds on third try', () => {
|
|
416
|
-
let api
|
|
417
|
-
let clientStub
|
|
418
|
-
let res
|
|
419
|
-
|
|
420
|
-
class MySystemError extends Error {
|
|
421
|
-
constructor () {
|
|
422
|
-
super()
|
|
423
|
-
this.code = 'ECONNRESET'
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
beforeEach(async () => {
|
|
428
|
-
global.FormData = Map
|
|
429
|
-
clientStub = stub()
|
|
430
|
-
clientStub.onFirstCall().rejects(new MySystemError())
|
|
431
|
-
clientStub.onSecondCall().rejects(new MySystemError())
|
|
432
|
-
clientStub.onThirdCall().resolves({
|
|
433
|
-
status: 200,
|
|
434
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
435
|
-
headers: new Map()
|
|
436
|
-
})
|
|
437
|
-
|
|
438
|
-
api = new Api({
|
|
439
|
-
baseUrl: 'https://example.com/api/v1',
|
|
440
|
-
retry: {
|
|
441
|
-
errors: [ 'ECONNRESET' ],
|
|
442
|
-
attempts: 3
|
|
443
|
-
}
|
|
444
|
-
})
|
|
445
|
-
|
|
446
|
-
res = await api
|
|
447
|
-
.context({ fetch: clientStub })
|
|
448
|
-
.endpoint('some/url')
|
|
449
|
-
.get(({ foo }) => foo)
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
afterEach(() => {
|
|
453
|
-
clientStub.reset()
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('retries three times', () => {
|
|
457
|
-
expect(
|
|
458
|
-
clientStub.callCount
|
|
459
|
-
).to.equal(3)
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
it('returns value', () => {
|
|
463
|
-
expect(
|
|
464
|
-
res
|
|
465
|
-
).to.equal('bar')
|
|
466
|
-
})
|
|
467
|
-
})
|
|
468
|
-
|
|
469
|
-
context('never succeeds', () => {
|
|
470
|
-
let api
|
|
471
|
-
let clientStub
|
|
472
|
-
let successStub
|
|
473
|
-
let error
|
|
474
|
-
|
|
475
|
-
class MySystemError extends Error {
|
|
476
|
-
constructor () {
|
|
477
|
-
super()
|
|
478
|
-
this.code = 'ECONNRESET'
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
beforeEach(async () => {
|
|
483
|
-
global.FormData = Map
|
|
484
|
-
clientStub = stub()
|
|
485
|
-
clientStub.onFirstCall().rejects(new MySystemError())
|
|
486
|
-
clientStub.onSecondCall().rejects(new MySystemError())
|
|
487
|
-
|
|
488
|
-
successStub = stub()
|
|
489
|
-
|
|
490
|
-
api = new Api({
|
|
491
|
-
baseUrl: 'https://example.com/api/v1',
|
|
492
|
-
retry: {
|
|
493
|
-
errors: [ 'ECONNRESET' ],
|
|
494
|
-
attempts: 2
|
|
495
|
-
}
|
|
496
|
-
})
|
|
497
|
-
|
|
498
|
-
await api
|
|
499
|
-
.context({ fetch: clientStub })
|
|
500
|
-
.endpoint('some/url')
|
|
501
|
-
.default(e => {
|
|
502
|
-
error = 'stuff happened'
|
|
503
|
-
})
|
|
504
|
-
.get(successStub)
|
|
505
|
-
})
|
|
506
|
-
|
|
507
|
-
afterEach(() => {
|
|
508
|
-
clientStub.reset()
|
|
509
|
-
successStub.reset()
|
|
510
|
-
})
|
|
511
|
-
|
|
512
|
-
it('retries three times', () => {
|
|
513
|
-
expect(
|
|
514
|
-
clientStub.callCount
|
|
515
|
-
).to.equal(2)
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
it('catches default error', () => {
|
|
519
|
-
expect(error).to.equal('stuff happened')
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('does not call success method', () => {
|
|
523
|
-
expect(
|
|
524
|
-
successStub.callCount
|
|
525
|
-
).to.equal(0)
|
|
526
|
-
})
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
context('passes context to error handlers', () => {
|
|
530
|
-
const clientStub = stub()
|
|
531
|
-
const defaultErrorHandler = stub()
|
|
532
|
-
|
|
533
|
-
clientStub.resolves({
|
|
534
|
-
ok: true,
|
|
535
|
-
status: 200,
|
|
536
|
-
headers: new Map(),
|
|
537
|
-
json: stub().resolves()
|
|
538
|
-
})
|
|
539
|
-
|
|
540
|
-
const ctx = { fetch: clientStub, foo: 'bar' }
|
|
541
|
-
|
|
542
|
-
class CustomError extends Error {}
|
|
543
|
-
|
|
544
|
-
let api
|
|
545
|
-
let error
|
|
546
|
-
|
|
547
|
-
beforeEach(async () => {
|
|
548
|
-
api = new Api({
|
|
549
|
-
baseUrl: 'https://example.com/api/v1'
|
|
550
|
-
})
|
|
551
|
-
|
|
552
|
-
error = await expect(
|
|
553
|
-
api
|
|
554
|
-
.context(ctx)
|
|
555
|
-
.endpoint('some/url')
|
|
556
|
-
.default(defaultErrorHandler)
|
|
557
|
-
.get(() => {
|
|
558
|
-
throw new CustomError()
|
|
559
|
-
})
|
|
560
|
-
).to.reject()
|
|
561
|
-
})
|
|
562
|
-
|
|
563
|
-
it('throws success handler error externally', () => {
|
|
564
|
-
expect(error).to.be.an.instanceOf(CustomError)
|
|
565
|
-
})
|
|
566
|
-
|
|
567
|
-
it('does not call default error handler', () => {
|
|
568
|
-
expect(defaultErrorHandler.callCount).to.equal(0)
|
|
569
|
-
})
|
|
570
|
-
})
|
|
571
|
-
|
|
572
|
-
context('error thrown in success handler is not caught', () => {
|
|
573
|
-
let api
|
|
574
|
-
let clientStub
|
|
575
|
-
|
|
576
|
-
const ctx = { fetch: clientStub, foo: 'bar' }
|
|
577
|
-
|
|
578
|
-
beforeEach(async () => {
|
|
579
|
-
clientStub = stub()
|
|
580
|
-
clientStub.resolves({
|
|
581
|
-
status: 200,
|
|
582
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
583
|
-
headers: new Map()
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
api = new Api({
|
|
587
|
-
baseUrl: 'https://example.com/api/v1'
|
|
588
|
-
})
|
|
589
|
-
|
|
590
|
-
await api
|
|
591
|
-
.context({ fetch: clientStub, foo: 'bar' })
|
|
592
|
-
.endpoint('some/url')
|
|
593
|
-
.get(({ foo }) => foo)
|
|
594
|
-
})
|
|
595
|
-
|
|
596
|
-
it('has cleared endpoint', () => {
|
|
597
|
-
expect(api.config.endpoint).to.equal(null)
|
|
598
|
-
})
|
|
599
|
-
|
|
600
|
-
it('has cleared method', () => {
|
|
601
|
-
expect(api.config.method).to.equal('get')
|
|
602
|
-
})
|
|
603
|
-
|
|
604
|
-
it('has not cleared client', () => {
|
|
605
|
-
expect(api.client).to.equal(clientStub)
|
|
606
|
-
})
|
|
607
|
-
|
|
608
|
-
it('has not cleared context', () => {
|
|
609
|
-
expect(api.ctx.foo).to.equal(ctx.foo)
|
|
610
|
-
})
|
|
611
|
-
|
|
612
|
-
it('has cleared query', () => {
|
|
613
|
-
expect(api.config.query).to.equal(null)
|
|
614
|
-
})
|
|
615
|
-
|
|
616
|
-
it('has cleared payload', () => {
|
|
617
|
-
expect(api.config.payload).to.equal(null)
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
it('has cleared overrides', () => {
|
|
621
|
-
expect(api.config.overrides).to.equal({})
|
|
622
|
-
})
|
|
623
|
-
})
|
|
624
|
-
})
|
|
625
|
-
|
|
626
|
-
context('context', () => {
|
|
627
|
-
context('sets context with client', () => {
|
|
628
|
-
let api
|
|
629
|
-
const clientStub = 'bar'
|
|
630
|
-
|
|
631
|
-
const ctx = { fetch: clientStub, foo: 'bar' }
|
|
632
|
-
|
|
633
|
-
beforeEach(async () => {
|
|
634
|
-
api = new Api({
|
|
635
|
-
baseUrl: 'https://example.com/api/v1'
|
|
636
|
-
})
|
|
637
|
-
|
|
638
|
-
await api
|
|
639
|
-
.context(ctx)
|
|
640
|
-
.endpoint('some/url')
|
|
641
|
-
})
|
|
642
|
-
|
|
643
|
-
it('has set context', () => {
|
|
644
|
-
expect(api.ctx).to.equal(ctx)
|
|
645
|
-
})
|
|
646
|
-
|
|
647
|
-
it('has set client', () => {
|
|
648
|
-
expect(api.client).to.equal(ctx.fetch)
|
|
649
|
-
})
|
|
650
|
-
})
|
|
651
|
-
|
|
652
|
-
context('sets context without client', () => {
|
|
653
|
-
let api
|
|
654
|
-
|
|
655
|
-
const ctx = { foo: 'bar' }
|
|
656
|
-
|
|
657
|
-
beforeEach(async () => {
|
|
658
|
-
api = new Api({
|
|
659
|
-
baseUrl: 'https://example.com/api/v1'
|
|
660
|
-
})
|
|
661
|
-
|
|
662
|
-
await api
|
|
663
|
-
.context(ctx)
|
|
664
|
-
.endpoint('some/url')
|
|
665
|
-
})
|
|
666
|
-
|
|
667
|
-
it('has set context', () => {
|
|
668
|
-
expect(api.ctx).to.equal(ctx)
|
|
669
|
-
})
|
|
670
|
-
|
|
671
|
-
it('has not set client', () => {
|
|
672
|
-
expect(api.client).to.be.null()
|
|
673
|
-
})
|
|
674
|
-
})
|
|
675
|
-
|
|
676
|
-
context('passes context to error handlers', () => {
|
|
677
|
-
let api
|
|
678
|
-
const clientStub = stub()
|
|
679
|
-
let passed
|
|
680
|
-
|
|
681
|
-
clientStub.resolves({
|
|
682
|
-
ok: false,
|
|
683
|
-
statusText: 'No',
|
|
684
|
-
json: stub().resolves({ error: 'no' }),
|
|
685
|
-
status: 406,
|
|
686
|
-
headers: new Map()
|
|
687
|
-
})
|
|
688
|
-
|
|
689
|
-
const ctx = { fetch: clientStub, foo: 'bar' }
|
|
690
|
-
|
|
691
|
-
beforeEach(async () => {
|
|
692
|
-
api = new Api({
|
|
693
|
-
baseUrl: 'https://example.com/api/v1'
|
|
694
|
-
})
|
|
695
|
-
|
|
696
|
-
await api
|
|
697
|
-
.context(ctx)
|
|
698
|
-
.endpoint('some/url')
|
|
699
|
-
.notAcceptable((e, ctx) => {
|
|
700
|
-
passed = ctx
|
|
701
|
-
})
|
|
702
|
-
.get()
|
|
703
|
-
})
|
|
704
|
-
|
|
705
|
-
it('has passed context to handler', () => {
|
|
706
|
-
expect(passed.foo).to.equal(ctx.foo)
|
|
707
|
-
})
|
|
708
|
-
})
|
|
709
|
-
})
|
|
710
|
-
})
|
|
711
|
-
|
|
712
|
-
describe('#post()', () => {
|
|
713
|
-
let api
|
|
714
|
-
let clientStub
|
|
715
|
-
|
|
716
|
-
beforeEach(async () => {
|
|
717
|
-
clientStub = stub()
|
|
718
|
-
api = new Api({
|
|
719
|
-
baseUrl: 'https://example.com/api/v1'
|
|
720
|
-
}, clientStub)
|
|
721
|
-
})
|
|
722
|
-
|
|
723
|
-
it('posts data to url', async () => {
|
|
724
|
-
clientStub.resolves({
|
|
725
|
-
status: 201,
|
|
726
|
-
json: stub(),
|
|
727
|
-
headers: new Map()
|
|
728
|
-
})
|
|
729
|
-
|
|
730
|
-
const content = { foo: 'bar' }
|
|
731
|
-
await api
|
|
732
|
-
.context({ fetch: clientStub })
|
|
733
|
-
.endpoint('some/url')
|
|
734
|
-
.payload(content)
|
|
735
|
-
.post()
|
|
736
|
-
|
|
737
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
738
|
-
method: 'POST',
|
|
739
|
-
headers: {
|
|
740
|
-
Accept: 'application/json',
|
|
741
|
-
'Content-Type': 'application/json'
|
|
742
|
-
},
|
|
743
|
-
body: JSON.stringify(content)
|
|
744
|
-
})
|
|
745
|
-
})
|
|
746
|
-
|
|
747
|
-
it('sets an authorization header', async () => {
|
|
748
|
-
clientStub.resolves({
|
|
749
|
-
status: 201,
|
|
750
|
-
json: stub(),
|
|
751
|
-
headers: new Map()
|
|
752
|
-
})
|
|
753
|
-
|
|
754
|
-
const content = { foo: 'bar' }
|
|
755
|
-
await api
|
|
756
|
-
.context({ fetch: clientStub })
|
|
757
|
-
.endpoint('some/url')
|
|
758
|
-
.headers({
|
|
759
|
-
Authorization: 'Bearer xxx'
|
|
760
|
-
})
|
|
761
|
-
.payload(content)
|
|
762
|
-
.post()
|
|
763
|
-
|
|
764
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
765
|
-
method: 'POST',
|
|
766
|
-
headers: {
|
|
767
|
-
Accept: 'application/json',
|
|
768
|
-
'Content-Type': 'application/json',
|
|
769
|
-
Authorization: 'Bearer xxx'
|
|
770
|
-
},
|
|
771
|
-
body: JSON.stringify(content)
|
|
772
|
-
})
|
|
773
|
-
})
|
|
774
|
-
})
|
|
775
|
-
|
|
776
|
-
describe('#patch()', () => {
|
|
777
|
-
let api
|
|
778
|
-
let clientStub
|
|
779
|
-
|
|
780
|
-
beforeEach(async () => {
|
|
781
|
-
clientStub = stub()
|
|
782
|
-
api = new Api({
|
|
783
|
-
baseUrl: 'https://example.com/api/v1'
|
|
784
|
-
}, clientStub)
|
|
785
|
-
})
|
|
786
|
-
|
|
787
|
-
it('sends data to url', async () => {
|
|
788
|
-
clientStub.resolves({
|
|
789
|
-
status: 200,
|
|
790
|
-
json: stub(),
|
|
791
|
-
headers: new Map()
|
|
792
|
-
})
|
|
793
|
-
|
|
794
|
-
const content = { foo: 'bar' }
|
|
795
|
-
await api
|
|
796
|
-
.context({ fetch: clientStub })
|
|
797
|
-
.endpoint('some/url')
|
|
798
|
-
.payload(content)
|
|
799
|
-
.patch()
|
|
800
|
-
|
|
801
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
802
|
-
method: 'PATCH',
|
|
803
|
-
headers: {
|
|
804
|
-
Accept: 'application/json',
|
|
805
|
-
'Content-Type': 'application/json'
|
|
806
|
-
},
|
|
807
|
-
body: JSON.stringify(content)
|
|
808
|
-
})
|
|
809
|
-
})
|
|
810
|
-
|
|
811
|
-
it('sets an authorization header', async () => {
|
|
812
|
-
clientStub.resolves({
|
|
813
|
-
status: 201,
|
|
814
|
-
json: stub(),
|
|
815
|
-
headers: new Map()
|
|
816
|
-
})
|
|
817
|
-
|
|
818
|
-
const content = { foo: 'bar' }
|
|
819
|
-
await api
|
|
820
|
-
.context({ fetch: clientStub })
|
|
821
|
-
.endpoint('some/url')
|
|
822
|
-
.headers({
|
|
823
|
-
Authorization: 'Bearer xxx'
|
|
824
|
-
})
|
|
825
|
-
.payload(content)
|
|
826
|
-
.patch()
|
|
827
|
-
|
|
828
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
829
|
-
method: 'PATCH',
|
|
830
|
-
headers: {
|
|
831
|
-
Accept: 'application/json',
|
|
832
|
-
'Content-Type': 'application/json',
|
|
833
|
-
Authorization: 'Bearer xxx'
|
|
834
|
-
},
|
|
835
|
-
body: JSON.stringify(content)
|
|
836
|
-
})
|
|
837
|
-
})
|
|
838
|
-
})
|
|
839
|
-
|
|
840
|
-
describe('#put()', () => {
|
|
841
|
-
let api
|
|
842
|
-
let clientStub
|
|
843
|
-
|
|
844
|
-
beforeEach(async () => {
|
|
845
|
-
clientStub = stub()
|
|
846
|
-
api = new Api({
|
|
847
|
-
baseUrl: 'https://example.com/api/v1'
|
|
848
|
-
}, clientStub)
|
|
849
|
-
})
|
|
850
|
-
|
|
851
|
-
it('fetches data from url', async () => {
|
|
852
|
-
clientStub.resolves({
|
|
853
|
-
status: 200,
|
|
854
|
-
json: stub(),
|
|
855
|
-
headers: new Map()
|
|
856
|
-
})
|
|
857
|
-
|
|
858
|
-
const content = { foo: 'bar' }
|
|
859
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').payload(content).put()
|
|
860
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
861
|
-
method: 'PUT',
|
|
862
|
-
headers: {
|
|
863
|
-
Accept: 'application/json',
|
|
864
|
-
'Content-Type': 'application/json'
|
|
865
|
-
},
|
|
866
|
-
body: JSON.stringify(content)
|
|
867
|
-
})
|
|
868
|
-
})
|
|
869
|
-
|
|
870
|
-
it('endpoint returns no data', async () => {
|
|
871
|
-
clientStub.resolves({
|
|
872
|
-
status: 200,
|
|
873
|
-
json: stub().rejects('Error'),
|
|
874
|
-
headers: new Map()
|
|
875
|
-
})
|
|
876
|
-
expect(
|
|
877
|
-
await api
|
|
878
|
-
.context({ fetch: clientStub })
|
|
879
|
-
.endpoint('some/url')
|
|
880
|
-
.put(() => true)
|
|
881
|
-
).to.be.true()
|
|
882
|
-
})
|
|
883
|
-
|
|
884
|
-
it('sets an authorization header', async () => {
|
|
885
|
-
clientStub.resolves({
|
|
886
|
-
status: 200,
|
|
887
|
-
json: stub().resolves({ foo: 'bar' }),
|
|
888
|
-
headers: new Map()
|
|
889
|
-
})
|
|
890
|
-
|
|
891
|
-
const content = { foo: 'bar' }
|
|
892
|
-
await api
|
|
893
|
-
.context({ fetch: clientStub })
|
|
894
|
-
.endpoint('some/url')
|
|
895
|
-
.headers({
|
|
896
|
-
Authorization: 'Bearer xxx'
|
|
897
|
-
})
|
|
898
|
-
.payload(content)
|
|
899
|
-
.put()
|
|
900
|
-
|
|
901
|
-
expect(clientStub.firstCall.args[1]).to.include({
|
|
902
|
-
method: 'PUT',
|
|
903
|
-
headers: {
|
|
904
|
-
Accept: 'application/json',
|
|
905
|
-
'Content-Type': 'application/json',
|
|
906
|
-
Authorization: 'Bearer xxx'
|
|
907
|
-
},
|
|
908
|
-
body: JSON.stringify(content)
|
|
909
|
-
})
|
|
910
|
-
})
|
|
911
|
-
})
|
|
912
|
-
|
|
913
|
-
describe('#del()', () => {
|
|
914
|
-
let api
|
|
915
|
-
let clientStub
|
|
916
|
-
|
|
917
|
-
beforeEach(async () => {
|
|
918
|
-
clientStub = stub()
|
|
919
|
-
api = new Api({
|
|
920
|
-
baseUrl: 'https://example.com/api/v1'
|
|
921
|
-
}, clientStub)
|
|
922
|
-
})
|
|
923
|
-
|
|
924
|
-
it('calls url with query params', async () => {
|
|
925
|
-
clientStub.resolves({
|
|
926
|
-
status: 200,
|
|
927
|
-
json: stub().resolves({}),
|
|
928
|
-
headers: new Map()
|
|
929
|
-
})
|
|
930
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').query({ foo: 'bar', baz: 'qux' }).del()
|
|
931
|
-
expect(clientStub.firstCall.args[0]).to.endWith('/some/url?foo=bar&baz=qux')
|
|
932
|
-
})
|
|
933
|
-
|
|
934
|
-
it('calls url ignoring undefined query params', async () => {
|
|
935
|
-
clientStub.resolves({
|
|
936
|
-
status: 200,
|
|
937
|
-
json: stub().resolves({}),
|
|
938
|
-
headers: new Map()
|
|
939
|
-
})
|
|
940
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').query({ foo: undefined, baz: 'qux' }).del()
|
|
941
|
-
expect(clientStub.firstCall.args[0]).to.endWith('/some/url?baz=qux')
|
|
942
|
-
})
|
|
943
|
-
|
|
944
|
-
it('calls url with delete method', async () => {
|
|
945
|
-
clientStub.resolves({
|
|
946
|
-
status: 200,
|
|
947
|
-
json: stub().resolves({}),
|
|
948
|
-
headers: new Map()
|
|
949
|
-
})
|
|
950
|
-
await api.context({ fetch: clientStub }).endpoint('some/url').del()
|
|
951
|
-
expect(clientStub.firstCall.args[1].method).equals('DELETE')
|
|
952
|
-
})
|
|
953
|
-
})
|
|
954
|
-
})
|