Introduce Page.$ and Page.$$ (#75)

This patch introduces Page.$ and Page.$$ methods which are
aliases for `document.querySelector` and `document.querySelectorAll`. 

Fixes #78.
This commit is contained in:
JoelEinbinder
2017-07-17 18:56:56 -07:00
committed by Andrey Lushnikov
parent bf7698e8f8
commit 117a128b42
8 changed files with 158 additions and 9 deletions

View File

@@ -154,18 +154,16 @@ class FrameManager extends EventEmitter {
/**
* @param {!Frame} frame
* @param {function()} pageFunction
* @param {!Array<*>} args
* @param {string} expression
* @return {!Promise<(!Object|undefined)>}
*/
async _evaluateOnFrame(frame, pageFunction, ...args) {
async _evaluateOnFrame(frame, expression) {
let contextId = undefined;
if (!frame.isMainFrame()) {
contextId = this._frameIdToExecutionContextId.get(frame._id);
console.assert(contextId, 'Frame does not have default context to evaluate in!');
}
let syncExpression = helper.evaluationString(pageFunction, ...args);
let expression = `Promise.resolve(${syncExpression})`;
expression = `Promise.resolve(${expression})`;
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true });
if (exceptionDetails) {
let message = await helper.getExceptionMessage(this._client, exceptionDetails);
@@ -192,6 +190,7 @@ class FrameManager extends EventEmitter {
functionDeclaration: 'function() { return this; }',
returnByValue: true,
});
this._client.send('Runtime.releaseObject', {objectId: remoteObject.objectId});
return response.result.value;
}
@@ -275,7 +274,7 @@ class Frame {
* @return {!Promise<(!Object|undefined)>}
*/
async evaluate(pageFunction, ...args) {
return this._frameManager._evaluateOnFrame(this, pageFunction, ...args);
return this._frameManager._evaluateOnFrame(this, helper.evaluationString(pageFunction, ...args));
}
/**
@@ -328,6 +327,38 @@ class Frame {
await this._frameManager._waitForInFrame(selector, this);
}
/**
* @param {string} selector
* @param {function(!Element):T} pageFunction
* @param {!Array<*>} args
* @return {!Promise<?T>}
*/
async $(selector, pageFunction, ...args) {
let argsString = ['node'].concat(args.map(x => JSON.stringify(x))).join(',');
let expression = `(()=>{
let node = document.querySelector(${JSON.stringify(selector)});
if (!node)
return null;
return (${pageFunction})(${argsString});
})()`;
return this._frameManager._evaluateOnFrame(this, expression);
}
/**
* @param {string} selector
* @param {function(!Element):T} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!Array<T>>}
*/
async $$(selector, pageFunction, ...args) {
let argsString = ['node, index'].concat(args.map(x => JSON.stringify(x))).join(',');
let expression = `(()=>{
let nodes = document.querySelectorAll(${JSON.stringify(selector)});
return Array.prototype.map.call(nodes, (node, index) => (${pageFunction})(${argsString}));
})()`;
return this._frameManager._evaluateOnFrame(this, expression);
}
/**
* @param {?Object} framePayload
*/