feat(page): waitForSelector hidden option (#967)

This patch adds a 'hidden' option for the `page.waitForSelector` method.
This commit is contained in:
Christian Davis 2017-10-13 11:11:11 -05:00 committed by Andrey Lushnikov
parent 8f430fb23d
commit 8511db957f
3 changed files with 37 additions and 7 deletions

View File

@ -1042,6 +1042,7 @@ Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args]
- `selector` <[string]> A [selector] of an element to wait for, - `selector` <[string]> A [selector] of an element to wait for,
- `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. Defaults to `false`. - `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). - `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.

View File

@ -413,22 +413,25 @@ class Frame {
waitForSelector(selector, options = {}) { waitForSelector(selector, options = {}) {
const timeout = options.timeout || 30000; const timeout = options.timeout || 30000;
const waitForVisible = !!options.visible; const waitForVisible = !!options.visible;
const polling = waitForVisible ? 'raf' : 'mutation'; const waitForHidden = !!options.hidden;
return this.waitForFunction(predicate, {timeout, polling}, selector, waitForVisible); const polling = waitForVisible || waitForHidden ? 'raf' : 'mutation';
return this.waitForFunction(predicate, {timeout, polling}, selector, waitForVisible, waitForHidden);
/** /**
* @param {string} selector * @param {string} selector
* @param {boolean} waitForVisible * @param {boolean} waitForVisible
* @param {boolean} waitForHidden
* @return {boolean} * @return {boolean}
*/ */
function predicate(selector, waitForVisible) { function predicate(selector, waitForVisible, waitForHidden) {
const node = document.querySelector(selector); const node = document.querySelector(selector);
if (!node) if (!node)
return false; return waitForHidden;
if (!waitForVisible) if (!waitForVisible && !waitForHidden)
return true; return true;
const style = window.getComputedStyle(node); 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);
} }
} }

View File

@ -656,12 +656,38 @@ describe('Page', function() {
it('should wait for visible', SX(async function() { it('should wait for visible', SX(async function() {
let divFound = false; let divFound = false;
const waitForSelector = page.waitForSelector('div', {visible: true}).then(() => divFound = true); 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); expect(divFound).toBe(false);
await page.evaluate(() => document.querySelector('div').style.removeProperty('display')); await page.evaluate(() => document.querySelector('div').style.removeProperty('display'));
expect(divFound).toBe(false); expect(divFound).toBe(false);
await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility')); await page.evaluate(() => document.querySelector('div').style.removeProperty('visibility'));
expect(await waitForSelector).toBe(true); 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() { it('should respect timeout', SX(async function() {
let error = null; let error = null;