Skip to content

Commit

Permalink
feat(page): waitForSelector hidden option (#967)
Browse files Browse the repository at this point in the history
This patch adds a 'hidden' option for the `page.waitForSelector` method.
  • Loading branch information
ChristianDavis authored and aslushnikov committed Oct 13, 2017
1 parent 8f430fb commit 8511db9
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/api.md
Expand Up @@ -1042,6 +1042,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
Expand Up @@ -413,22 +413,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
Expand Up @@ -656,12 +656,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

0 comments on commit 8511db9

Please sign in to comment.