2020-08-05 02:32:10 +03:00
|
|
|
/**
|
|
|
|
* Copyright 2018 Google Inc. All rights reserved.
|
|
|
|
* Modifications copyright (c) Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-03-23 20:07:15 +03:00
|
|
|
import { it, expect } from '../fixtures';
|
|
|
|
import type { Route } from '../..';
|
2020-08-05 02:32:10 +03:00
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should pick up ongoing navigation', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
let response = null;
|
|
|
|
server.setRoute('/one-style.css', (req, res) => response = res);
|
|
|
|
await Promise.all([
|
|
|
|
server.waitForRequest('/one-style.css'),
|
|
|
|
page.goto(server.PREFIX + '/one-style.html', {waitUntil: 'domcontentloaded'}),
|
|
|
|
]);
|
|
|
|
const waitPromise = page.waitForLoadState();
|
|
|
|
response.statusCode = 404;
|
|
|
|
response.end('Not found');
|
|
|
|
await waitPromise;
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should respect timeout', async ({page, server}) => {
|
2020-08-12 01:50:53 +03:00
|
|
|
server.setRoute('/one-style.css', (req, res) => void 0);
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.PREFIX + '/one-style.html', {waitUntil: 'domcontentloaded'});
|
|
|
|
const error = await page.waitForLoadState('load', { timeout: 1 }).catch(e => e);
|
|
|
|
expect(error.message).toContain('page.waitForLoadState: Timeout 1ms exceeded.');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should resolve immediately if loaded', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.PREFIX + '/one-style.html');
|
|
|
|
await page.waitForLoadState();
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should throw for bad state', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.PREFIX + '/one-style.html');
|
2020-09-09 13:06:52 +03:00
|
|
|
// @ts-expect-error 'bad' is not a valid load state
|
|
|
|
const error = await page.waitForLoadState('bad').catch(e => e);
|
2020-08-05 02:32:10 +03:00
|
|
|
expect(error.message).toContain(`state: expected one of (load|domcontentloaded|networkidle)`);
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should resolve immediately if load state matches', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
2020-08-12 01:50:53 +03:00
|
|
|
server.setRoute('/one-style.css', (req, res) => void 0);
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.PREFIX + '/one-style.html', {waitUntil: 'domcontentloaded'});
|
|
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should work with pages that have loaded before being connected to', async ({page, context, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
2020-08-28 14:20:29 +03:00
|
|
|
page.evaluate(() => window['_popup'] = window.open(document.location.href)),
|
2020-08-05 02:32:10 +03:00
|
|
|
]);
|
|
|
|
// The url is about:blank in FF.
|
|
|
|
// expect(popup.url()).toBe(server.EMPTY_PAGE);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(popup.url()).toBe(server.EMPTY_PAGE);
|
|
|
|
});
|
|
|
|
|
2020-09-11 20:02:07 +03:00
|
|
|
it('should wait for load state of empty url popup', async ({page, isFirefox}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
const [popup, readyState] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.evaluate(() => {
|
|
|
|
const popup = window.open('');
|
|
|
|
return popup.document.readyState;
|
|
|
|
}),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
2020-09-11 20:02:07 +03:00
|
|
|
expect(readyState).toBe(isFirefox ? 'uninitialized' : 'complete');
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe(isFirefox ? 'uninitialized' : 'complete');
|
2020-08-05 02:32:10 +03:00
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should wait for load state of about:blank popup ', async ({browser, page}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.evaluate(() => window.open('about:blank') && 1),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should wait for load state of about:blank popup with noopener ', async ({browser, page}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.evaluate(() => window.open('about:blank', null, 'noopener') && 1),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should wait for load state of popup with network url ', async ({browser, page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.evaluate(url => window.open(url) && 1, server.EMPTY_PAGE),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should wait for load state of popup with network url and noopener ', async ({browser, page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.evaluate(url => window.open(url, null, 'noopener') && 1, server.EMPTY_PAGE),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should work with clicking target=_blank', async ({browser, page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
|
|
|
await page.setContent('<a target=_blank rel="opener" href="/one-style.html">yo</a>');
|
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.click('a'),
|
|
|
|
]);
|
|
|
|
await popup.waitForLoadState();
|
|
|
|
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should wait for load state of newPage', async ({browser, context, page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
const [newPage] = await Promise.all([
|
|
|
|
context.waitForEvent('page'),
|
|
|
|
context.newPage(),
|
|
|
|
]);
|
|
|
|
await newPage.waitForLoadState();
|
|
|
|
expect(await newPage.evaluate(() => document.readyState)).toBe('complete');
|
|
|
|
});
|
|
|
|
|
2021-03-23 20:07:15 +03:00
|
|
|
it('should resolve after popup load', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.EMPTY_PAGE);
|
|
|
|
// Stall the 'load' by delaying css.
|
|
|
|
let cssResponse;
|
|
|
|
server.setRoute('/one-style.css', (req, res) => cssResponse = res);
|
|
|
|
const [popup] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
server.waitForRequest('/one-style.css'),
|
2020-08-28 14:20:29 +03:00
|
|
|
page.evaluate(url => window['popup'] = window.open(url), server.PREFIX + '/one-style.html'),
|
2020-08-05 02:32:10 +03:00
|
|
|
]);
|
|
|
|
let resolved = false;
|
|
|
|
const loadSatePromise = popup.waitForLoadState().then(() => resolved = true);
|
|
|
|
// Round trips!
|
|
|
|
for (let i = 0; i < 5; i++)
|
|
|
|
await page.evaluate('window');
|
|
|
|
expect(resolved).toBe(false);
|
|
|
|
cssResponse.end('');
|
|
|
|
await loadSatePromise;
|
|
|
|
expect(resolved).toBe(true);
|
|
|
|
expect(popup.url()).toBe(server.PREFIX + '/one-style.html');
|
|
|
|
});
|
|
|
|
|
2020-08-28 14:20:29 +03:00
|
|
|
it('should work for frame', async ({page, server}) => {
|
2020-08-05 02:32:10 +03:00
|
|
|
await page.goto(server.PREFIX + '/frames/one-frame.html');
|
|
|
|
const frame = page.frames()[1];
|
|
|
|
|
2020-08-12 01:50:53 +03:00
|
|
|
const requestPromise = new Promise<Route>(resolve => page.route(server.PREFIX + '/one-style.css',resolve));
|
2020-08-05 02:32:10 +03:00
|
|
|
await frame.goto(server.PREFIX + '/one-style.html', {waitUntil: 'domcontentloaded'});
|
|
|
|
const request = await requestPromise;
|
|
|
|
let resolved = false;
|
|
|
|
const loadPromise = frame.waitForLoadState().then(() => resolved = true);
|
|
|
|
// give the promise a chance to resolve, even though it shouldn't
|
|
|
|
await page.evaluate('1');
|
|
|
|
expect(resolved).toBe(false);
|
|
|
|
request.continue();
|
|
|
|
await loadPromise;
|
|
|
|
});
|