Skip to content

Commit

Permalink
test(navigation): fix flaky networkidle tests (#1058)
Browse files Browse the repository at this point in the history
The network idle tests were waiting for requests to appear on the server, but not for playwright to be notified of the request via protocol. They also assumed performance.now would match up with setTimeout times.
  • Loading branch information
JoelEinbinder authored Feb 19, 2020
1 parent 84ee297 commit 568c6cb
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions test/navigation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/

const utils = require('./utils');
const { performance } = require('perf_hooks');

/**
* @type {PageTestSuite}
Expand Down Expand Up @@ -396,29 +395,39 @@ module.exports.describe = function({testRunner, expect, playwright, MAC, WIN, FF
expect(response.status()).toBe(200);
});

/**
* @param {import('../src/frames').Frame} frame
* @param {TestServer} server
* @param {'networkidle0'|'networkidle2'} signal
* @param {() => Promise<void>} action
* @param {boolean} isSetContent
*/
async function networkIdleTest(frame, server, signal, action, isSetContent) {
let lastResponseFinished;
const finishResponse = response => {
lastResponseFinished = performance.now();
response.statusCode = 404;
response.end(`File not found`);
};

const waitForRequest = suffix => {
return Promise.all([
server.waitForRequest(suffix),
frame._page.waitForRequest(server.PREFIX + suffix),
])
}
let responses = {};
// Hold on to a bunch of requests without answering.
server.setRoute('/fetch-request-a.js', (req, res) => responses.a = res);
server.setRoute('/fetch-request-b.js', (req, res) => responses.b = res);
server.setRoute('/fetch-request-c.js', (req, res) => responses.c = res);
const initialFetchResourcesRequested = Promise.all([
server.waitForRequest('/fetch-request-a.js'),
server.waitForRequest('/fetch-request-b.js'),
server.waitForRequest('/fetch-request-c.js'),
waitForRequest('/fetch-request-a.js'),
waitForRequest('/fetch-request-b.js'),
waitForRequest('/fetch-request-c.js')
]);

let secondFetchResourceRequested;
if (signal === 'networkidle0') {
server.setRoute('/fetch-request-d.js', (req, res) => responses.d = res);
secondFetchResourceRequested = server.waitForRequest('/fetch-request-d.js');
secondFetchResourceRequested = waitForRequest('/fetch-request-d.js');
}

const waitForLoadPromise = isSetContent ? Promise.resolve() : frame.waitForNavigation({ waitUntil: 'load' });
Expand All @@ -442,10 +451,11 @@ module.exports.describe = function({testRunner, expect, playwright, MAC, WIN, FF
expect(responses.a).toBeTruthy();
expect(responses.b).toBeTruthy();
expect(responses.c).toBeTruthy();
// Finishing first response should leave 2 requests alive and trigger networkidle2.
finishResponse(responses.a);

let timer;
let timerTriggered = false;
if (signal === 'networkidle0') {
// Finishing first response should leave 2 requests alive and trigger networkidle2.
finishResponse(responses.a);
// Finishing two more responses should trigger the second round.
finishResponse(responses.b);
finishResponse(responses.c);
Expand All @@ -454,11 +464,16 @@ module.exports.describe = function({testRunner, expect, playwright, MAC, WIN, FF
await secondFetchResourceRequested;
expect(actionFinished).toBe(false);
// Finishing the last response should trigger networkidle0.
timer = setTimeout(() => timerTriggered = true, 500);
finishResponse(responses.d);
} else {
timer = setTimeout(() => timerTriggered = true, 500);
// Finishing first response should leave 2 requests alive and trigger networkidle2.
finishResponse(responses.a);
}

const response = await actionPromise;
expect(performance.now() - lastResponseFinished).not.toBeLessThan(450);
clearTimeout(timer);
expect(timerTriggered).toBe(true);
if (!isSetContent)
expect(response.ok()).toBe(true);

Expand Down

0 comments on commit 568c6cb

Please sign in to comment.