Skip to content

Commit 17d29eb

Browse files
authored
⚠ Force merge pull request #1165 from goodeggs/fix/fetch-error-as-null
Fix: Only append default Fetch error name when Error in `catch` is different than null
2 parents 6c1af84 + 5583fbb commit 17d29eb

File tree

2 files changed

+48
-46
lines changed

2 files changed

+48
-46
lines changed

src/index.test.ts

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ declare global {
2020
}
2121
}
2222

23-
describe('jsonFetch', function () {
23+
describe('jsonFetch', () => {
2424
const {sandbox} = useSinonSandbox();
25-
describe('single request with no retry', function () {
26-
it('resolves with json body for 200 status codes', async function () {
25+
describe('single request with no retry', () => {
26+
it('resolves with json body for 200 status codes', async () => {
2727
nock('http://www.test.com').get('/products/1234').reply(200, {
2828
name: 'apple',
2929
});
@@ -36,7 +36,7 @@ describe('jsonFetch', function () {
3636
expect(response.headers).to.be.ok();
3737
});
3838

39-
it('resolves with JSON body for 500 status codes', async function () {
39+
it('resolves with JSON body for 500 status codes', async () => {
4040
nock('http://www.test.com').get('/products/1234').reply(500, '"Something went wrong"', {
4141
'Content-Type': 'application/json',
4242
});
@@ -46,23 +46,23 @@ describe('jsonFetch', function () {
4646
expect(response.statusText).to.equal('Internal Server Error');
4747
expect(response.headers).to.be.ok();
4848
});
49-
it('resolves with JSON body when content-type contains other values but includes application/json', async function () {
49+
it('resolves with JSON body when content-type contains other values but includes application/json', async () => {
5050
nock('http://www.test.com').get('/products/1234').reply(204, '[{}]', {
5151
'Content-Type': 'application/json; charset=utf-8',
5252
});
5353
const response = await jsonFetch('http://www.test.com/products/1234');
5454
expect(response.body).to.deep.equal([{}]);
5555
});
5656

57-
it('resolves with non-JSON body', async function () {
57+
it('resolves with non-JSON body', async () => {
5858
nock('http://www.test.com').get('/products/1234').reply(200, 'This is not JSON', {
5959
'Content-Type': 'text/plain',
6060
});
6161
const response = await jsonFetch('http://www.test.com/products/1234');
6262
expect(response.body).to.equal(undefined);
6363
});
64-
it('rejects when there is a connection error', async function () {
65-
sandbox.stub(global, 'fetch').callsFake(async function () {
64+
it('rejects when there is a connection error', async () => {
65+
sandbox.stub(global, 'fetch').callsFake(async () => {
6666
throw new Error('Something is broken!');
6767
});
6868
let errorThrown = false;
@@ -79,7 +79,7 @@ describe('jsonFetch', function () {
7979
expect(errorThrown).to.be.true();
8080
});
8181

82-
it('rejects with responseText when there is a json parse error', async function () {
82+
it('rejects with responseText when there is a json parse error', async () => {
8383
nock('http://www.test.com').get('/products/1234').reply(200, 'foo', {
8484
'Content-Type': 'application/json; charset=utf-8',
8585
});
@@ -99,7 +99,7 @@ describe('jsonFetch', function () {
9999
expect(errorThrown).to.be.true();
100100
});
101101

102-
it('sends json request body', async function () {
102+
it('sends json request body', async () => {
103103
nock('http://www.test.com')
104104
.post('/products/1234', {
105105
name: 'apple',
@@ -123,7 +123,7 @@ describe('jsonFetch', function () {
123123
expect(response.headers).to.be.ok();
124124
});
125125

126-
it('calls onRequestStart when is passed to jsonFetch in JsonFetchOptions', async function () {
126+
it('calls onRequestStart when is passed to jsonFetch in JsonFetchOptions', async () => {
127127
const onRequestStart = sandbox.stub();
128128
nock('http://www.test.com').get('/products/1234').reply(200);
129129
await jsonFetch('http://www.test.com/products/1234', {
@@ -138,7 +138,7 @@ describe('jsonFetch', function () {
138138
});
139139
});
140140

141-
it('calls onRequestEnd when is passed to jsonFetch in JsonFetchOptions', async function () {
141+
it('calls onRequestEnd when is passed to jsonFetch in JsonFetchOptions', async () => {
142142
const onRequestEnd = sandbox.stub();
143143
nock('http://www.test.com').get('/products/1234').reply(200);
144144
await jsonFetch('http://www.test.com/products/1234', {
@@ -153,8 +153,8 @@ describe('jsonFetch', function () {
153153
});
154154
});
155155

156-
it('onRequestEnd returns error object when request fails', async function () {
157-
sandbox.stub(global, 'fetch').callsFake(async function () {
156+
it('onRequestEnd returns error object when request fails', async () => {
157+
sandbox.stub(global, 'fetch').callsFake(async () => {
158158
throw new Error('Something is broken!');
159159
});
160160
const onRequestEnd = sandbox.stub();
@@ -175,8 +175,8 @@ describe('jsonFetch', function () {
175175
});
176176
});
177177

178-
describe('expected statuses', function () {
179-
it('errors with FetchUnexpectedStatus if the response has an unexpected status code', async function () {
178+
describe('expected statuses', () => {
179+
it('errors with FetchUnexpectedStatus if the response has an unexpected status code', async () => {
180180
nock('http://www.test.com').get('/products/1234').reply(400, 'not found');
181181

182182
try {
@@ -195,21 +195,21 @@ describe('jsonFetch', function () {
195195
throw new Error('expected to throw');
196196
});
197197

198-
it('returns a response with an expected status code', async function () {
198+
it('returns a response with an expected status code', async () => {
199199
nock('http://www.test.com').get('/products/1234').reply(201, 'not found');
200200
const response = await jsonFetch('http://www.test.com/products/1234', {
201201
expectedStatuses: [201],
202202
});
203203
expect(response).to.have.property('status', 201);
204204
});
205-
it('returns a response without an expected status code', async function () {
205+
it('returns a response without an expected status code', async () => {
206206
nock('http://www.test.com').get('/products/1234').reply(404, 'not found');
207207
const response = await jsonFetch('http://www.test.com/products/1234');
208208
expect(response).to.have.property('status', 404);
209209
});
210210
});
211211

212-
describe('retry', function () {
212+
describe('retry', () => {
213213
let fetchSpy: sinon.SinonSpy<
214214
[input: RequestInfo, init?: RequestInit | undefined],
215215
Promise<Response>
@@ -223,13 +223,13 @@ describe('jsonFetch', function () {
223223
fetchSpy.restore();
224224
});
225225

226-
it('does not retry by default', async function () {
226+
it('does not retry by default', async () => {
227227
nock('http://www.test.com').get('/').reply(200, {});
228228
await jsonFetch('http://www.test.com/');
229229
expect(fetchSpy.callCount).to.equal(1);
230230
});
231231

232-
it('does not retry and calls OnRequest callbacks one single time each by default', async function () {
232+
it('does not retry and calls OnRequest callbacks one single time each by default', async () => {
233233
const onRequestStart = sandbox.stub();
234234
const onRequestEnd = sandbox.stub();
235235
nock('http://www.test.com').get('/').reply(200, {});
@@ -241,7 +241,7 @@ describe('jsonFetch', function () {
241241
expect(onRequestEnd).to.have.been.calledOnce();
242242
});
243243

244-
it('does specified number of retries', async function () {
244+
it('does specified number of retries', async () => {
245245
nock('http://www.test.com').get('/').reply(200, {});
246246

247247
try {
@@ -263,7 +263,7 @@ describe('jsonFetch', function () {
263263
throw new Error('Should have failed');
264264
});
265265

266-
it('respects the shouldRetry() function', async function () {
266+
it('respects the shouldRetry() function', async () => {
267267
nock('http://www.test.com').get('/').times(6).reply(200, {});
268268

269269
try {
@@ -282,7 +282,7 @@ describe('jsonFetch', function () {
282282
});
283283
});
284284

285-
describe('retry network errors', function () {
285+
describe('retry network errors', () => {
286286
let fetchStub: sinon.SinonStub<
287287
[input: RequestInfo, init?: RequestInit | undefined],
288288
Promise<Response>
@@ -296,7 +296,7 @@ describe('jsonFetch', function () {
296296
fetchStub.restore();
297297
});
298298

299-
it('respects the should retry function for a network error', async function () {
299+
it('respects the should retry function for a network error', async () => {
300300
fetchStub.rejects(new Error('ECONRST'));
301301

302302
try {
@@ -316,7 +316,7 @@ describe('jsonFetch', function () {
316316
throw new Error('Should have failed');
317317
});
318318

319-
it('adds the retryCount to the error', async function () {
319+
it('adds the retryCount to the error', async () => {
320320
fetchStub.rejects(new Error('ECONRST'));
321321

322322
try {
@@ -337,7 +337,7 @@ describe('jsonFetch', function () {
337337
throw new Error('Should have failed');
338338
});
339339

340-
it('calls the onRequestStart and onRequestEnd functions in each retry', async function () {
340+
it('calls the onRequestStart and onRequestEnd functions in each retry', async () => {
341341
const onRequestStart = sandbox.stub();
342342
const onRequestEnd = sandbox.stub();
343343

@@ -368,7 +368,7 @@ describe('jsonFetch', function () {
368368
throw new Error('Should have failed');
369369
});
370370

371-
it('call the onRequestStart and onRequestEnd functions when non-retryable setup is passed', async function () {
371+
it('call the onRequestStart and onRequestEnd functions when non-retryable setup is passed', async () => {
372372
const onRequestStart = sandbox.stub();
373373
const onRequestEnd = sandbox.stub();
374374

@@ -388,9 +388,9 @@ describe('jsonFetch', function () {
388388
});
389389
});
390390

391-
describe('retriers', function () {
392-
describe('.is5xx', function () {
393-
it('accepts a 503 and 504 status codes', async function () {
391+
describe('retriers', () => {
392+
describe('.is5xx', () => {
393+
it('accepts a 503 and 504 status codes', async () => {
394394
expect(
395395
retriers.is5xx(
396396
new Response('', {
@@ -407,7 +407,7 @@ describe('jsonFetch', function () {
407407
).to.equal(true);
408408
});
409409

410-
it('rejects all other inputs', async function () {
410+
it('rejects all other inputs', async () => {
411411
expect(retriers.is5xx(new Error(fake.sentence()))).to.equal(false);
412412
expect(
413413
retriers.is5xx(
@@ -460,7 +460,7 @@ describe('jsonFetch', function () {
460460
).to.equal(false);
461461
});
462462

463-
describe('used within jsonFetch', function () {
463+
describe('used within jsonFetch', () => {
464464
let fetchStub: sinon.SinonStub<
465465
[input: RequestInfo, init?: RequestInit | undefined],
466466
Promise<{status: number}>
@@ -474,7 +474,7 @@ describe('jsonFetch', function () {
474474
fetchStub.restore();
475475
});
476476

477-
it('attempts to retry on a 5xx error code', async function () {
477+
it('attempts to retry on a 5xx error code', async () => {
478478
const is5xxSpy = sandbox.spy(retriers, 'is5xx');
479479

480480
fetchStub.resolves({status: 503});
@@ -498,12 +498,12 @@ describe('jsonFetch', function () {
498498
});
499499
});
500500

501-
describe('.isNetworkError', function () {
502-
it('accepts any errors', async function () {
501+
describe('.isNetworkError', () => {
502+
it('accepts any errors', async () => {
503503
expect(retriers.isNetworkError(new Error(fake.sentence()))).to.equal(true);
504504
});
505505

506-
it('rejects any non errors', async function () {
506+
it('rejects any non errors', async () => {
507507
expect(retriers.isNetworkError(new Response('foo'))).to.equal(false);
508508
expect(retriers.isNetworkError(new Response(''))).to.equal(false);
509509
expect(
@@ -522,7 +522,7 @@ describe('jsonFetch', function () {
522522
).to.equal(false);
523523
});
524524

525-
describe('used within jsonFetch', function () {
525+
describe('used within jsonFetch', () => {
526526
let fetchStub: sinon.SinonStub<
527527
[input: RequestInfo, init?: RequestInit | undefined],
528528
Promise<{status: number}>
@@ -536,7 +536,7 @@ describe('jsonFetch', function () {
536536
fetchStub.restore();
537537
});
538538

539-
it('attempts to retry on a network error', async function () {
539+
it('attempts to retry on a network error', async () => {
540540
const isNetworkErrorSpy = sandbox.spy(retriers, 'isNetworkError');
541541
fetchStub.rejects(new Error('ECONRST'));
542542

@@ -560,8 +560,8 @@ describe('jsonFetch', function () {
560560
});
561561
});
562562
});
563-
describe('malformed json', function () {
564-
it('throws error with malformed text', async function () {
563+
describe('malformed json', () => {
564+
it('throws error with malformed text', async () => {
565565
nock('http://www.test.com').get('/products/1234').reply(200, '{"name": "apple""}', {
566566
'Content-Type': 'application/json',
567567
});
@@ -576,15 +576,15 @@ describe('jsonFetch', function () {
576576
throw new Error('expected to throw');
577577
});
578578
});
579-
describe('missing content type', function () {
580-
it('handles it gracefully', async function () {
579+
describe('missing content type', () => {
580+
it('handles it gracefully', async () => {
581581
nock('http://www.test.com').get('/products/1234').reply(200, 'test', {});
582582
const response = await jsonFetch('http://www.test.com/products/1234');
583583
expect(response.body).to.equal(undefined);
584584
});
585585
});
586-
describe('thrown errors', function () {
587-
it('does not include request headers', async function () {
586+
describe('thrown errors', () => {
587+
it('does not include request headers', async () => {
588588
nock('http://www.test.com').get('/products/1234').reply(200, '{""}', {
589589
'Content-Type': 'application/json',
590590
});

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ async function retryFetch(
110110
}, retryOptions);
111111
return response;
112112
} catch (err) {
113-
err.name = 'FetchError';
113+
if (err != null) {
114+
err.name = 'FetchError';
115+
}
114116
throw err;
115117
}
116118
}

0 commit comments

Comments
 (0)