From 49a7326aef9a21298c4e4928ecdb5afb830dca73 Mon Sep 17 00:00:00 2001 From: vigneshshanmugam Date: Tue, 5 Jan 2021 17:00:31 -0800 Subject: [PATCH 1/2] fix: capture redirected requests in waterfall --- src/plugins/network.ts | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/plugins/network.ts b/src/plugins/network.ts index 799a15a5..ef85f479 100644 --- a/src/plugins/network.ts +++ b/src/plugins/network.ts @@ -51,6 +51,41 @@ export class NetworkManager { const { requestId, request, timestamp, type, loaderId } = event; const { url, method } = request; const isNavigationRequest = requestId == loaderId && type === 'Document'; + const record = this.waterfallMap.get(requestId); + /** + * On redirects, another `requestWillBeSent` event will be fired for the + * same requestId. We calculate the timings for the redirect request using + * the `redirectedResponse` from the redirected request. + */ + if (record) { + if (event.redirectResponse) { + const response = event.redirectResponse; + const data = Object.assign(event, { + type: event.type, + response, + encodedDataLength: response.encodedDataLength, + }); + this._onResponseReceived(data); + this._onLoadingFinished(data); + } else { + /** + * Edge case, we handle it to proceed with next navigation + */ + this._onLoadingFailed( + Object.assign(event, { + type: event.type, + errorText: 'redirectResponse data is not available', + }) + ); + } + const redirectedRecord = this.waterfallMap.get(requestId); + /** + * Rewrite the map with new redirect id to not reset + * the redirect request with original request + */ + this.waterfallMap.delete(requestId); + this.waterfallMap.set(`${requestId}:redirect`, redirectedRecord); + } this.waterfallMap.set(requestId, { step: this._currentStep, From f55697f54d16332231cab9d6818c2f12e1534745 Mon Sep 17 00:00:00 2001 From: vigneshshanmugam Date: Mon, 11 Jan 2021 13:42:48 -0800 Subject: [PATCH 2/2] chore: add tests for redirect --- __tests__/plugins/network.test.ts | 23 ++++++++++++++++++++++- src/plugins/network.ts | 5 ++++- utils/server.ts | 11 ++++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/__tests__/plugins/network.test.ts b/__tests__/plugins/network.test.ts index 494ecc19..9f8a71ef 100644 --- a/__tests__/plugins/network.test.ts +++ b/__tests__/plugins/network.test.ts @@ -36,7 +36,7 @@ describe('network', () => { await server.close(); }); - it('should capture network info', async () => { + it('capture network info', async () => { const driver = await Gatherer.setupDriver(); const network = new NetworkManager(); await network.start(driver.client); @@ -51,4 +51,25 @@ describe('network', () => { }); await Gatherer.dispose(driver); }); + + it('produce distinct events for redirects', async () => { + const driver = await Gatherer.setupDriver(); + const network = new NetworkManager(); + await network.start(driver.client); + /** + * Set up two level of redirects + */ + server.setRedirect('/route1', '/route2'); + server.setRedirect('/route2', '/route3'); + server.route('/route3', (req, res) => { + res.end('route3'); + }); + await driver.page.goto(server.PREFIX + '/route1'); + const netinfo = await network.stop(); + expect(netinfo.length).toEqual(3); + expect(netinfo[0].status).toBe(302); + expect(netinfo[1].status).toBe(302); + expect(netinfo[2].status).toBe(200); + await Gatherer.dispose(driver); + }); }); diff --git a/src/plugins/network.ts b/src/plugins/network.ts index ef85f479..c22a4891 100644 --- a/src/plugins/network.ts +++ b/src/plugins/network.ts @@ -84,7 +84,10 @@ export class NetworkManager { * the redirect request with original request */ this.waterfallMap.delete(requestId); - this.waterfallMap.set(`${requestId}:redirect`, redirectedRecord); + this.waterfallMap.set( + `redirect:${timestamp}:${requestId}`, + redirectedRecord + ); } this.waterfallMap.set(requestId, { diff --git a/utils/server.ts b/utils/server.ts index 963f7e2a..05de0268 100644 --- a/utils/server.ts +++ b/utils/server.ts @@ -30,6 +30,7 @@ import { join } from 'path'; import { AddressInfo } from 'net'; export class Server { + PREFIX: string; TEST_PAGE: string; _server: http.Server; _routes = new Map(); @@ -45,7 +46,15 @@ export class Server { this._server = http.createServer(this._onRequest.bind(this)); this._server.listen(0); const { port } = this._server.address() as AddressInfo; - this.TEST_PAGE = `http://localhost:${port}/index.html`; + this.PREFIX = `http://localhost:${port}`; + this.TEST_PAGE = `${this.PREFIX}/index.html`; + } + + setRedirect(from, to) { + this.route(from, (req, res) => { + res.writeHead(302, { location: to }); + res.end(); + }); } route(path, handler: RequestListener) {