fix(page): teach waitForSelector to return null (#3846)

`page.waitForSelector` should return `null` if waiting for `hidden:
true` and there's no matching node in DOM.

Before this patch, `page.waitForSelector` would return some JSHandle
pointing to boolean value.
This commit is contained in:
Andrey Lushnikov
2019-01-28 14:24:53 -05:00
committed by GitHub
parent 7446550fdb
commit 2061dd4718
5 changed files with 32 additions and 15 deletions

View File

@@ -429,7 +429,7 @@ class DOMWorld {
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForSelector(selector, options) {
return this._waitForSelectorOrXPath(selector, false, options);
@@ -438,7 +438,7 @@ class DOMWorld {
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForXPath(xpath, options) {
return this._waitForSelectorOrXPath(xpath, true, options);
@@ -468,9 +468,9 @@ class DOMWorld {
* @param {string} selectorOrXPath
* @param {boolean} isXPath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
_waitForSelectorOrXPath(selectorOrXPath, isXPath, options = {}) {
async _waitForSelectorOrXPath(selectorOrXPath, isXPath, options = {}) {
const {
visible: waitForVisible = false,
hidden: waitForHidden = false,
@@ -478,7 +478,13 @@ class DOMWorld {
} = options;
const polling = waitForVisible || waitForHidden ? 'raf' : 'mutation';
const title = `${isXPath ? 'XPath' : 'selector'} "${selectorOrXPath}"${waitForHidden ? ' to be hidden' : ''}`;
return new WaitTask(this, predicate, title, polling, timeout, selectorOrXPath, isXPath, waitForVisible, waitForHidden).promise;
const waitTask = new WaitTask(this, predicate, title, polling, timeout, selectorOrXPath, isXPath, waitForVisible, waitForHidden);
const handle = await waitTask.promise;
if (!handle.asElement()) {
await handle.dispose();
return null;
}
return handle.asElement();
/**
* @param {string} selectorOrXPath

View File

@@ -585,7 +585,7 @@ class Frame {
* @param {(string|number|Function)} selectorOrFunctionOrTimeout
* @param {!Object=} options
* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<?Puppeteer.JSHandle>}
*/
waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {
const xPathPattern = '//';
@@ -606,7 +606,7 @@ class Frame {
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForSelector(selector, options) {
return this._mainWorld.waitForSelector(selector, options);
@@ -615,7 +615,7 @@ class Frame {
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForXPath(xpath, options) {
return this._mainWorld.waitForXPath(xpath, options);

View File

@@ -1049,7 +1049,7 @@ class Page extends EventEmitter {
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForSelector(selector, options = {}) {
return this.mainFrame().waitForSelector(selector, options);
@@ -1058,7 +1058,7 @@ class Page extends EventEmitter {
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<?Puppeteer.ElementHandle>}
*/
waitForXPath(xpath, options = {}) {
return this.mainFrame().waitForXPath(xpath, options);