api(context): get rid of PageEvent (#1433)
This commit is contained in:
parent
3ed9970b33
commit
535b484637
60
docs/api.md
60
docs/api.md
|
|
@ -9,7 +9,6 @@
|
|||
- [class: Browser](#class-browser)
|
||||
- [class: BrowserContext](#class-browsercontext)
|
||||
- [class: Page](#class-page)
|
||||
- [class: PageEvent](#class-pageevent)
|
||||
- [class: Frame](#class-frame)
|
||||
- [class: ElementHandle](#class-elementhandle)
|
||||
- [class: JSHandle](#class-jshandle)
|
||||
|
|
@ -312,19 +311,22 @@ Emitted when Browser context gets closed. This might happen because of one of th
|
|||
- The [`browser.close`](#browserclose) method was called.
|
||||
|
||||
#### event: 'page'
|
||||
- <[PageEvent]>
|
||||
- <[Page]>
|
||||
|
||||
Emitted when a new Page is created in the BrowserContext. The event will also fire for popup
|
||||
pages. See also [`Page.on('popup')`](#event-popup) to receive events about popups relevant to a specific page.
|
||||
The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event will also fire for popup pages. See also [`Page.on('popup')`](#event-popup) to receive events about popups relevant to a specific page.
|
||||
|
||||
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is done and its response has started loading in the popup.
|
||||
|
||||
```js
|
||||
const [event] = await Promise.all([
|
||||
const [page] = await Promise.all([
|
||||
context.waitForEvent('page'),
|
||||
page.click('a[target=_blank]'),
|
||||
]);
|
||||
const newPage = await event.page();
|
||||
console.log(await page.evaluate('location.href'));
|
||||
```
|
||||
|
||||
> **NOTE** Use [Page.waitForLoadState](#pagewaitforloadstateoptions) to wait until the page gets to a particular state (you should not need it in most cases).
|
||||
|
||||
#### browserContext.addCookies(cookies)
|
||||
- `cookies` <[Array]<[Object]>>
|
||||
- `name` <[string]> **required**
|
||||
|
|
@ -765,25 +767,20 @@ Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/We
|
|||
Emitted when an uncaught exception happens within the page.
|
||||
|
||||
#### event: 'popup'
|
||||
- <[PageEvent]> Page event corresponding to "popup" window
|
||||
- <[Page]> Page corresponding to "popup" window
|
||||
|
||||
Emitted when the page opens a new tab or window. This event is emitted in addition to the [`browserContext.on('page')`](#event-page), but only for popups relevant to this page.
|
||||
|
||||
```js
|
||||
const [event] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.click('a[target=_blank]'),
|
||||
]);
|
||||
const popup = await event.page();
|
||||
```
|
||||
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is done and its response has started loading in the popup.
|
||||
|
||||
```js
|
||||
const [event] = await Promise.all([
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('https://example.com')),
|
||||
]);
|
||||
const popup = await event.page();
|
||||
console.log(await popup.evaluate('location.href'));
|
||||
```
|
||||
> **NOTE** Use [Page.waitForLoadState](#pagewaitforloadstateoptions) to wait until the page gets to a particular state (you should not need it in most cases).
|
||||
|
||||
#### event: 'request'
|
||||
- <[Request]>
|
||||
|
|
@ -1815,34 +1812,6 @@ This method returns all of the dedicated [WebWorkers](https://developer.mozilla.
|
|||
|
||||
> **NOTE** This does not contain ServiceWorkers
|
||||
|
||||
### class: PageEvent
|
||||
|
||||
Event object passed to the listeners of [`browserContext.on('page')`](#event-page) and [`page.on('popup')`](#event-popup) events. Provides access to the newly created page.
|
||||
|
||||
#### pageEvent.page([options])
|
||||
- `options` <[Object]>
|
||||
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout), [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout), [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
|
||||
- `waitUntil` <"load"|"domcontentloaded"|"networkidle0"|"networkidle2"|"nowait"> When to consider the page to be loaded, defaults to `load`. Events can be either:
|
||||
- `'nowait'` - navigation is committed, new url is displayed in the browser address bar.
|
||||
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
|
||||
- `'load'` - consider navigation to be finished when the `load` event is fired.
|
||||
- `'networkidle0'` - consider navigation to be finished when there are no more than 0 network connections for at least `500` ms.
|
||||
- `'networkidle2'` - consider navigation to be finished when there are no more than 2 network connections for at least `500` ms.
|
||||
- returns: <[Promise]<[Page]>> Promise which resolves to the created page once it loads, according to `waitUntil` option.
|
||||
|
||||
This resolves when the page reaches a required load state, `load` by default. The earliest moment that page is available is when it has navigated to the initial url (corresponds to `{waitUntil: 'nowait'}` option). For example, when opening a popup with `window.open('http://example.com')`, this method will wait until the network request to "http://example.com" is done and its response has started loading in the popup. Passing different `waitUntil` options will also wait for the particular load state to happen, e.g. default `load` waits until the load event fires.
|
||||
|
||||
```js
|
||||
const [, popup] = await Promise.all([
|
||||
// Click opens a popup window.
|
||||
page.click('button'),
|
||||
// Resolves after popup has fired 'DOMContentLoaded' event.
|
||||
page.waitForEvent('popup').then(event => event.page({ waitUntil: 'domcontentloaded' })),
|
||||
]);
|
||||
```
|
||||
|
||||
> **NOTE** Some pages will never fire `load` event. In this case, default `pageEvent.page()` without options will timeout - try using `pageEvent.page({ waitUntil: 'domcontentloaded' })` instead.
|
||||
|
||||
### class: Frame
|
||||
|
||||
At every point of time, page exposes its current frame tree via the [page.mainFrame()](#pagemainframe) and [frame.childFrames()](#framechildframes) methods.
|
||||
|
|
@ -3836,7 +3805,7 @@ const backgroundPage = await backroundPageTarget.page();
|
|||
<!-- GEN:stop -->
|
||||
|
||||
#### event: 'backgroundpage'
|
||||
- <[PageEvent]>
|
||||
- <[Page]>
|
||||
|
||||
Emitted when new background page is created in the context.
|
||||
|
||||
|
|
@ -4101,7 +4070,6 @@ const { chromium } = require('playwright');
|
|||
[Mouse]: #class-mouse "Mouse"
|
||||
[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object "Object"
|
||||
[Page]: #class-page "Page"
|
||||
[PageEvent]: #class-pageevent "PageEvent"
|
||||
[Playwright]: #class-playwright "Playwright"
|
||||
[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise"
|
||||
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export { Frame } from './frames';
|
|||
export { Keyboard, Mouse } from './input';
|
||||
export { JSHandle } from './javascript';
|
||||
export { Request, Response, Route } from './network';
|
||||
export { FileChooser, Page, PageEvent, Worker } from './page';
|
||||
export { FileChooser, Page, Worker } from './page';
|
||||
export { Selectors } from './selectors';
|
||||
|
||||
export { CRBrowser as ChromiumBrowser } from './chromium/crBrowser';
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, Bro
|
|||
import { Events as CommonEvents } from '../events';
|
||||
import { assert, debugError, helper } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { Page, PageBinding, PageEvent, Worker } from '../page';
|
||||
import { Page, PageBinding, Worker } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import * as types from '../types';
|
||||
|
|
@ -129,19 +129,22 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
|
|||
const { context, target } = this._createTarget(targetInfo, session);
|
||||
|
||||
if (CRTarget.isPageType(targetInfo.type)) {
|
||||
const pageEvent = new PageEvent(context, target.pageOrError());
|
||||
target.pageOrError().then(async () => {
|
||||
const page = target._crPage!.page();
|
||||
if (targetInfo.type === 'page') {
|
||||
this._firstPageCallback();
|
||||
context.emit(CommonEvents.BrowserContext.Page, pageEvent);
|
||||
context.emit(CommonEvents.BrowserContext.Page, page);
|
||||
const opener = target.opener();
|
||||
if (!opener)
|
||||
return;
|
||||
// Opener page must have been initialized already and resumed in order to
|
||||
// create this popup but there is a chance that not all responses have been
|
||||
// received yet so we cannot use opener._crPage?.page()
|
||||
const openerPage = await opener.pageOrError();
|
||||
if (openerPage instanceof Page && !openerPage.isClosed())
|
||||
openerPage.emit(CommonEvents.Page.Popup, pageEvent);
|
||||
openerPage.emit(CommonEvents.Page.Popup, page);
|
||||
} else if (targetInfo.type === 'background_page') {
|
||||
context.emit(Events.CRBrowserContext.BackgroundPage, pageEvent);
|
||||
context.emit(Events.CRBrowserContext.BackgroundPage, page);
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, Bro
|
|||
import { Events } from '../events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { Page, PageBinding, PageEvent } from '../page';
|
||||
import { Page, PageBinding } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import * as types from '../types';
|
||||
|
|
@ -130,15 +130,15 @@ export class FFBrowser extends platform.EventEmitter implements Browser {
|
|||
const ffPage = new FFPage(session, context, opener);
|
||||
this._ffPages.set(targetId, ffPage);
|
||||
|
||||
const pageEvent = new PageEvent(context, ffPage.pageOrError());
|
||||
ffPage.pageOrError().then(async () => {
|
||||
this._firstPageCallback();
|
||||
context.emit(Events.BrowserContext.Page, pageEvent);
|
||||
const page = ffPage._page;
|
||||
context.emit(Events.BrowserContext.Page, page);
|
||||
if (!opener)
|
||||
return;
|
||||
const openerPage = await opener.pageOrError();
|
||||
if (openerPage instanceof Page && !openerPage.isClosed())
|
||||
openerPage.emit(Events.Page.Popup, pageEvent);
|
||||
openerPage.emit(Events.Page.Popup, page);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
42
src/page.ts
42
src/page.ts
|
|
@ -87,48 +87,6 @@ export type FileChooser = {
|
|||
multiple: boolean
|
||||
};
|
||||
|
||||
export class PageEvent {
|
||||
private readonly _browserContext: BrowserContextBase;
|
||||
private readonly _pageOrError: Promise<Page | Error>;
|
||||
private readonly _lifecyclePromises = new Map<types.LifecycleEvent, Promise<Page | Error>>();
|
||||
|
||||
constructor(browserContext: BrowserContextBase, pageOrErrorPromise: Promise<Page | Error>) {
|
||||
this._browserContext = browserContext;
|
||||
this._pageOrError = pageOrErrorPromise;
|
||||
for (const lifecycle of types.kLifecycleEvents)
|
||||
this._lifecyclePromises.set(lifecycle, this._createLifecyclePromise(lifecycle));
|
||||
}
|
||||
|
||||
async _createLifecyclePromise(lifecycle: types.LifecycleEvent): Promise<Page | Error> {
|
||||
const page = await this._pageOrError;
|
||||
if (!(page instanceof Page))
|
||||
return page;
|
||||
|
||||
try {
|
||||
const frameTask = new frames.FrameTask(page.mainFrame(), { timeout: 0 });
|
||||
await frameTask.waitForLifecycle(lifecycle);
|
||||
frameTask.done();
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
async page(options: types.TimeoutOptions & { waitUntil?: types.LifecycleEvent | 'nowait' } = {}): Promise<Page> {
|
||||
const {
|
||||
timeout = this._browserContext._timeoutSettings.navigationTimeout(),
|
||||
waitUntil = 'load',
|
||||
} = options;
|
||||
const lifecyclePromise = waitUntil === 'nowait' ? this._pageOrError : this._lifecyclePromises.get(waitUntil);
|
||||
if (!lifecyclePromise)
|
||||
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);
|
||||
const pageOrError = await helper.waitWithTimeout(lifecyclePromise, `"${waitUntil}"`, timeout);
|
||||
if (pageOrError instanceof Page)
|
||||
return pageOrError;
|
||||
throw pageOrError;
|
||||
}
|
||||
}
|
||||
|
||||
export class Page extends platform.EventEmitter {
|
||||
private _closed = false;
|
||||
private _closedCallback: () => void;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, Bro
|
|||
import { Events } from '../events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { Page, PageBinding, PageEvent } from '../page';
|
||||
import { Page, PageBinding } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import * as types from '../types';
|
||||
|
|
@ -137,15 +137,16 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
|
|||
const wkPage = new WKPage(context, pageProxySession, opener || null, hasInitialAboutBlank);
|
||||
this._wkPages.set(pageProxyId, wkPage);
|
||||
|
||||
const pageEvent = new PageEvent(context, wkPage.pageOrError());
|
||||
wkPage.pageOrError().then(async () => {
|
||||
this._firstPageCallback();
|
||||
context!.emit(Events.BrowserContext.Page, pageEvent);
|
||||
const page = wkPage._page;
|
||||
context!.emit(Events.BrowserContext.Page, page);
|
||||
if (!opener)
|
||||
return;
|
||||
const openerPage = await opener.pageOrError();
|
||||
if (openerPage instanceof Page && !openerPage.isClosed())
|
||||
openerPage.emit(Events.Page.Popup, pageEvent);
|
||||
await opener.pageOrError();
|
||||
const openerPage = opener._page;
|
||||
if (!openerPage.isClosed())
|
||||
openerPage.emit(Events.Page.Popup, page);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
utils.waitEvent(page, 'popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
||||
]);
|
||||
expect(popup.context()).toBe(context);
|
||||
|
|
@ -479,24 +479,25 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
});
|
||||
});
|
||||
|
||||
describe('Events.BrowserContext.PageEvent', function() {
|
||||
it.fail(FFOX)('should have url with nowait', async({browser, server}) => {
|
||||
describe('Events.BrowserContext.Page', function() {
|
||||
it.fail(FFOX)('should have url', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
context.waitForEvent('page').then(event => event.page({ waitUntil: 'nowait' })),
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
||||
]);
|
||||
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
||||
await context.close();
|
||||
});
|
||||
it('should have url with domcontentloaded', async({browser, server}) => {
|
||||
it('should have url after domcontentloaded', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
context.waitForEvent('page').then(event => event.page({ waitUntil: 'domcontentloaded' })),
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
||||
]);
|
||||
await otherPage.waitForLoadState({ waitUntil: 'domcontentloaded' });
|
||||
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
||||
await context.close();
|
||||
});
|
||||
|
|
@ -504,9 +505,10 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
context.waitForEvent('page').then(event => event.page({ waitUntil: 'domcontentloaded' })),
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(url => window.open(url), 'about:blank')
|
||||
]);
|
||||
await otherPage.waitForLoadState({ waitUntil: 'domcontentloaded' });
|
||||
expect(otherPage.url()).toBe('about:blank');
|
||||
await context.close();
|
||||
});
|
||||
|
|
@ -514,19 +516,21 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
context.waitForEvent('page').then(event => event.page({ waitUntil: 'domcontentloaded' })),
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(() => window.open())
|
||||
]);
|
||||
await otherPage.waitForLoadState({ waitUntil: 'domcontentloaded' });
|
||||
expect(otherPage.url()).toBe('about:blank');
|
||||
await context.close();
|
||||
});
|
||||
it('should report when a new page is created and closed', async({browser, server}) => {
|
||||
it.fail(FFOX)('should report when a new page is created and closed', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
context.waitForEvent('page').then(event => event.page()),
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(url => window.open(url), server.CROSS_PROCESS_PREFIX + '/empty.html'),
|
||||
]);
|
||||
// The url is about:blank in FF when 'page' event is fired.
|
||||
expect(otherPage.url()).toContain(server.CROSS_PROCESS_PREFIX);
|
||||
expect(await otherPage.evaluate(() => ['Hello', 'world'].join(' '))).toBe('Hello world');
|
||||
expect(await otherPage.$('body')).toBeTruthy();
|
||||
|
|
@ -547,12 +551,12 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
});
|
||||
it('should report initialized pages', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const pagePromise = context.waitForEvent('page').then(e => e.page());
|
||||
const pagePromise = context.waitForEvent('page');
|
||||
context.newPage();
|
||||
const newPage = await pagePromise;
|
||||
expect(newPage.url()).toBe('about:blank');
|
||||
|
||||
const popupPromise = context.waitForEvent('page').then(e => e.page());
|
||||
const popupPromise = context.waitForEvent('page');
|
||||
const evaluatePromise = newPage.evaluate(() => window.open('about:blank'));
|
||||
const popup = await popupPromise;
|
||||
expect(popup.url()).toBe('about:blank');
|
||||
|
|
@ -565,7 +569,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
let serverResponse = null;
|
||||
server.setRoute('/one-style.css', (req, res) => serverResponse = res);
|
||||
// Open a new page. Use window.open to connect to the page later.
|
||||
const [newPageEvent] = await Promise.all([
|
||||
const [newPage] = await Promise.all([
|
||||
context.waitForEvent('page'),
|
||||
page.evaluate(url => window.open(url), server.PREFIX + '/one-style.html'),
|
||||
server.waitForRequest('/one-style.css')
|
||||
|
|
@ -573,20 +577,20 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
// Issue a redirect.
|
||||
serverResponse.writeHead(302, { location: '/injectedstyle.css' });
|
||||
serverResponse.end();
|
||||
const newPage = await newPageEvent.page();
|
||||
// Connect to the opened page.
|
||||
await newPage.waitForLoadState({ waitUntil: 'domcontentloaded' });
|
||||
expect(newPage.url()).toBe(server.PREFIX + '/one-style.html');
|
||||
// Cleanup.
|
||||
await context.close();
|
||||
});
|
||||
it('should have an opener', async({browser, server}) => {
|
||||
it.fail(FFOX)('should have an opener', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
context.waitForEvent('page').then(e => e.page()),
|
||||
context.waitForEvent('page'),
|
||||
page.goto(server.PREFIX + '/popup/window-open.html')
|
||||
]);
|
||||
// The url is still about:blank in FF when 'page' event is fired.
|
||||
expect(popup.url()).toBe(server.PREFIX + '/popup/popup.html');
|
||||
expect(await popup.opener()).toBe(page);
|
||||
expect(await page.opener()).toBe(null);
|
||||
|
|
@ -595,8 +599,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
it('should fire page lifecycle events', async function({browser, server}) {
|
||||
const context = await browser.newContext();
|
||||
const events = [];
|
||||
context.on('page', async event => {
|
||||
const page = await event.page();
|
||||
context.on('page', async page => {
|
||||
events.push('CREATED: ' + page.url());
|
||||
page.on('close', () => events.push('DESTROYED: ' + page.url()));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, b
|
|||
const backgroundPages = context.backgroundPages();
|
||||
let backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
: await context.waitForEvent('backgroundpage').then(event => event.page());
|
||||
: await context.waitForEvent('backgroundpage');
|
||||
expect(backgroundPage).toBeTruthy();
|
||||
expect(context.backgroundPages()).toContain(backgroundPage);
|
||||
expect(context.pages()).not.toContain(backgroundPage);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT})
|
|||
it('should work for adopted elements', async({page,server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(url => window.__popup = window.open(url), server.EMPTY_PAGE),
|
||||
]);
|
||||
const divHandle = await page.evaluateHandle(() => {
|
||||
|
|
@ -218,6 +218,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT})
|
|||
return div;
|
||||
});
|
||||
expect(await divHandle.ownerFrame()).toBe(page.mainFrame());
|
||||
await popup.waitForLoadState({ waitUntil: 'domcontentloaded' });
|
||||
await page.evaluate(() => {
|
||||
const div = document.querySelector('div');
|
||||
window.__popup.document.body.appendChild(div);
|
||||
|
|
|
|||
|
|
@ -835,14 +835,99 @@ module.exports.describe = function({testRunner, expect, playwright, MAC, WIN, FF
|
|||
it('should work with pages that have loaded before being connected to', async({page, context, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window._popup = window.open(document.location.href)),
|
||||
]);
|
||||
expect(popup.url()).toBe(server.EMPTY_PAGE);
|
||||
// The url is about:blank in FF.
|
||||
// expect(popup.url()).toBe(server.EMPTY_PAGE);
|
||||
await popup.waitForLoadState();
|
||||
expect(popup.url()).toBe(server.EMPTY_PAGE);
|
||||
});
|
||||
});
|
||||
it.fail(FFOX)('should wait for load state of empty url popup', async({browser, page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('') && 1),
|
||||
]);
|
||||
await popup.waitForLoadState({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should wait for load state of about:blank popup ', async({browser, page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('about:blank') && 1),
|
||||
]);
|
||||
await popup.waitForLoadState({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should wait for load state of about:blank popup with noopener ', async({browser, page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('about:blank', null, 'noopener') && 1),
|
||||
]);
|
||||
await popup.waitForLoadState({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should wait for load state of popup with network url ', async({browser, page, server}) => {
|
||||
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({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should wait for load state of popup with network url and noopener ', async({browser, page, server}) => {
|
||||
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({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should work with clicking target=_blank', async({browser, page, server}) => {
|
||||
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({ waitUntil: 'load' });
|
||||
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should wait for load state of newPage', async({browser, context, page, server}) => {
|
||||
const [newPage] = await Promise.all([
|
||||
context.waitForEvent('page'),
|
||||
context.newPage(),
|
||||
]);
|
||||
await newPage.waitForLoadState({ waitUntil: 'load' });
|
||||
expect(await newPage.evaluate(() => document.readyState)).toBe('complete');
|
||||
});
|
||||
it('should resolve after popup load', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
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'),
|
||||
page.evaluate(url => window.popup = window.open(url), server.PREFIX + '/one-style.html'),
|
||||
]);
|
||||
let resolved = false;
|
||||
const loadSatePromise = popup.waitForLoadState({waitUntil: 'load'}).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');
|
||||
await context.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.goBack', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
|||
describe('Page.opener', function() {
|
||||
it('should provide access to the opener page', async({page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('about:blank')),
|
||||
]);
|
||||
const opener = await popup.opener();
|
||||
|
|
@ -140,7 +140,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
|||
});
|
||||
it('should return null if parent page has been closed', async({page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.open('about:blank')),
|
||||
]);
|
||||
await page.close();
|
||||
|
|
@ -227,7 +227,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
|||
it.fail(FFOX)('should not throw when there are console messages in detached iframes', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(async() => {
|
||||
// 1. Create a popup that Playwright is not connected to.
|
||||
const win = window.open('');
|
||||
|
|
@ -1060,7 +1060,7 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
|||
|
||||
describe('Page.Events.Close', function() {
|
||||
it('should work with window.close', async function({ page, context, server }) {
|
||||
const newPagePromise = page.waitForEvent('popup').then(e => e.page());
|
||||
const newPagePromise = page.waitForEvent('popup');
|
||||
await page.evaluate(() => window['newPage'] = window.open('about:blank'));
|
||||
const newPage = await newPagePromise;
|
||||
const closedPromise = new Promise(x => newPage.on('close', x));
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
await page.setContent('<a target=_blank rel=noopener href="/popup/popup.html">link</a>');
|
||||
const requestPromise = server.waitForRequest('/popup/popup.html');
|
||||
const [popup] = await Promise.all([
|
||||
context.waitForEvent('page').then(pageEvent => pageEvent.page()),
|
||||
context.waitForEvent('page'),
|
||||
page.click('a'),
|
||||
]);
|
||||
const userAgent = await popup.evaluate(() => window.initialUserAgent);
|
||||
|
|
@ -48,8 +48,8 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
route.continue();
|
||||
intercepted = true;
|
||||
});
|
||||
const [popup] = await Promise.all([
|
||||
context.waitForEvent('page').then(pageEvent => pageEvent.page()),
|
||||
await Promise.all([
|
||||
context.waitForEvent('page'),
|
||||
page.click('a'),
|
||||
]);
|
||||
await context.close();
|
||||
|
|
@ -106,9 +106,10 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(url => window._popup = window.open(url), server.PREFIX + '/title.html'),
|
||||
]);
|
||||
await popup.waitForLoadState({waitUntil: 'domcontentloaded'});
|
||||
expect(await popup.title()).toBe('Woof-Woof');
|
||||
await context.close();
|
||||
});
|
||||
|
|
@ -183,7 +184,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.__popup = window.open('about:blank')),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -195,7 +196,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.__popup = window.open(window.location.href, 'Title', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top=0,left=0')),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -205,75 +206,16 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
it('should emit for immediately closed popups', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popupEvent] = await Promise.all([
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => {
|
||||
const win = window.open('about:blank');
|
||||
win.close();
|
||||
}),
|
||||
]);
|
||||
expect(popupEvent).toBeTruthy();
|
||||
await context.close();
|
||||
});
|
||||
it('should resolve page() after initial navigation', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// First popup navigation is about:blank.
|
||||
const [popupEvent] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.popup = window.open('about:blank')),
|
||||
]);
|
||||
// Stall the 'load' for second navigation.
|
||||
server.setRoute('/one-style.css', (req, res) => {});
|
||||
await Promise.all([
|
||||
server.waitForRequest('/one-style.css'),
|
||||
page.evaluate(url => window.popup.location.href = url, server.PREFIX + '/one-style.html'),
|
||||
]);
|
||||
// Second navigation should be committed, but page() should resolve because first navigation is done.
|
||||
const popup = await popupEvent.page();
|
||||
expect(popup).toBeTruthy();
|
||||
await context.close();
|
||||
});
|
||||
it('should resolve page() after load', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Stall the 'load' by delaying css.
|
||||
let cssResponse;
|
||||
server.setRoute('/one-style.css', (req, res) => cssResponse = res);
|
||||
const [popupEvent] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
server.waitForRequest('/one-style.css'),
|
||||
page.evaluate(url => window.popup = window.open(url), server.PREFIX + '/one-style.html'),
|
||||
]);
|
||||
let resolved = false;
|
||||
const popupPromise = popupEvent.page().then(page => { resolved = true; return page; });
|
||||
expect(resolved).toBe(false);
|
||||
// Round trips!
|
||||
for (let i = 0; i < 5; i++)
|
||||
await page.evaluate('window');
|
||||
expect(resolved).toBe(false);
|
||||
cssResponse.end('');
|
||||
const popup = await popupPromise;
|
||||
expect(resolved).toBe(true);
|
||||
expect(popup.url()).toBe(server.PREFIX + '/one-style.html');
|
||||
await context.close();
|
||||
});
|
||||
it('should respect timeout in page()', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Stall the 'load' by delaying css.
|
||||
server.setRoute('/one-style.css', (req, res) => {});
|
||||
const [popupEvent] = await Promise.all([
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(url => window.popup = window.open(url), server.PREFIX + '/one-style.html'),
|
||||
]);
|
||||
const error = await popupEvent.page({ timeout: 1 }).catch(e => e);
|
||||
expect(error.message).toBe('waiting for "load" failed: timeout 1ms exceeded');
|
||||
await context.close();
|
||||
});
|
||||
it.fail(FFOX)('should be able to capture alert', async({browser}) => {
|
||||
// Firefox:
|
||||
// - immediately closes dialog by itself, without protocol call;
|
||||
|
|
@ -284,52 +226,29 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
const win = window.open('about:blank');
|
||||
win.alert('hello');
|
||||
});
|
||||
const popupEvent = await page.waitForEvent('popup');
|
||||
const popup = await popupEvent.page();
|
||||
const popup = await page.waitForEvent('popup');
|
||||
const dialog = await popup.waitForEvent('dialog');
|
||||
expect(dialog.message()).toBe('hello');
|
||||
await dialog.dismiss();
|
||||
await evaluatePromise;
|
||||
await context.close();
|
||||
});
|
||||
it.fail(FFOX)('should work with empty url', async({browser}) => {
|
||||
it('should work with empty url', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.__popup = window.open('')),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
|
||||
await context.close();
|
||||
});
|
||||
it('should work with empty url and nowait', async({browser}) => {
|
||||
it('should work with noopener and about:blank', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page({ waitUntil: 'nowait' })),
|
||||
page.evaluate(() => window.__popup = window.open()),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
|
||||
await context.close();
|
||||
});
|
||||
it('should work with noopener', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.evaluate(() => window.__popup = window.open('about:blank', null, 'noopener')),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
|
||||
await context.close();
|
||||
});
|
||||
it('should work with noopener and nowait', async({browser}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page({ waitUntil: 'nowait' })),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(() => window.__popup = window.open('about:blank', null, 'noopener')),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -341,19 +260,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.evaluate(url => window.__popup = window.open(url, null, 'noopener'), server.EMPTY_PAGE),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
|
||||
await context.close();
|
||||
});
|
||||
it('should work with noopener and url and nowait', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page({ waitUntil: 'nowait' })),
|
||||
page.waitForEvent('popup'),
|
||||
page.evaluate(url => window.__popup = window.open(url, null, 'noopener'), server.EMPTY_PAGE),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -366,20 +273,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
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').then(e => e.page()),
|
||||
page.click('a'),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
|
||||
await context.close();
|
||||
});
|
||||
it('should work with clicking target=_blank and nowait', async({browser, server}) => {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
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').then(e => e.page({ waitUntil: 'nowait' })),
|
||||
page.waitForEvent('popup'),
|
||||
page.click('a'),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -393,7 +287,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setContent('<a target=_blank rel=noopener href="/one-style.html">yo</a>');
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.$eval('a', a => a.click()),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -408,7 +302,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setContent('<a target=_blank rel=noopener href="/one-style.html">yo</a>');
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.click('a'),
|
||||
]);
|
||||
expect(await page.evaluate(() => !!window.opener)).toBe(false);
|
||||
|
|
@ -421,7 +315,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setContent('<a target=_blank rel=noopener href="/one-style.html">yo</a>');
|
||||
const [popup] = await Promise.all([
|
||||
page.waitForEvent('popup').then(e => e.page()),
|
||||
page.waitForEvent('popup'),
|
||||
page.click('a'),
|
||||
]);
|
||||
let badSecondPopup = false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue