From d3531c50ff8653b2d19b199285eba37ddffeddde Mon Sep 17 00:00:00 2001 From: Evan Brodie Date: Tue, 21 Jan 2025 17:54:22 -0500 Subject: [PATCH] [graphql-client] Improves error handling for missing Response.body in multipart requests --- .changeset/funny-mangos-study.md | 5 ++++ .../src/graphql-client/graphql-client.ts | 2 +- .../client-requestStream.test.ts | 30 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .changeset/funny-mangos-study.md diff --git a/.changeset/funny-mangos-study.md b/.changeset/funny-mangos-study.md new file mode 100644 index 0000000000..438ac2b9d8 --- /dev/null +++ b/.changeset/funny-mangos-study.md @@ -0,0 +1,5 @@ +--- +'@shopify/graphql-client': patch +--- + +Better error handling for missing Response.body in multipart requests. Instead of being "Cannot read properties of undefined (reading 'Symbol(Symbol.asyncIterator)')", it will now be the more useful and accurate message "API multipart response did not return an iterable body". diff --git a/packages/api-clients/graphql-client/src/graphql-client/graphql-client.ts b/packages/api-clients/graphql-client/src/graphql-client/graphql-client.ts index 59b93875f0..fe3b3cb428 100644 --- a/packages/api-clients/graphql-client/src/graphql-client/graphql-client.ts +++ b/packages/api-clients/graphql-client/src/graphql-client/graphql-client.ts @@ -365,7 +365,7 @@ function createMultipartResponseAsyncInterator( if ( !response.body?.getReader && - !(response.body as any)![Symbol.asyncIterator] + !(response.body as any)?.[Symbol.asyncIterator] ) { throw new Error('API multipart response did not return an iterable body', { cause: response, diff --git a/packages/api-clients/graphql-client/src/graphql-client/tests/graphql-client/client-requestStream.test.ts b/packages/api-clients/graphql-client/src/graphql-client/tests/graphql-client/client-requestStream.test.ts index db02442778..b0cbed8092 100644 --- a/packages/api-clients/graphql-client/src/graphql-client/tests/graphql-client/client-requestStream.test.ts +++ b/packages/api-clients/graphql-client/src/graphql-client/tests/graphql-client/client-requestStream.test.ts @@ -712,6 +712,36 @@ describe('GraphQL Client', () => { }); }); + it('returns an async iterator that returns a response object with an error when Response.body is undefined', async () => { + const mockedResponse = new Response(undefined, { + status: 200, + headers: new Headers({ + 'Content-Type': 'multipart/mixed; boundary=graphql', + }), + }); + Object.defineProperty(mockedResponse, 'body', { + value: undefined, + writable: true, + }); + + fetchMock.mockResolvedValue(mockedResponse); + + const responseStream = await client.requestStream(operation); + + const results: any = []; + for await (const response of responseStream) { + results.push(response); + } + + expect(results[0].errors).toEqual({ + message: + 'GraphQL Client: API multipart response did not return an iterable body', + networkStatusCode: 200, + response: mockedResponse, + }); + expect(results[0].data).toBeUndefined(); + }); + it('returns an async iterator that returns a response object with no data value and a JSON parsing error if the returned data is a malformed JSON', async () => { const multipleResponsesArray = [ `