diff --git a/docs/api.md b/docs/api.md index 22418cbb56d..357d92f738d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -58,7 +58,7 @@ + [page.uploadFile(selector, ...filePaths)](#pageuploadfileselector-filepaths) + [page.url()](#pageurl) + [page.viewport()](#pageviewport) - + [page.waitFor(selectorOrTimeout[, options])](#pagewaitforselectorortimeout-options) + + [page.waitFor(selectorOrFunctionOrTimeout[, options])](#pagewaitforselectororfunctionortimeout-options) + [page.waitForFunction(pageFunction[, options], ...args)](#pagewaitforfunctionpagefunction-options-args) + [page.waitForNavigation(options)](#pagewaitfornavigationoptions) + [page.waitForSelector(selector[, options])](#pagewaitforselectorselector-options) @@ -91,7 +91,7 @@ + [frame.parentFrame()](#frameparentframe) + [frame.title()](#frametitle) + [frame.url()](#frameurl) - + [frame.waitFor(selectorOrTimeout[, options])](#framewaitforselectorortimeout-options) + + [frame.waitFor(selectorOrFunctionOrTimeout[, options])](#framewaitforselectororfunctionortimeout-options) + [frame.waitForFunction(pageFunction[, options], ...args)](#framewaitforfunctionpagefunction-options-args) + [frame.waitForSelector(selector[, options])](#framewaitforselectorselector-options) * [class: Request](#class-request) @@ -641,16 +641,17 @@ This is a shortcut for [page.mainFrame().url()](#frameurl) #### page.viewport() - returns: <[Object]> An object with the save fields as described in [page.setViewport](#pagesetviewportviewport) -#### page.waitFor(selectorOrTimeout[, options]) -- `selectorOrTimeout` <[string]|[number]> A [selector] or timeout to wait for +#### page.waitFor(selectorOrFunctionOrTimeout[, options]) +- `selectorOrFunctionOrTimeout` <[string]|[number]|[function]> A [selector], predicate or timeout to wait for - `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`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). - returns: <[Promise]> +This is a shortcut method for [frame.waitForSelector](#framewaitforselectorselector-options) or [page.mainFrame().waitForFunction()](#framewaitforfunctionpagefunction-options-args). + This method behaves differently with respect to the type of the first parameter: -- if `selectorOrTimeout` is a `string`, than the first argument is treated as a [selector] to wait for and the method is a shortcut for [frame.waitForSelector](#framewaitforselectorselector-options) -- if `selectorOrTimeout` is a `number`, than the first argument is treated as a timeout in milliseconds and the method returns a promise which resolves after the timeout +- if `selectorOrFunctionOrTimeout` is a `string`, than the first argument is treated as a [selector] to wait for and the method is a shortcut for [frame.waitForSelector](#framewaitforselectorselector-options) +- if `selectorOrFunctionOrTimeout` is a `function`, than the first argument is treated as a predicate to wait for and the method is a shortcut for [frame.waitForFunction()](#framewaitforfunctionpagefunction-options-args). +- if `selectorOrFunctionOrTimeout` is a `number`, than the first argument is treated as a timeout in milliseconds and the method returns a promise which resolves after the timeout - otherwise, an exception is thrown The method is a shortcut for [page.mainFrame().waitFor()](#framewaitforselectorortimeout-options). @@ -904,16 +905,17 @@ Note: This value is calculated once when the frame is created, and will not upda Returns frame's url. -#### frame.waitFor(selectorOrTimeout[, options]) -- `selectorOrTimeout` <[string]|[number]> A [selector] or timeout to wait for +#### frame.waitFor(selectorOrFunctionOrTimeout[, options]) +- `selectorOrFunctionOrTimeout` <[string]|[number]|[function]> A [selector], predicate or timeout to wait for - `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`. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). - returns: <[Promise]> +This is a shortcut method for [frame.waitForSelector](#framewaitforselectorselector-options) or [page.mainFrame().waitForFunction()](#framewaitforfunctionpagefunction-options-args). + This method behaves differently with respect to the type of the first parameter: -- if `selectorOrTimeout` is a `string`, than the first argument is treated as a [selector] to wait for and the method is a shortcut for [frame.waitForSelector](#framewaitforselectorselectoroptions) -- if `selectorOrTimeout` is a `number`, than the first argument is treated as a timeout in milliseconds and the method returns a promise which resolves after the timeout +- if `selectorOrFunctionOrTimeout` is a `string`, than the first argument is treated as a [selector] to wait for and the method is a shortcut for [frame.waitForSelector](#framewaitforselectorselector-options) +- if `selectorOrFunctionOrTimeout` is a `function`, than the first argument is treated as a predicate to wait for and the method is a shortcut for [frame.waitForFunction()](#framewaitforfunctionpagefunction-options-args). +- if `selectorOrFunctionOrTimeout` is a `number`, than the first argument is treated as a timeout in milliseconds and the method returns a promise which resolves after the timeout - otherwise, an exception is thrown #### frame.waitForFunction(pageFunction[, options], ...args) diff --git a/lib/FrameManager.js b/lib/FrameManager.js index ccfd4c70f8f..fcd8264cc84 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -270,16 +270,18 @@ class Frame { } /** - * @param {(string|number)} selectorOrTimeout + * @param {(string|number|function())} selectorOrTimeout * @param {!Object=} options * @return {!Promise} */ - waitFor(selectorOrTimeout, options = {}) { - if (helper.isString(selectorOrTimeout)) - return this.waitForSelector(selectorOrTimeout, options); - if (helper.isNumber(selectorOrTimeout)) - return new Promise(fulfill => setTimeout(fulfill, selectorOrTimeout)); - return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrTimeout))); + waitFor(selectorOrFunctionOrTimeout, options = {}) { + if (helper.isString(selectorOrFunctionOrTimeout)) + return this.waitForSelector(selectorOrFunctionOrTimeout, options); + if (helper.isNumber(selectorOrFunctionOrTimeout)) + return new Promise(fulfill => setTimeout(fulfill, selectorOrFunctionOrTimeout)); + if (typeof selectorOrFunctionOrTimeout === 'function') + return this.waitForFunction(selectorOrFunctionOrTimeout, options); + return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrFunctionOrTimeout))); } /** diff --git a/lib/Page.js b/lib/Page.js index 65c833a57f5..67a074097ad 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -554,12 +554,12 @@ class Page extends EventEmitter { } /** - * @param {string} selectorOrTimeout + * @param {(string|number|function())} selectorOrTimeout * @param {!Object=} options - * @return {!Promise} + * @return {!Promise} */ - waitFor(selectorOrTimeout, options) { - return this.mainFrame().waitFor(selectorOrTimeout, options); + waitFor(selectorOrFunctionOrTimeout, options = {}) { + return this.mainFrame().waitFor(selectorOrFunctionOrTimeout, options); } /** diff --git a/test/test.js b/test/test.js index f00c3c8e118..ca2aad39ba0 100644 --- a/test/test.js +++ b/test/test.js @@ -388,6 +388,11 @@ describe('Puppeteer', function() { await page.waitFor(timeout); expect(Date.now() - startTime).not.toBeLessThan(timeout / 2); })); + it('should wait for predicate', SX(async function() { + const watchdog = page.waitFor(() => window.innerWidth < 100); + page.setViewport({width: 10, height: 10}); + await watchdog; + })); it('should throw when unknown type', SX(async function() { try { await page.waitFor({foo: 'bar'});