Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: remove waitForLoadState() in favor of PageEvent.page(options) #1323

Merged
merged 1 commit into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 23 additions & 46 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ This setting will change the default maximum navigation time for the following m
- [page.goto(url[, options])](#pagegotourl-options)
- [page.reload([options])](#pagereloadoptions)
- [page.setContent(html[, options])](#pagesetcontenthtml-options)
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)

> **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) and [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout) take priority over [`browserContext.setDefaultNavigationTimeout`](#browsercontextsetdefaultnavigationtimeouttimeout).
Expand Down Expand Up @@ -717,7 +716,6 @@ page.removeListener('request', logRequest);
- [page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#pagewaitforselectororfunctionortimeout-options-args)
- [page.waitForEvent(event[, optionsOrPredicate])](#pagewaitforeventevent-optionsorpredicate)
- [page.waitForFunction(pageFunction[, options[, ...args]])](#pagewaitforfunctionpagefunction-options-args)
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)
- [page.waitForRequest(urlOrPredicate[, options])](#pagewaitforrequesturlorpredicate-options)
- [page.waitForResponse(urlOrPredicate[, options])](#pagewaitforresponseurlorpredicate-options)
Expand Down Expand Up @@ -1567,7 +1565,6 @@ This setting will change the default maximum navigation time for the following m
- [page.goto(url[, options])](#pagegotourl-options)
- [page.reload([options])](#pagereloadoptions)
- [page.setContent(html[, options])](#pagesetcontenthtml-options)
- [page.waitForLoadState([options])](#pagewaitforloadstateoptions)
- [page.waitForNavigation([options])](#pagewaitfornavigationoptions)

> **NOTE** [`page.setDefaultNavigationTimeout`](#pagesetdefaultnavigationtimeouttimeout) takes priority over [`page.setDefaultTimeout`](#pagesetdefaulttimeouttimeout), [`browserContext.setDefaultTimeout`](#browsercontextsetdefaulttimeouttimeout) and [`browserContext.setDefaultNavigationTimeout`](#browsercontextsetdefaultnavigationtimeouttimeout).
Expand Down Expand Up @@ -1782,27 +1779,6 @@ await page.waitForFunction(selector => !!document.querySelector(selector), {}, s

Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args).

#### page.waitForLoadState([options])
- `options` <[Object]> Navigation parameters which might have the following properties:
- `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` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider navigation succeeded, defaults to `load`. Events can be either:
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
- `'load'` - consider navigation to be finished when the `load` event is fired.
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` 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]> Promise which resolves when the load state has been achieved.

This resolves when the page reaches a required load state, `load` by default. The navigation can be in progress when it is called.
If navigation is already at a required state, resolves immediately.

```js
await page.click('button'); // Click triggers navigation.
await page.waitForLoadState(); // The promise resolves after navigation has finished.
```

Shortcut for [page.mainFrame().waitForLoadState([options])](#framewaitforloadstateoptions).

#### page.waitForNavigation([options])
- `options` <[Object]> Navigation parameters which might have the following properties:
- `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.
Expand Down Expand Up @@ -1895,8 +1871,29 @@ This method returns all of the dedicated [WebWorkers](https://developer.mozilla.

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()
- returns: <[Promise]<[Page]>> Promise which resolves to the 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` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider the page to be loaded, defaults to `load`. Events can be either:
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
- `'load'` - consider navigation to be finished when the `load` event is fired.
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` 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 committed navigation to the initial url (corresponds to `{waitUntil: 'commit'}` 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

Expand Down Expand Up @@ -1968,7 +1965,6 @@ An example of getting text from an iframe element:
- [frame.url()](#frameurl)
- [frame.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])](#framewaitforselectororfunctionortimeout-options-args)
- [frame.waitForFunction(pageFunction[, options[, ...args]])](#framewaitforfunctionpagefunction-options-args)
- [frame.waitForLoadState([options])](#framewaitforloadstateoptions)
- [frame.waitForNavigation([options])](#framewaitfornavigationoptions)
- [frame.waitForSelector(selector[, options])](#framewaitforselectorselector-options)
<!-- GEN:stop -->
Expand Down Expand Up @@ -2498,25 +2494,6 @@ const selector = '.foo';
await page.waitForFunction(selector => !!document.querySelector(selector), {}, selector);
```

#### frame.waitForLoadState([options])
- `options` <[Object]> Navigation parameters which might have the following properties:
- `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` <"commit"|"load"|"domcontentloaded"|"networkidle0"|"networkidle2"> When to consider navigation succeeded, defaults to `load`. Events can be either:
- `'commit'` - navigation is committed, new url is displayed in the browser address bar.
- `'load'` - consider navigation to be finished when the `load` event is fired.
- `'domcontentloaded'` - consider navigation to be finished when the `DOMContentLoaded` 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]> Promise which resolves when the load state has been achieved.

This resolves when the page reaches a required load state, `load` by default. The navigation can be in progress when it is called.
If navigation is already at a required state, resolves immediately.

```js
await frame.click('button'); // Click triggers navigation.
await frame.waitForLoadState(); // The promise resolves after navigation has finished.
```

#### frame.waitForNavigation([options])
- `options` <[Object]> Navigation parameters which might have the following properties:
- `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.
Expand Down
6 changes: 3 additions & 3 deletions src/chromium/crBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,18 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
try {
switch (targetInfo.type) {
case 'page': {
const event = new PageEvent(target.pageOrError());
const event = new PageEvent(context, target.pageOrError());
context.emit(CommonEvents.BrowserContext.Page, event);
const opener = target.opener();
if (!opener)
break;
const openerPage = await opener.pageOrError();
if (openerPage instanceof Page && !openerPage.isClosed())
openerPage.emit(CommonEvents.Page.Popup, new PageEvent(target.pageOrError()));
openerPage.emit(CommonEvents.Page.Popup, new PageEvent(context, target.pageOrError()));
break;
}
case 'background_page': {
const event = new PageEvent(target.pageOrError());
const event = new PageEvent(context, target.pageOrError());
context.emit(Events.CRBrowserContext.BackgroundPage, event);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/firefox/ffBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class FFBrowser extends platform.EventEmitter implements Browser {
const ffPage = new FFPage(session, context, opener);
this._ffPages.set(targetId, ffPage);

const pageEvent = new PageEvent(ffPage.pageOrError());
const pageEvent = new PageEvent(context, ffPage.pageOrError());
context.emit(Events.BrowserContext.Page, pageEvent);

ffPage.pageOrError().then(() => this._firstPageCallback());
Expand Down
8 changes: 3 additions & 5 deletions src/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ export type GotoResult = {
newDocumentId?: string,
};

const kLifecycleEvents: Set<types.LifecycleEvent> = new Set(['commit', 'load', 'domcontentloaded', 'networkidle0', 'networkidle2']);

type ConsoleTagHandler = () => void;

export class FrameManager {
Expand Down Expand Up @@ -437,7 +435,7 @@ export class Frame {
return request ? request._finalRequest._waitForResponse() : null;
}

async waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
async _waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
const {timeout = this._page._timeoutSettings.navigationTimeout()} = options;
const disposer = new Disposer();
const error = await Promise.race([
Expand Down Expand Up @@ -491,7 +489,7 @@ export class Frame {

_waitForLifecycle(waitUntil: types.LifecycleEvent = 'load'): Disposable<Promise<void>> {
let resolve: () => void;
if (!kLifecycleEvents.has(waitUntil))
if (!types.kLifecycleEvents.has(waitUntil))
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);

const checkLifecycleComplete = () => {
Expand Down Expand Up @@ -643,7 +641,7 @@ export class Frame {
this._page._frameManager._consoleMessageTags.set(tag, () => {
// Clear lifecycle right after document.open() - see 'tag' below.
this._page._frameManager.clearFrameLifecycle(this);
resolve(this.waitForLoadState(options));
resolve(this._waitForLoadState(options));
});
});
const contentPromise = context.evaluate((html, tag) => {
Expand Down
51 changes: 36 additions & 15 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,45 @@ export type FileChooser = {
};

export class PageEvent {
private readonly _browserContext: BrowserContextBase;
private readonly _pageOrError: Promise<Page | Error>;
private readonly _lifecyclePromises = new Map<types.LifecycleEvent, Promise<Page | Error>>();

constructor(pageOrErrorPromise: Promise<Page | Error>) {
constructor(browserContext: BrowserContextBase, pageOrErrorPromise: Promise<Page | Error>) {
this._browserContext = browserContext;
this._pageOrError = pageOrErrorPromise;
}

async page(/* options?: frames.NavigateOptions */): Promise<Page> {
const result = await this._pageOrError;
if (result instanceof Page) {
if (result.isClosed())
throw new Error('Page has been closed.');
return result;
}
throw result;
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;

const { dispose, value: waitForLifecycle } = page.mainFrame()._waitForLifecycle(lifecycle);
const error = await Promise.race([
page.mainFrame()._createFrameDestroyedPromise(),
waitForLifecycle,
]);
dispose();
if (error)
return error;
return page;
}

async page(options: types.NavigateOptions = {}): Promise<Page> {
const {
timeout = this._browserContext._timeoutSettings.navigationTimeout(),
waitUntil = 'load',
} = options;
const lifecyclePromise = 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;
}
}

Expand Down Expand Up @@ -311,10 +336,6 @@ export class Page extends platform.EventEmitter {
return this.mainFrame().waitForNavigation(options);
}

async waitForLoadState(options?: types.NavigateOptions): Promise<void> {
return this.mainFrame().waitForLoadState(options);
}

async waitForEvent(event: string, optionsOrPredicate: Function | (types.TimeoutOptions & { predicate?: Function }) = {}): Promise<any> {
if (typeof optionsOrPredicate === 'function')
optionsOrPredicate = { predicate: optionsOrPredicate };
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type Polling = 'raf' | 'mutation' | number;
export type WaitForFunctionOptions = TimeoutOptions & { polling?: Polling };

export type LifecycleEvent = 'commit' | 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
export const kLifecycleEvents: Set<LifecycleEvent> = new Set(['commit', 'load', 'domcontentloaded', 'networkidle0', 'networkidle2']);

export type NavigateOptions = TimeoutOptions & {
waitUntil?: LifecycleEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/webkit/wkBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
this._firstPageCallback = undefined;
}

const pageEvent = new PageEvent(wkPage.pageOrError());
const pageEvent = new PageEvent(context, wkPage.pageOrError());
context.emit(Events.BrowserContext.Page, pageEvent);
if (!opener)
return;
Expand Down
Loading