feat(page): introduce consoleMessage.location() (#3365)

This patch adds a new consoleMessage.location() method that returns console message origins.

Fixes #3029
This commit is contained in:
Tom P 2019-01-11 02:51:13 +02:00 committed by Andrey Lushnikov
parent 16fc28bf06
commit 0c867631b0
5 changed files with 94 additions and 6 deletions

View File

@ -185,6 +185,7 @@
* [dialog.type()](#dialogtype) * [dialog.type()](#dialogtype)
- [class: ConsoleMessage](#class-consolemessage) - [class: ConsoleMessage](#class-consolemessage)
* [consoleMessage.args()](#consolemessageargs) * [consoleMessage.args()](#consolemessageargs)
* [consoleMessage.location()](#consolemessagelocation)
* [consoleMessage.text()](#consolemessagetext) * [consoleMessage.text()](#consolemessagetext)
* [consoleMessage.type()](#consolemessagetype) * [consoleMessage.type()](#consolemessagetype)
- [class: Frame](#class-frame) - [class: Frame](#class-frame)
@ -2315,6 +2316,12 @@ puppeteer.launch().then(async browser => {
#### consoleMessage.args() #### consoleMessage.args()
- returns: <[Array]<[JSHandle]>> - returns: <[Array]<[JSHandle]>>
#### consoleMessage.location()
- returns: <[Object]>
- `url` <[string]> URL of the resource if known
- `lineNumber` <[number]> line number in the resource
- `columnNumber` <[number]> line number in the resource
#### consoleMessage.text() #### consoleMessage.text()
- returns: <[string]> - returns: <[string]>

View File

@ -187,11 +187,11 @@ class Page extends EventEmitter {
* @param {!Protocol.Log.entryAddedPayload} event * @param {!Protocol.Log.entryAddedPayload} event
*/ */
_onLogEntryAdded(event) { _onLogEntryAdded(event) {
const {level, text, args, source} = event.entry; const {level, text, args, source, url, lineNumber} = event.entry;
if (args) if (args)
args.map(arg => helper.releaseObject(this._client, arg)); args.map(arg => helper.releaseObject(this._client, arg));
if (source !== 'worker') if (source !== 'worker')
this.emit(Page.Events.Console, new ConsoleMessage(level, text)); this.emit(Page.Events.Console, new ConsoleMessage(level, text, undefined, { url, lineNumber }));
} }
/** /**
@ -510,7 +510,14 @@ class Page extends EventEmitter {
async _onConsoleAPI(event) { async _onConsoleAPI(event) {
const context = this._frameManager.executionContextById(event.executionContextId); const context = this._frameManager.executionContextById(event.executionContextId);
const values = event.args.map(arg => createJSHandle(context, arg)); const values = event.args.map(arg => createJSHandle(context, arg));
this._addConsoleMessage(event.type, values); const location = {};
if (event.stackTrace && event.stackTrace.callFrames) {
const {url, lineNumber, columnNumber} = event.stackTrace.callFrames[0];
if (url) location.url = url;
if (lineNumber) location.lineNumber = lineNumber;
if (columnNumber) location.columnNumber = columnNumber;
}
this._addConsoleMessage(event.type, values, location);
} }
/** /**
@ -567,8 +574,9 @@ class Page extends EventEmitter {
/** /**
* @param {string} type * @param {string} type
* @param {!Array<!Puppeteer.JSHandle>} args * @param {!Array<!Puppeteer.JSHandle>} args
* @param {ConsoleMessage.Location} location
*/ */
_addConsoleMessage(type, args) { _addConsoleMessage(type, args, location) {
if (!this.listenerCount(Page.Events.Console)) { if (!this.listenerCount(Page.Events.Console)) {
args.forEach(arg => arg.dispose()); args.forEach(arg => arg.dispose());
return; return;
@ -581,7 +589,7 @@ class Page extends EventEmitter {
else else
textTokens.push(helper.valueFromRemoteObject(remoteObject)); textTokens.push(helper.valueFromRemoteObject(remoteObject));
} }
const message = new ConsoleMessage(type, textTokens.join(' '), args); const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
this.emit(Page.Events.Console, message); this.emit(Page.Events.Console, message);
} }
@ -1226,16 +1234,25 @@ Page.Events = {
* @property {("Strict"|"Lax")=} sameSite * @property {("Strict"|"Lax")=} sameSite
*/ */
/**
* @typedef {Object} ConsoleMessage.Location
* @property {string=} url
* @property {number=} lineNumber
* @property {number=} columnNumber
*/
class ConsoleMessage { class ConsoleMessage {
/** /**
* @param {string} type * @param {string} type
* @param {string} text * @param {string} text
* @param {!Array<!Puppeteer.JSHandle>} args * @param {!Array<!Puppeteer.JSHandle>} args
* @param {ConsoleMessage.Location} location
*/ */
constructor(type, text, args = []) { constructor(type, text, args = [], location = {}) {
this._type = type; this._type = type;
this._text = text; this._text = text;
this._args = args; this._args = args;
this._location = location;
} }
/** /**
@ -1258,6 +1275,13 @@ class ConsoleMessage {
args() { args() {
return this._args; return this._args;
} }
/**
* @return {Object}
*/
location() {
return this._location;
}
} }

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Log Entry Test</title>
</head>
<body>
<script>
fetch('http://wat')
</script>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Log Entry Test</title>
</head>
<body>
<script>
console.warn('wat')
</script>
</body>
</html>

View File

@ -322,6 +322,41 @@ module.exports.addTests = function({testRunner, expect, headless}) {
expect(message.text()).toContain('No \'Access-Control-Allow-Origin\''); expect(message.text()).toContain('No \'Access-Control-Allow-Origin\'');
expect(message.type()).toEqual('error'); expect(message.type()).toEqual('error');
}); });
it('should show correct additional info when console event emitted for logEntry', async({page, server}) => {
let message = null;
page.on('console', msg => {
message = msg;
});
await Promise.all([
page.goto(server.PREFIX + '/console-message-1.html'),
waitEvent(page, 'console'),
]);
await new Promise(resolve => setTimeout(resolve, 5000));
expect(message.text()).toContain(`ERR_NAME_NOT_RESOLVED`);
expect(message.type()).toEqual('error');
expect(message.location()).toEqual({
url: 'http://wat/',
lineNumber: undefined
});
});
it('should show correct additional info when console event emitted for consoleAPI', async({page, server}) => {
let message = null;
page.on('console', msg => {
message = msg;
});
await Promise.all([
page.goto(server.PREFIX + '/console-message-2.html'),
waitEvent(page, 'console'),
]);
await new Promise(resolve => setTimeout(resolve, 5000));
expect(message.text()).toContain(`wat`);
expect(message.type()).toEqual('warning');
expect(message.location()).toEqual({
url: `http://localhost:${server.PORT}/console-message-2.html`,
lineNumber: 7,
columnNumber: 16
});
});
}); });
describe('Page.Events.DOMContentLoaded', function() { describe('Page.Events.DOMContentLoaded', function() {