Skip to content

Commit

Permalink
Implement timeout option for page.waitFor
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aslushnikov committed Jul 21, 2017
1 parent aba61de commit 1f954fa
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
5 changes: 3 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -804,12 +804,13 @@ Returns frame's url.
#### frame.waitFor(selector[, options])
- `selector` <[string]> CSS selector of awaited element,
- `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.

Wait for the `selector` to appear in page. If at the moment of calling
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:
```js
Expand Down
20 changes: 15 additions & 5 deletions lib/FrameManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,17 @@ class FrameManager extends EventEmitter {
* @param {!Frame} frame
* @param {string} selector
* @param {boolean} waitForVisible
* @param {number} timeout
* @return {!Promise<undefined>}
*/
async _waitForSelector(frame, selector, waitForVisible) {
async _waitForSelector(frame, selector, waitForVisible, timeout) {
let contextId = undefined;
if (!frame.isMainFrame()) {
contextId = this._frameIdToExecutionContextId.get(frame._id);
console.assert(contextId, 'Frame does not have default context to evaluate in!');
}
let { exceptionDetails } = await this._client.send('Runtime.evaluate', {
expression: helper.evaluationString(inPageWatchdog, selector, waitForVisible),
expression: helper.evaluationString(inPageWatchdog, selector, waitForVisible, timeout),
contextId,
awaitPromise: true,
returnByValue: false,
Expand All @@ -194,10 +195,15 @@ class FrameManager extends EventEmitter {
/**
* @param {string} selector
* @param {boolean} waitForVisible
* @param {number} timeout
* @return {!Promise}
*/
function inPageWatchdog(selector, visible) {
return visible ? waitForVisible(selector) : waitInDOM(selector);
async function inPageWatchdog(selector, visible, timeout) {
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
Expand Down Expand Up @@ -342,7 +348,11 @@ class Frame {
* @return {!Promise}
*/
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);
let cleanup = () => this._awaitedElements.delete(awaitedElement);
Expand Down
6 changes: 6 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ describe('Puppeteer', function() {
await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility'));
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() {
Expand Down

0 comments on commit 1f954fa

Please sign in to comment.