feat(Console): Introduce ConsoleMessage type (#909)

This patch introduces ConsoleMessage type and starts dispatching
it for the 'console' event.

BREAKING CHANGE: this breaks the api of the 'console' event.

Fixes #744.
This commit is contained in:
Andrey Lushnikov 2017-09-29 11:27:22 -07:00 committed by GitHub
parent cfece3451d
commit f6255029bd
5 changed files with 59 additions and 18 deletions

View File

@ -153,7 +153,7 @@ Explore the [API documentation](docs/api.md) and [examples](https://github.com/G
This is also handy when debugging code in `page.evaluate()`:
```js
page.on('console', (...args) => console.log('PAGE LOG:', ...args));
page.on('console', msg => console.log('PAGE LOG:', ...msg.args));
await page.evaluate(() => console.log(`url is ${location.href}`));
```

View File

@ -99,6 +99,10 @@
+ [dialog.dismiss()](#dialogdismiss)
+ [dialog.message()](#dialogmessage)
+ [dialog.type](#dialogtype)
* [class: ConsoleMessage](#class-consolemessage)
+ [consoleMessage.args](#consolemessageargs)
+ [consoleMessage.text](#consolemessagetext)
+ [consoleMessage.type](#consolemessagetype)
* [class: Frame](#class-frame)
+ [frame.$(selector)](#frameselector)
+ [frame.$$(selector)](#frameselector)
@ -249,7 +253,7 @@ puppeteer.launch().then(async browser => {
```
#### event: 'console'
- <[string]>
- <[ConsoleMessage]>
Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also emitted if the page throws an error or a warning.
@ -257,11 +261,11 @@ The arguments passed into `console.log` appear as arguments on the event handler
An example of handling `console` event:
```js
page.on('console', (...args) => {
for (let i = 0; i < args.length; ++i)
page.on('console', msg => {
for (let i = 0; i < msg.args.length; ++i)
console.log(`${i}: ${args[i]}`);
});
page.evaluate(() => console.log(5, 'hello', {foo: 'bar'}));
page.evaluate(() => console.log('hello', 5, {foo: 'bar'}));
```
#### event: 'dialog'
@ -514,7 +518,7 @@ const crypto = require('crypto');
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
page.on('console', console.log);
page.on('console', msg => console.log(msg.text));
await page.exposeFunction('md5', text =>
crypto.createHash('md5').update(text).digest('hex')
);
@ -536,7 +540,7 @@ const fs = require('fs');
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
page.on('console', console.log);
page.on('console', msg => console.log(msg.text));
await page.exposeFunction('readfile', async filePath => {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, text) => {
@ -1093,6 +1097,21 @@ puppeteer.launch().then(async browser => {
Dialog's type, could be one of the `alert`, `beforeunload`, `confirm` and `prompt`.
### class: ConsoleMessage
[ConsoleMessage] objects are dispatched by page via the ['console'](#event-console) event.
#### consoleMessage.args
- <[Array]<[string]>>
#### consoleMessage.text
- <[string]>
#### consoleMessage.type
- <[string]>
One of the following values: `'log'`, `'debug'`, `'info'`, `'error'`, `'warning'`, `'dir'`, `'dirxml'`, `'table'`, `'trace'`, `'clear'`, `'startGroup'`, `'startGroupCollapsed'`, `'endGroup'`, `'assert'`, `'profile'`, `'profileEnd'`, `'count'`, `'timeEnd'`.
### class: Frame
At every point of time, page exposes its current frame tree via the [page.mainFrame()](#pagemainframe) and [frame.childFrames()](#framechildframes) methods.
@ -1432,6 +1451,7 @@ Contains the URL of the response.
[stream.Readable]: https://nodejs.org/api/stream.html#stream_class_stream_readable "stream.Readable"
[Error]: https://nodejs.org/api/errors.html#errors_class_error "Error"
[Frame]: #class-frame "Frame"
[ConsoleMessage]: #class-consolemessage "ConsoleMessage"
[iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols "Iterator"
[Response]: #class-response "Response"
[Request]: #class-request "Request"

View File

@ -313,7 +313,9 @@ class Page extends EventEmitter {
return;
}
const values = await Promise.all(event.args.map(arg => helper.serializeRemoteObject(this._client, arg)));
this.emit(Page.Events.Console, ...values);
const text = values.join(' ');
const message = new ConsoleMessage(event.type, text, values);
this.emit(Page.Events.Console, message);
}
_onDialog(event) {
@ -875,6 +877,19 @@ Page.Viewport;
* @property {("Strict"|"Lax")=} sameSite
*/
class ConsoleMessage {
/**
* @param {string} type
* @param {string} text
* @param {!Array<*>} args
*/
constructor(type, text, args) {
this.type = type;
this.text = text;
this.args = args;
}
}
module.exports = Page;
helper.tracePublicAPI(Page);

View File

@ -537,13 +537,15 @@ describe('Page', function() {
describe('Page.Events.Console', function() {
it('should work', SX(async function() {
let commandArgs = [];
page.once('console', (...args) => commandArgs = args);
let message = null;
page.once('console', m => message = m);
await Promise.all([
page.evaluate(() => console.log(5, 'hello', {foo: 'bar'})),
page.evaluate(() => console.log('hello', 5, {foo: 'bar'})),
waitForEvents(page, 'console')
]);
expect(commandArgs).toEqual([5, 'hello', {foo: 'bar'}]);
expect(message.text).toEqual('hello 5 [object Object]');
expect(message.type).toEqual('log');
expect(message.args).toEqual(['hello', 5, {foo: 'bar'}]);
}));
it('should work for different console API calls', SX(async function() {
const messages = [];
@ -559,11 +561,14 @@ describe('Page', function() {
console.error('calling console.error');
console.log(Promise.resolve('should not wait until resolved!'));
}),
// Wait for 5 events to hit.
// Wait for 5 events to hit - console.time is not reported
waitForEvents(page, 'console', 5)
]);
expect(messages[0]).toContain('calling console.time');
expect(messages.slice(1)).toEqual([
expect(messages.map(msg => msg.type)).toEqual([
'timeEnd', 'trace', 'dir', 'warning', 'error', 'log'
]);
expect(messages[0].text).toContain('calling console.time');
expect(messages.slice(1).map(msg => msg.text)).toEqual([
'calling console.trace',
'calling console.dir',
'calling console.warn',
@ -572,13 +577,13 @@ describe('Page', function() {
]);
}));
it('should not fail for window object', SX(async function() {
let windowObj = null;
page.once('console', arg => windowObj = arg);
let message = null;
page.once('console', msg => message = msg);
await Promise.all([
page.evaluate(() => console.error(window)),
waitForEvents(page, 'console')
]);
expect(windowObj).toBe('Window');
expect(message.text).toBe('Window');
}));
});

View File

@ -37,6 +37,7 @@ const EXCLUDE_CLASSES = new Set([
const EXCLUDE_METHODS = new Set([
'Body.constructor',
'Browser.constructor',
'ConsoleMessage.constructor',
'Dialog.constructor',
'ElementHandle.constructor',
'Frame.constructor',