From ce037b8500cd762497114bf8e130fa40de85a86f Mon Sep 17 00:00:00 2001 From: Bastien Caudan Date: Thu, 6 Feb 2020 14:37:50 +0100 Subject: [PATCH] :bug:[RUMF-293][fetch] handle fetch response text error (#252) When consuming a fetch response body, it can be disturbed or locked, a rejected promise is then returned (cf https://fetch.spec.whatwg.org/#concept-body-consume-body). This rejected promise was displayed on the browser console and the corresponding request was not collected. Handle the rejected promise and add the corresponding error to the collected request response. --- packages/core/src/requestCollection.ts | 7 ++++++- packages/core/src/specHelper.ts | 10 +++++++++- packages/core/test/requestCollection.spec.ts | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/core/src/requestCollection.ts b/packages/core/src/requestCollection.ts index 4c3f051f10..e521eb9462 100644 --- a/packages/core/src/requestCollection.ts +++ b/packages/core/src/requestCollection.ts @@ -103,7 +103,12 @@ export function trackFetch(observable: RequestObservable) { type: RequestType.FETCH, }) } else if ('status' in response) { - const text = await response.clone().text() + let text: string + try { + text = await response.clone().text() + } catch (e) { + text = `Unable to retrieve response: ${e}` + } observable.notify({ duration, method, diff --git a/packages/core/src/specHelper.ts b/packages/core/src/specHelper.ts index c8990e40f8..b4ac67b076 100644 --- a/packages/core/src/specHelper.ts +++ b/packages/core/src/specHelper.ts @@ -55,7 +55,14 @@ export class FetchStubBuilder { resolve({ ...response, clone: () => { - const cloned = { text: async () => response.responseText } + const cloned = { + text: async () => { + if (response.responseTextError) { + throw response.responseTextError + } + return response.responseText + }, + } return cloned as Response }, }) as Promise @@ -67,6 +74,7 @@ export class FetchStubBuilder { export interface ResponseStub extends Partial { responseText?: string + responseTextError?: Error } export type FetchStub = (input: RequestInfo, init?: RequestInit) => FetchStubPromise diff --git a/packages/core/test/requestCollection.spec.ts b/packages/core/test/requestCollection.spec.ts index df3c27b262..d7ab1c81a1 100644 --- a/packages/core/test/requestCollection.spec.ts +++ b/packages/core/test/requestCollection.spec.ts @@ -70,6 +70,23 @@ describe('fetch tracker', () => { }) }) + // https://fetch.spec.whatwg.org/#concept-body-consume-body + it('should track fetch with response text error', (done) => { + fetchStub(FAKE_URL).resolveWith({ status: 200, responseTextError: new Error('locked') }) + + fetchStubBuilder.whenAllComplete((requests: RequestDetails[]) => { + const request = requests[0] + expect(request.type).toEqual(RequestType.FETCH) + expect(request.method).toEqual('GET') + expect(request.url).toEqual(FAKE_URL) + expect(request.status).toEqual(200) + expect(request.response).toMatch(/Error: locked/) + expect(isRejected(request)).toBe(false) + expect(isServerError(request)).toBe(false) + done() + }) + }) + it('should track opaque fetch', (done) => { // https://fetch.spec.whatwg.org/#concept-filtered-response-opaque fetchStub(FAKE_URL).resolveWith({ status: 0, type: 'opaque' })