From 8511db957ff28a493d57b36e6184842232ca6eaf Mon Sep 17 00:00:00 2001 From: Christian Davis Date: Fri, 13 Oct 2017 11:11:11 -0500 Subject: [PATCH] feat(page): waitForSelector hidden option (#967) This patch adds a 'hidden' option for the `page.waitForSelector` method. --- docs/api.md | 1 + lib/FrameManager.js | 15 +++++++++------ test/test.js | 28 +++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/docs/api.md b/docs/api.md index 5ec881f5f75..eeea265e212 100644 --- a/docs/api.md +++ b/docs/api.md @@ -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. diff --git a/lib/FrameManager.js b/lib/FrameManager.js index 6e895e5f5fa..d58771b4c92 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -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); } } diff --git a/test/test.js b/test/test.js index 79b6a730ee6..c6291426562 100644 --- a/test/test.js +++ b/test/test.js @@ -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(`
`); + await page.setContent(`
`); 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(`
`); + 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(`
`); + 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(`
`); + 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;