feat(coverage): add an option to collect coverage of anonymous scripts (#2796)

This patch adds `reportAnonymousScripts` option to the `coverage.startJSCoverage` method. With this option, anonymous scripts are reported as well.

Fixes #2777
This commit is contained in:
Pavel Pomerantsev
2018-07-11 21:38:34 -04:00
committed by Andrey Lushnikov
parent 96c558d544
commit 12bc1e1a62
5 changed files with 47 additions and 13 deletions

View File

@@ -16,6 +16,8 @@
const {helper, debugError, assert} = require('./helper');
const {EVALUATION_SCRIPT_URL} = require('./ExecutionContext');
/**
* @typedef {Object} CoverageEntry
* @property {string} url
@@ -83,6 +85,7 @@ class JSCoverage {
async start(options = {}) {
assert(!this._enabled, 'JSCoverage is already enabled');
this._resetOnNavigation = options.resetOnNavigation === undefined ? true : !!options.resetOnNavigation;
this._reportAnonymousScripts = !!options.reportAnonymousScripts;
this._enabled = true;
this._scriptURLs.clear();
this._scriptSources.clear();
@@ -109,8 +112,11 @@ class JSCoverage {
* @param {!Protocol.Debugger.scriptParsedPayload} event
*/
async _onScriptParsed(event) {
// Ignore anonymous scripts
if (!event.url)
// Ignore puppeteer-injected scripts
if (event.url === EVALUATION_SCRIPT_URL)
return;
// Ignore other anonymous scripts unless the reportAnonymousScripts option is true.
if (!event.url && !this._reportAnonymousScripts)
return;
try {
const response = await this._client.send('Debugger.getScriptSource', {scriptId: event.scriptId});

View File

@@ -16,6 +16,9 @@
const {helper, assert} = require('./helper');
const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
class ExecutionContext {
/**
* @param {!Puppeteer.CDPSession} client
@@ -61,11 +64,14 @@ class ExecutionContext {
* @return {!Promise<!JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`;
if (helper.isString(pageFunction)) {
const contextId = this._contextId;
const expression = /** @type {string} */ (pageFunction);
const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression) ? expression : expression + '\n' + suffix;
const {exceptionDetails, result: remoteObject} = await this._client.send('Runtime.evaluate', {
expression,
expression: expressionWithSourceUrl,
contextId,
returnByValue: false,
awaitPromise: true,
@@ -76,8 +82,11 @@ class ExecutionContext {
return this._objectHandleFactory(remoteObject);
}
if (typeof pageFunction !== 'function')
throw new Error('The following is not a function: ' + pageFunction);
const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.callFunctionOn', {
functionDeclaration: pageFunction.toString(),
functionDeclaration: pageFunction.toString() + '\n' + suffix + '\n',
executionContextId: this._contextId,
arguments: args.map(convertArgument.bind(this)),
returnByValue: false,
@@ -239,4 +248,4 @@ class JSHandle {
}
helper.tracePublicAPI(JSHandle);
module.exports = {ExecutionContext, JSHandle};
module.exports = {ExecutionContext, JSHandle, EVALUATION_SCRIPT_URL};