Skip to content

Commit

Permalink
fix: QA-100 stalled request when mocked body is empty and using ppter…
Browse files Browse the repository at this point in the history
… 2.0+
  • Loading branch information
lukaszfiszer committed Feb 27, 2020
1 parent 031f11a commit a823a61
Show file tree
Hide file tree
Showing 7 changed files with 978 additions and 917 deletions.
21 changes: 2 additions & 19 deletions src/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import {
waitFor,
TimeoutError,
nth,
getCorsHeaders,
sanitizeHeaders,
requestToPlainObject,
getRequestOrigin,
} from './utils';
Expand Down Expand Up @@ -57,7 +55,7 @@ export class Mock {
this.options = { ...this.options, ...options };
this.debug(
'+',
`created mock: method=${filter.method} url=${filter.url}`
`created mock: method=${filter.method || ''} url=${filter.url}`
);
}

Expand Down Expand Up @@ -128,22 +126,7 @@ export class Mock {
? this.response(serializedRequest)
: this.response;

const status = response.status || 200;

// Set default value of Content-Type header
const headers = sanitizeHeaders({
['content-type']: `'application/json';charset=UTF-8`,
...getCorsHeaders(request),
...response.headers,
});

// Serialize JSON response
const body =
typeof response.body !== 'string'
? JSON.stringify(response.body)
: response.body;

return { status, headers, body };
return response;
}

private getRequestMatch(
Expand Down
55 changes: 44 additions & 11 deletions src/mocketeer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
createRequestFilter,
getCorsHeaders,
sanitizeHeaders,
printResponse,
} from './utils';

const interceptedTypes: ResourceType[] = ['xhr', 'fetch'];
Expand Down Expand Up @@ -122,9 +123,7 @@ export class Mocketeer {
const should404 =
interceptedTypes.indexOf(request.resourceType()) !== -1;

debug(
`> req: type=${request.resourceType()} method=${request.method()} url=${request.url()} `
);
debug(`> req: ${printRequest(request)} `);

// Handle preflight requests
if (request.method() === 'OPTIONS') {
Expand All @@ -138,15 +137,49 @@ export class Mocketeer {
const response = mock.getResponseForRequest(request);

if (response) {
const status = response.status || 200;

// Convert response body to Buffer.
// A bug in puppeteer causes stalled response when body is equal to "" or undefined.
// Providing response as Buffer fixes it.
let body: Buffer;
if (typeof response.body === 'string') {
body = Buffer.from(response.body);
} else if (
response.body === undefined ||
response.body === null
) {
body = Buffer.alloc(0);
} else {
try {
body = Buffer.from(JSON.stringify(response.body));
} catch (e) {
// Response body in either not JSON-serializable or something else
// that cannot be handled. In this case we throw an error
console.error('Could not serialize response body', e);
throw e;
}
}

// Set default value of Content-Type header
const headers = sanitizeHeaders({
'content-length': String(body.length),
'content-type':
body.length > 0
? `application/json; charset=utf-8`
: '',
...getCorsHeaders(request),
...response.headers,
});

try {
debug(
`< res: status=${
response.status
} headers=${JSON.stringify(response.headers)} body=${
response.body
}`
);
return await request.respond(response);
await request.respond({
status,
headers,
body,
});
debug(`< res: ${printResponse(status, headers, body)}`);
return;
} catch (e) {
console.error(
`Failed to reply with mocked response for ${printRequest(
Expand Down
13 changes: 12 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export function waitFor(fn: () => boolean, timeout = 100): Promise<void> {
}

export function printRequest(request: Request): string {
return `${request.resourceType()} ${request.method()} ${request.url()}`;
return `type=${request.resourceType()} method=${request.method() ||
''} url=${request.url() || ''}`;
}

export function nth(d: number): string {
Expand Down Expand Up @@ -143,3 +144,13 @@ export function sanitizeHeaders(headers: Headers): Headers {
return acc;
}, {});
}

export function printResponse(
status: number,
headers: Record<string, string>,
body: Buffer
): string {
const headersStr = JSON.stringify(headers);
const bodyStr = body.toString('utf8');
return `status=${status} headers=${headersStr} body=${bodyStr}`;
}
16 changes: 16 additions & 0 deletions test/integration/mocketeer.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,4 +688,20 @@ describe('Mocketeer integration', () => {
await page.waitForNavigation();
await expect(page.title()).resolves.toEqual('page1');
});

test('set correct response headers when response body is empty', async () => {
await mocketeer.mock('/example', { status: 200 });
const response = await makeRequest('GET', '/example');
expect(response.headers['content-length']).toBe('0');
expect(response.headers['content-type']).toBe(undefined);
});

test('set correct response headers when response body is not empty', async () => {
await mocketeer.mock('/example', { status: 200, body: { ok: 'yes' } });
const response = await makeRequest('GET', '/example');
expect(response.headers['content-length']).toBe('12');
expect(response.headers['content-type']).toContain(
'application/json; charset=utf-8'
);
});
});
3 changes: 3 additions & 0 deletions test/unit/__snapshots__/utils.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`printResponse() 1`] = `"status=200 headers={\\"content-type\\":\\"text/html; charset=utf-8\\",\\"date\\":\\"Thu, 13 Feb 2020 17:03:57 GMT\\",\\"content-language\\":\\"de-DE, en-CA\\"} body={\\"foo\\":\\"bar\\"}"`;
15 changes: 15 additions & 0 deletions test/unit/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
waitFor,
addMockByPriority,
createRequestFilter,
printResponse,
} from '../../src/utils';
import { createRestMock, Request } from './fixtures/request';

Expand Down Expand Up @@ -169,3 +170,17 @@ describe('createRequestMatcher', () => {
});
});
});

test('printResponse()', () => {
expect(
printResponse(
200,
{
'content-type': 'text/html; charset=utf-8',
date: 'Thu, 13 Feb 2020 17:03:57 GMT',
'content-language': 'de-DE, en-CA',
},
Buffer.from(JSON.stringify({ foo: 'bar' }))
)
).toMatchSnapshot();
});
Loading

0 comments on commit a823a61

Please sign in to comment.