diff --git a/packages/core/src/fetch.test.ts b/packages/core/src/fetch.test.ts index 8a69877..354fb49 100644 --- a/packages/core/src/fetch.test.ts +++ b/packages/core/src/fetch.test.ts @@ -52,12 +52,44 @@ describe('fetch', () => { test('can handle error response', async () => { jest.spyOn(global, 'fetch').mockImplementation(fetchMockResponseTextError); - try { - const data = await createFetch('https://mock.com/test'); - } catch (error) { - const fetchError = error as FetchError; - expect(fetchError.message).toEqual('unexpected error'); - expect(fetchError.httpCode).toEqual(400); - } + let caught: unknown; + await expect( + createFetch('https://mock.com/test').catch((e) => { + caught = e; + throw e; + }) + ).rejects.toMatchObject({ message: 'unexpected error', httpCode: 400 }); + expect(caught).toBeInstanceOf(FetchError); + expect(Object.prototype.hasOwnProperty.call(caught, 'cause')).toBe(false); + }); + + test('keeps the original error as cause', async () => { + const original = new TypeError('fetch failed', { + cause: { code: 'ECONNRESET' } + }); + jest.spyOn(global, 'fetch').mockRejectedValue(original); + + const result = createFetch('https://mock.com/test'); + await expect(result).rejects.toBeInstanceOf(FetchError); + await expect(result).rejects.toMatchObject({ + message: 'fetch failed', + httpCode: undefined, + cause: original + }); + await expect(result).rejects.toHaveProperty( + 'cause.cause.code', + 'ECONNRESET' + ); + await expect(result).rejects.toHaveProperty('cause', original); + }); + + test('keeps a non-Error rejection as cause', async () => { + jest.spyOn(global, 'fetch').mockRejectedValue('boom'); + + const result = createFetch('https://mock.com/test'); + await expect(result).rejects.toMatchObject({ + message: JSON.stringify('boom'), + cause: 'boom' + }); }); }); diff --git a/packages/core/src/fetch.ts b/packages/core/src/fetch.ts index 9a2d88d..b7ab718 100644 --- a/packages/core/src/fetch.ts +++ b/packages/core/src/fetch.ts @@ -53,7 +53,7 @@ export const createFetch = async ( Log().debug(error.httpCode + ': ' + error.message); throw error; } - throw new FetchError({ message: getErrorMessage(error) }); + throw new FetchError({ message: getErrorMessage(error), cause: error }); } }; @@ -65,8 +65,16 @@ const getErrorMessage = (error: unknown) => { export class FetchError extends Error { httpCode?: number; - constructor({ message, httpCode }: { message: string; httpCode?: number }) { - super(message); + constructor({ + message, + httpCode, + cause + }: { + message: string; + httpCode?: number; + cause?: unknown; + }) { + super(message, cause === undefined ? undefined : { cause }); this.httpCode = httpCode; } }