feat(navigation): early return when navigation was canceled by another one (#459)

Also added related interception tests.
This commit is contained in:
Dmitry Gozman 2020-01-10 17:33:07 -08:00 committed by Pavel Feldman
parent 7a7ff9e994
commit 67e4214146
3 changed files with 57 additions and 0 deletions

View File

@ -945,6 +945,11 @@ class LifecycleWatcher {
}
_onCommittedNewDocumentNavigation(frame: Frame) {
if (frame === this._frame && this._expectedDocumentId !== undefined && this._navigationRequest &&
frame._lastDocumentId !== this._expectedDocumentId) {
this._navigationAbortedCallback(new Error('Navigation to ' + this._targetUrl + ' was canceled by another one'));
return;
}
if (frame === this._frame && this._expectedDocumentId === undefined && this._urlMatches(frame.url())) {
this._expectedDocumentId = frame._lastDocumentId;
this._targetUrl = frame.url();

View File

@ -384,6 +384,49 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
await page.goto(server.EMPTY_PAGE);
expect(error.message).toContain('Request Interception is not enabled');
});
it.skip(WEBKIT)('should intercept main resource during cross-process navigation', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.setRequestInterception(true);
let intercepted = false;
page.on('request', request => {
if (request.url().includes(server.CROSS_PROCESS_PREFIX + '/empty.html'))
intercepted = true;
request.continue();
});
const response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
expect(response.ok()).toBe(true);
expect(intercepted).toBe(true);
});
it('should not throw when continued after navigation', async({page, server}) => {
await page.setRequestInterception(true);
page.on('request', request => {
if (request.url() !== server.PREFIX + '/one-style.css')
request.continue();
});
// For some reason, Firefox issues load event with one outstanding request.
const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e);
const request = await page.waitForRequest(server.PREFIX + '/one-style.css');
await page.goto(server.PREFIX + '/empty.html');
const error = await failed;
expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one');
const notAnError = await request.continue().then(() => null).catch(e => e);
expect(notAnError).toBe(null);
});
it.skip(WEBKIT)('should not throw when continued after cross-process navigation', async({page, server}) => {
await page.setRequestInterception(true);
page.on('request', request => {
if (request.url() !== server.PREFIX + '/one-style.css')
request.continue();
});
// For some reason, Firefox issues load event with one outstanding request.
const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e);
const request = await page.waitForRequest(server.PREFIX + '/one-style.css');
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
const error = await failed;
expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one');
const notAnError = await request.continue().then(() => null).catch(e => e);
expect(notAnError).toBe(null);
});
});
describe('Interception.continue', function() {

View File

@ -353,6 +353,15 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME
expect(request2.headers['referer']).toBe(undefined);
expect(page.url()).toBe(server.PREFIX + '/grid.html');
});
it('should fail when canceled by another navigation', async({page, server}) => {
server.setRoute('/one-style.css', (req, res) => {});
// For some reason, Firefox issues load event with one outstanding request.
const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e);
await server.waitForRequest('/one-style.css');
await page.goto(server.PREFIX + '/empty.html');
const error = await failed;
expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one');
});
describe('network idle', function() {
it('should navigate to empty page with networkidle0', async({page, server}) => {