Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]
- `selector` <[string]> A [selector] of an element 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`.
- `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).
- returns: <[Promise]> Promise which resolves when element specified by selector string is added to DOM.

Expand Down
15 changes: 9 additions & 6 deletions lib/FrameManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,22 +401,25 @@ class Frame {
waitForSelector(selector, options = {}) {
const timeout = options.timeout || 30000;
const waitForVisible = !!options.visible;
const polling = waitForVisible ? 'raf' : 'mutation';
return this.waitForFunction(predicate, {timeout, polling}, selector, waitForVisible);
const waitForHidden = !!options.hidden;
const polling = waitForVisible || waitForHidden ? 'raf' : 'mutation';
return this.waitForFunction(predicate, {timeout, polling}, selector, waitForVisible, waitForHidden);

/**
* @param {string} selector
* @param {boolean} waitForVisible
* @param {boolean} waitForHidden
* @return {boolean}
*/
function predicate(selector, waitForVisible) {
function predicate(selector, waitForVisible, waitForHidden) {
const node = document.querySelector(selector);
if (!node)
return false;
if (!waitForVisible)
return waitForHidden;
if (!waitForVisible && !waitForHidden)
return true;
const style = window.getComputedStyle(node);
return style && style.display !== 'none' && style.visibility !== 'hidden';
const isVisible = style && style.display !== 'none' && style.visibility !== 'hidden';
return (waitForVisible === isVisible || waitForHidden === !isVisible);
}
}

Expand Down
28 changes: 27 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,12 +498,38 @@ describe('Page', function() {
it('should wait for visible', SX(async function() {
let divFound = false;
const waitForSelector = page.waitForSelector('div', {visible: true}).then(() => divFound = true);
await page.setContent(`<div style='display: none;visibility: hidden'></div>`);
await page.setContent(`<div style='display: none; visibility: hidden;'></div>`);
expect(divFound).toBe(false);
await page.evaluate(() => document.querySelector('div').style.removeProperty('display'));
expect(divFound).toBe(false);
await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility'));
expect(await waitForSelector).toBe(true);
expect(divFound).toBe(true);
}));
it('hidden should wait for visibility: hidden', SX(async function() {
let divHidden = false;
await page.setContent(`<div style='display: block;'></div>`);
const waitForSelector = page.waitForSelector('div', {hidden: true}).then(() => divHidden = true);
await page.evaluate(() => document.querySelector('div').style.setProperty('visibility', 'hidden'));
expect(await waitForSelector).toBe(true);
expect(divHidden).toBe(true);
}));
it('hidden should wait for display: none', SX(async function() {
let divHidden = false;
await page.setContent(`<div style='display: block;'></div>`);
const waitForSelector = page.waitForSelector('div', {hidden: true}).then(() => divHidden = true);
await page.evaluate(() => document.querySelector('div').style.setProperty('display', 'none'));
expect(await waitForSelector).toBe(true);
expect(divHidden).toBe(true);
}));
it('hidden should wait for removal', SX(async function() {
await page.setContent(`<div></div>`);
let divRemoved = false;
const waitForSelector = page.waitForSelector('div', {hidden: true}).then(() => divRemoved = true);
expect(divRemoved).toBe(false);
await page.evaluate(() => document.querySelector('div').remove());
expect(await waitForSelector).toBe(true);
expect(divRemoved).toBe(true);
}));
it('should respect timeout', SX(async function() {
let error = null;
Expand Down