Implement timeout option for page.waitFor
This patch implements timeout option for page.waitFor. The function will throw if the selector doesn't appear during timeout milliseconds of waittime. References #89, #91.
This commit is contained in:
parent
aba61de905
commit
1f954fa7ed
@ -804,12 +804,13 @@ Returns frame's url.
|
|||||||
#### frame.waitFor(selector[, options])
|
#### frame.waitFor(selector[, options])
|
||||||
- `selector` <[string]> CSS selector of awaited element,
|
- `selector` <[string]> CSS selector of awaited element,
|
||||||
- `options` <[Object]> Optional waiting parameters
|
- `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.
|
- `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]> Promise which resolves when element specified by selector string is added to DOM.
|
- returns: <[Promise]> 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
|
Wait for the `selector` to appear in page. If at the moment of calling
|
||||||
the method the `selector` already exists, the method will return
|
the method the `selector` already exists, the method will return
|
||||||
immediately.
|
immediately. If the selector doesn't appear after the `timeout` milliseconds of waiting, the function will throw.
|
||||||
|
|
||||||
This method works across navigations:
|
This method works across navigations:
|
||||||
```js
|
```js
|
||||||
|
@ -174,16 +174,17 @@ class FrameManager extends EventEmitter {
|
|||||||
* @param {!Frame} frame
|
* @param {!Frame} frame
|
||||||
* @param {string} selector
|
* @param {string} selector
|
||||||
* @param {boolean} waitForVisible
|
* @param {boolean} waitForVisible
|
||||||
|
* @param {number} timeout
|
||||||
* @return {!Promise<undefined>}
|
* @return {!Promise<undefined>}
|
||||||
*/
|
*/
|
||||||
async _waitForSelector(frame, selector, waitForVisible) {
|
async _waitForSelector(frame, selector, waitForVisible, timeout) {
|
||||||
let contextId = undefined;
|
let contextId = undefined;
|
||||||
if (!frame.isMainFrame()) {
|
if (!frame.isMainFrame()) {
|
||||||
contextId = this._frameIdToExecutionContextId.get(frame._id);
|
contextId = this._frameIdToExecutionContextId.get(frame._id);
|
||||||
console.assert(contextId, 'Frame does not have default context to evaluate in!');
|
console.assert(contextId, 'Frame does not have default context to evaluate in!');
|
||||||
}
|
}
|
||||||
let { exceptionDetails } = await this._client.send('Runtime.evaluate', {
|
let { exceptionDetails } = await this._client.send('Runtime.evaluate', {
|
||||||
expression: helper.evaluationString(inPageWatchdog, selector, waitForVisible),
|
expression: helper.evaluationString(inPageWatchdog, selector, waitForVisible, timeout),
|
||||||
contextId,
|
contextId,
|
||||||
awaitPromise: true,
|
awaitPromise: true,
|
||||||
returnByValue: false,
|
returnByValue: false,
|
||||||
@ -194,10 +195,15 @@ class FrameManager extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* @param {string} selector
|
* @param {string} selector
|
||||||
* @param {boolean} waitForVisible
|
* @param {boolean} waitForVisible
|
||||||
|
* @param {number} timeout
|
||||||
* @return {!Promise}
|
* @return {!Promise}
|
||||||
*/
|
*/
|
||||||
function inPageWatchdog(selector, visible) {
|
async function inPageWatchdog(selector, visible, timeout) {
|
||||||
return visible ? waitForVisible(selector) : waitInDOM(selector);
|
const resultPromise = visible ? waitForVisible(selector) : waitInDOM(selector);
|
||||||
|
const timeoutPromise = new Promise((resolve, reject) => {
|
||||||
|
setTimeout(reject.bind(null, new Error(`waitFor failed: timeout ${timeout}ms exceeded.`)), timeout);
|
||||||
|
});
|
||||||
|
await Promise.race([resultPromise, timeoutPromise]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} selector
|
* @param {string} selector
|
||||||
@ -342,7 +348,11 @@ class Frame {
|
|||||||
* @return {!Promise}
|
* @return {!Promise}
|
||||||
*/
|
*/
|
||||||
async waitFor(selector, options = {}) {
|
async waitFor(selector, options = {}) {
|
||||||
const awaitedElement = new AwaitedElement(() => this._frameManager._waitForSelector(this, selector, !!options.visible));
|
const timeout = options.timeout || 30000;
|
||||||
|
const awaitedElement = new AwaitedElement(() => this._frameManager._waitForSelector(this, selector, !!options.visible, timeout));
|
||||||
|
// Since navigation will re-install page watchdogs, we should timeout on our
|
||||||
|
// end as well.
|
||||||
|
setTimeout(() => awaitedElement.terminate(new Error(`waitFor failed: timeout ${timeout}ms exceeded`)), timeout);
|
||||||
|
|
||||||
this._awaitedElements.add(awaitedElement);
|
this._awaitedElements.add(awaitedElement);
|
||||||
let cleanup = () => this._awaitedElements.delete(awaitedElement);
|
let cleanup = () => this._awaitedElements.delete(awaitedElement);
|
||||||
|
@ -274,6 +274,12 @@ describe('Puppeteer', function() {
|
|||||||
await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility'));
|
await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility'));
|
||||||
expect(await waitFor).toBe(true);
|
expect(await waitFor).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
it('should respect timeout', SX(async function() {
|
||||||
|
let error = null;
|
||||||
|
await page.waitFor('div', {timeout: 10}).catch(e => error = e);
|
||||||
|
expect(error).toBeTruthy();
|
||||||
|
expect(error.message).toContain('waitFor failed: timeout');
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.Events.Console', function() {
|
describe('Page.Events.Console', function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user