From abb05e069ddb70d5a79ff7b7623ebd96666ea280 Mon Sep 17 00:00:00 2001 From: Yaniv Efraim Date: Thu, 29 Mar 2018 02:34:37 +0300 Subject: [PATCH] feat(page): add an option to disable timeout for waitForFunction (#2252) This patch adds support for `timeout: 0` to disable timeout for the following functions: - `page.waitForFunction` - `page.waitForXPath` - `page.waitForSelector` and their `frame` counterparts. Fixes #2200 --- docs/api.md | 12 ++++++------ lib/FrameManager.js | 3 ++- test/frame.spec.js | 6 ++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/api.md b/docs/api.md index 3b47a363e1760..609f22f59b06f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1344,7 +1344,7 @@ Shortcut for [page.mainFrame().waitFor(selectorOrFunctionOrTimeout[, options[, . - `polling` <[string]|[number]> An interval at which the `pageFunction` is executed, defaults to `raf`. If `polling` is a number, then it is treated as an interval in milliseconds at which the function would be executed. If `polling` is a string, then it can be one of the following values: - `raf` - to constantly execute `pageFunction` in `requestAnimationFrame` callback. This is the tightest polling mode which is suitable to observe styling changes. - `mutation` - to execute `pageFunction` on every DOM mutation. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` - returns: <[Promise]<[JSHandle]>> Promise which resolves when the `pageFunction` returns a truthy value. It resolves to a JSHandle of the truthy value. @@ -1377,7 +1377,7 @@ Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args] - `options` <[Object]> Optional waiting parameters - `visible` <[boolean]> wait for element to be present in DOM and to be visible, i.e. to not have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - `hidden` <[boolean]> wait for element to not be found in the DOM or to be hidden, i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - returns: <[Promise]<[ElementHandle]>> Promise which resolves when element specified by selector string is added to DOM. Wait for the `selector` to appear in page. If at the moment of calling @@ -1406,7 +1406,7 @@ Shortcut for [page.mainFrame().waitForSelector(selector[, options])](#framewaitf - `options` <[Object]> Optional waiting parameters - `visible` <[boolean]> wait for element to be present in DOM and to be visible, i.e. to not have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - `hidden` <[boolean]> wait for element to not be found in the DOM or to be hidden, i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - returns: <[Promise]<[ElementHandle]>> Promise which resolves when element specified by xpath string is added to DOM. Wait for the `xpath` to appear in page. If at the moment of calling @@ -1926,7 +1926,7 @@ This method behaves differently with respect to the type of the first parameter: - `polling` <[string]|[number]> An interval at which the `pageFunction` is executed, defaults to `raf`. If `polling` is a number, then it is treated as an interval in milliseconds at which the function would be executed. If `polling` is a string, then it can be one of the following values: - `raf` - to constantly execute `pageFunction` in `requestAnimationFrame` callback. This is the tightest polling mode which is suitable to observe styling changes. - `mutation` - to execute `pageFunction` on every DOM mutation. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - `...args` <...[Serializable]|[JSHandle]> Arguments to pass to `pageFunction` - returns: <[Promise]<[JSHandle]>> Promise which resolves when the `pageFunction` returns a truthy value. It resolves to a JSHandle of the truthy value. @@ -1948,7 +1948,7 @@ puppeteer.launch().then(async browser => { - `options` <[Object]> Optional waiting parameters - `visible` <[boolean]> wait for element to be present in DOM and to be visible, i.e. to not have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - `hidden` <[boolean]> wait for element to not be found in the DOM or to be hidden, i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - returns: <[Promise]<[ElementHandle]>> Promise which resolves when element specified by selector string is added to DOM. Wait for the `selector` to appear in page. If at the moment of calling @@ -1976,7 +1976,7 @@ puppeteer.launch().then(async browser => { - `options` <[Object]> Optional waiting parameters - `visible` <[boolean]> wait for element to be present in DOM and to be visible, i.e. to not have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - `hidden` <[boolean]> wait for element to not be found in the DOM or to be hidden, i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to `false`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). + - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. - returns: <[Promise]<[ElementHandle]>> Promise which resolves when element specified by xpath string is added to DOM. Wait for the `xpath` to appear in page. If at the moment of calling diff --git a/lib/FrameManager.js b/lib/FrameManager.js index bd4269f066f93..4c9cda92c37eb 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -790,7 +790,8 @@ class WaitTask { }); // Since page navigation requires us to re-install the pageScript, we should track // timeout on our end. - this._timeoutTimer = setTimeout(() => this.terminate(new Error(`waiting failed: timeout ${timeout}ms exceeded`)), timeout); + if (timeout) + this._timeoutTimer = setTimeout(() => this.terminate(new Error(`waiting failed: timeout ${timeout}ms exceeded`)), timeout); this.rerun(); } diff --git a/test/frame.spec.js b/test/frame.spec.js index 88c39b25cdeb7..a77794bb2e430 100644 --- a/test/frame.spec.js +++ b/test/frame.spec.js @@ -145,6 +145,12 @@ module.exports.addTests = function({testRunner, expect}) { await page.evaluate(element => element.remove(), div); await waitForFunction; }); + it('should disable timeout when its set to 0', async({page}) => { + let error = null; + const res = await page.waitForFunction(() => new Promise(res => setTimeout(() => res(42), 100)), {timeout: 0}).catch(e => error = e); + expect(error).toBe(null); + expect(await res.jsonValue()).toBe(42); + }); }); describe('Frame.waitForSelector', function() {