Skip to content

Commit

Permalink
feat(Page): Add global navigation timeout setting (puppeteer#1728)
Browse files Browse the repository at this point in the history
This patch introduces `page.setDefaultNavigationTimeout` method to override the 
default 30 seconds navigation timeout.

Fixes puppeteer#1514
  • Loading branch information
nougat123 authored and aslushnikov committed Jan 10, 2018
1 parent 3985dee commit ec8e40f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
21 changes: 16 additions & 5 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
* [page.select(selector, ...values)](#pageselectselector-values)
* [page.setContent(html)](#pagesetcontenthtml)
* [page.setCookie(...cookies)](#pagesetcookiecookies)
* [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout)
* [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
* [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled)
* [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled)
Expand Down Expand Up @@ -837,7 +838,7 @@ If there's no element matching `selector`, the method throws an error.

#### page.goBack(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.
- `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 [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) method.
- `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
- `load` - consider navigation to be finished when the `load` event is fired.
- `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
Expand All @@ -850,7 +851,7 @@ Navigate to the previous page in history.

#### page.goForward(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.
- `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 [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) method.
- `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
- `load` - consider navigation to be finished when the `load` event is fired.
- `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
Expand All @@ -864,7 +865,7 @@ Navigate to the next page in history.
#### page.goto(url, options)
- `url` <[string]> URL to navigate page to. The url should include scheme, e.g. `https://`.
- `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.
- `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 [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) method.
- `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
- `load` - consider navigation to be finished when the `load` event is fired.
- `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
Expand Down Expand Up @@ -1004,7 +1005,7 @@ Shortcut for [page.mainFrame().executionContext().queryObjects(prototypeHandle)]

#### page.reload(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.
- `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 [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) method.
- `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
- `load` - consider navigation to be finished when the `load` event is fired.
- `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
Expand Down Expand Up @@ -1058,6 +1059,16 @@ Shortcut for [page.mainFrame().select()](#frameselectselector-values)
- `sameSite` <[string]> `"Strict"` or `"Lax"`.
- returns: <[Promise]>

#### page.setDefaultNavigationTimeout(timeout)
- `timeout` <[number]> Maximum navigation time in milliseconds

This setting will change the default maximum navigation time of 30 seconds for the following methods:
- [page.goto(url, options)](#pagegotourl-options)
- [page.goBack(options)](#pagegobackoptions)
- [page.goForward(options)](#pagegoforwardoptions)
- [page.reload(options)](#pagereloadoptions)
- [page.waitForNavigation(options)](#pagewaitfornavigationoptions)

#### page.setExtraHTTPHeaders(headers)
- `headers` <[Object]> An object containing additional http headers to be sent with every request. All header values must be strings.
- returns: <[Promise]>
Expand Down Expand Up @@ -1209,7 +1220,7 @@ Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]

#### 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.
- `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 [page.setDefaultNavigationTimeout(timeout)](#pagesetdefaultnavigationtimeouttimeout) method.
- `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either:
- `load` - consider navigation to be finished when the `load` event is fired.
- `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired.
Expand Down
5 changes: 3 additions & 2 deletions lib/NavigatorWatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ class NavigatorWatcher {
/**
* @param {!FrameManager} frameManager
* @param {!Puppeteer.Frame} frame
* @param {number} timeout
* @param {!Object=} options
*/
constructor(frameManager, frame, options = {}) {
constructor(frameManager, frame, timeout, options = {}) {
console.assert(options.networkIdleTimeout === undefined, 'ERROR: networkIdleTimeout option is no longer supported.');
console.assert(options.networkIdleInflight === undefined, 'ERROR: networkIdleInflight option is no longer supported.');
console.assert(options.waitUntil !== 'networkidle', 'ERROR: "networkidle" option is no longer supported. Use "networkidle2" instead');
Expand All @@ -41,7 +42,7 @@ class NavigatorWatcher {
this._frameManager = frameManager;
this._frame = frame;
this._initialLoaderId = frame._loaderId;
this._timeout = typeof options.timeout === 'number' ? options.timeout : 30000;
this._timeout = timeout;
this._eventListeners = [
helper.addEventListener(this._frameManager, FrameManager.Events.LifecycleEvent, this._checkLifecycleComplete.bind(this)),
helper.addEventListener(this._frameManager, FrameManager.Events.FrameDetached, this._checkLifecycleComplete.bind(this))
Expand Down
18 changes: 14 additions & 4 deletions lib/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Page extends EventEmitter {
this._pageBindings = new Map();
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._coverage = new Coverage(client);
this._defaultNavigationTimeout = 30000;

this._screenshotTaskQueue = screenshotTaskQueue;

Expand Down Expand Up @@ -170,6 +171,13 @@ class Page extends EventEmitter {
return this._networkManager.setOfflineMode(enabled);
}

/**
* @param {number} timeout
*/
setDefaultNavigationTimeout(timeout) {
this._defaultNavigationTimeout = timeout;
}

/**
* @param {!Object} event
*/
Expand Down Expand Up @@ -471,7 +479,7 @@ class Page extends EventEmitter {
* @param {!Object=} options
* @return {!Promise<?Response>}
*/
async goto(url, options) {
async goto(url, options = {}) {
const referrer = this._networkManager.extraHTTPHeaders()['referer'];

const requests = new Map();
Expand All @@ -480,7 +488,8 @@ class Page extends EventEmitter {
];

const mainFrame = this._frameManager.mainFrame();
const watcher = new NavigatorWatcher(this._frameManager, mainFrame, options);
const timeout = typeof options.timeout === 'number' ? options.timeout : this._defaultNavigationTimeout;
const watcher = new NavigatorWatcher(this._frameManager, mainFrame, timeout, options);
const navigationPromise = watcher.navigationPromise();
let error = await Promise.race([
navigate(this._client, url, referrer),
Expand Down Expand Up @@ -527,9 +536,10 @@ class Page extends EventEmitter {
* @param {!Object=} options
* @return {!Promise<!Response>}
*/
async waitForNavigation(options) {
async waitForNavigation(options = {}) {
const mainFrame = this._frameManager.mainFrame();
const watcher = new NavigatorWatcher(this._frameManager, mainFrame, options);
const timeout = typeof options.timeout === 'number' ? options.timeout : this._defaultNavigationTimeout;
const watcher = new NavigatorWatcher(this._frameManager, mainFrame, timeout, options);

const responses = new Map();
const listener = helper.addEventListener(this._networkManager, NetworkManager.Events.Response, response => responses.set(response.url(), response));
Expand Down
8 changes: 8 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,14 @@ describe('Page', function() {
await page.goto(server.PREFIX + '/empty.html', {timeout: 1}).catch(e => error = e);
expect(error.message).toContain('Navigation Timeout Exceeded: 1ms');
});
it('should fail when exceeding default maximum navigation timeout', async({page, server}) => {
// Hang for request to the empty.html
server.setRoute('/empty.html', (req, res) => { });
let error = null;
page.setDefaultNavigationTimeout(1);
await page.goto(server.PREFIX + '/empty.html').catch(e => error = e);
expect(error.message).toContain('Navigation Timeout Exceeded: 1ms');
});
it('should disable timeout when its set to 0', async({page, server}) => {
let error = null;
let loaded = false;
Expand Down

0 comments on commit ec8e40f

Please sign in to comment.