Skip to content

Commit

Permalink
added more tests for http request handler
Browse files Browse the repository at this point in the history
  • Loading branch information
imolorhe committed Nov 3, 2024
1 parent 9bb5364 commit 0f9d967
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ exports[`response-builder auto strategy should concatenate the responses when th
]
`;

exports[`response-builder auto strategy should patch the responses when patchable - sample 2 1`] = `
[
{
"content": "{
"data": {
"bookById": {
"name": "Effective Java",
"author": {
"firstName": "Joshua"
}
}
}
}",
"timestamp": 1718252802585,
},
]
`;

exports[`response-builder auto strategy should patch the responses when the first response is patchable 1`] = `
[
{
Expand Down
83 changes: 83 additions & 0 deletions packages/altair-core/src/request/handlers/http.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,89 @@ describe('HTTP handler', () => {
]);
});

// https://github.com/felipe-gdr/spring-graphql-defer/issues/5
it('should properly handle multipart streamed responses - sample 2', async () => {
const mockHandler = new MswMockRequestHandler(
'http://localhost:3000/multipart-stream-2',
async () => {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
await delay(10);
// this is invalid since there is no boundary before the first content, so it should be ignored as the preamble as per the spec
controller.enqueue(
encoder.encode(
`\r\ncontent-type: application/json; charset=utf-8\r\n\r\n{"data":{"bookById":{"name":"Effective Java"}},"hasNext":true}\r\n---`
)
);
await delay(10);
controller.enqueue(
encoder.encode(
`\r\ncontent-type: application/json; charset=utf-8\r\n\r\n{"hasNext":true,"incremental":[{"path":["bookById"],"data":{"author":{"firstName":"Joshua"}}}]}\r\n---`
)
);
await delay(10);
controller.enqueue(
encoder.encode(
`content-type: application/json; charset=utf-8\r\n\r\n{"hasNext":false,"incremental":[{"path":[],"data":{"book2":{"name":"Hitchhiker's Guide to the Galaxy"}}}]}\r\n-----`
)
);
await delay(10);
controller.close();
},
});

return new Response(stream, {
headers: {
'content-type': 'multipart/mixed; boundary="-"',
},
});
}
);
server.use(mockHandler);
const request: GraphQLRequestOptions = {
url: 'http://localhost:3000/multipart-stream-2',
method: 'POST',
additionalParams: {
testData: [
{
hello: 'world',
},
],
},
headers: [],
query: 'query { hello }',
variables: {},
selectedOperation: 'hello',
};

const httpHandler: GraphQLRequestHandler = new HttpRequestHandler();
const res = await testObserver(httpHandler.handle(request));

expect(res).toEqual([
expect.objectContaining({
ok: true,
data: '{"hasNext":true,"incremental":[{"path":["bookById"],"data":{"author":{"firstName":"Joshua"}}}]}',
headers: expect.any(Object),
status: 200,
url: 'http://localhost:3000/multipart-stream-2',
requestStartTimestamp: expect.any(Number),
requestEndTimestamp: expect.any(Number),
resopnseTimeMs: expect.any(Number),
}),
expect.objectContaining({
ok: true,
data: `{"hasNext":false,"incremental":[{"path":[],"data":{"book2":{"name":"Hitchhiker's Guide to the Galaxy"}}}]}`,
headers: expect.any(Object),
status: 200,
url: 'http://localhost:3000/multipart-stream-2',
requestStartTimestamp: expect.any(Number),
requestEndTimestamp: expect.any(Number),
resopnseTimeMs: expect.any(Number),
}),
]);
});

it('should properly handle multipart streamed responses with errors', async () => {
const mockHandler = new MswMockRequestHandler(
'http://localhost:3000/error-multipart-stream',
Expand Down
2 changes: 1 addition & 1 deletion packages/altair-core/src/request/handlers/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class HttpRequestHandler implements GraphQLRequestHandler {

if (!merosResponse.ok || !merosResponse.body) {
// don't handle streaming
const buffer = await merosResponse.arrayBuffer()
const buffer = await merosResponse.arrayBuffer();
return this.emitChunk(
merosResponse,
new Uint8Array(buffer),
Expand Down
26 changes: 23 additions & 3 deletions packages/altair-core/src/request/response-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,13 @@ describe('response-builder', () => {
const res = buildResponse([
{
content: '{"hello":',
timestamp: 1718252802585
timestamp: 1718252802585,
},
{
content: '"world"}',
timestamp: 1718252802585,
}
])
},
]);
expect(res).toMatchSnapshot();
});

Expand Down Expand Up @@ -380,6 +380,26 @@ describe('response-builder', () => {
expect(res).toMatchSnapshot();
});

// https://github.com/felipe-gdr/spring-graphql-defer/issues/5
it('should patch the responses when patchable - sample 2', () => {
const res = buildResponse([
{
content: `{"data":{"bookById":{"name":"Effective Java"}},"hasNext":true}`,
timestamp: 1718252802585,
},
{
content: `{"hasNext":true,"incremental":[{"path":["bookById"],"data":{"author":{"firstName":"Joshua"}}}]}`,
timestamp: 1718252802585,
},
{
content: `{"hasNext":false,"incremental":[{"path":[],"data":{"book2":{"name":"Hitchhiker's Guide to the Galaxy"}}}]}`,
timestamp: 1718252802585,
},
]);

expect(res).toMatchSnapshot();
});

it('should append the responses when the first response is a JSON object but not patchable', () => {
const res = buildResponse(
[
Expand Down

0 comments on commit 0f9d967

Please sign in to comment.