Skip to content

Commit

Permalink
feat(Console): Introduce ConsoleMessage type (#909)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aslushnikov committed Sep 29, 2017
1 parent cfece34 commit f625502
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -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}`));
```
Expand Down
32 changes: 26 additions & 6 deletions docs/api.md
Expand Up @@ -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)
Expand Down Expand Up @@ -249,19 +253,19 @@ 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.

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'
Expand Down Expand Up @@ -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')
);
Expand All @@ -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) => {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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"
Expand Down
17 changes: 16 additions & 1 deletion lib/Page.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
25 changes: 15 additions & 10 deletions test/test.js
Expand Up @@ -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 = [];
Expand All @@ -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',
Expand All @@ -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');
}));
});

Expand Down
1 change: 1 addition & 0 deletions utils/doclint/check_public_api/index.js
Expand Up @@ -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',
Expand Down

0 comments on commit f625502

Please sign in to comment.