diff --git a/README.md b/README.md index acf0b85a4b6..062e7784ab3 100644 --- a/README.md +++ b/README.md @@ -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}`)); ``` diff --git a/docs/api.md b/docs/api.md index 87d6f8b0d75..92310407ca9 100644 --- a/docs/api.md +++ b/docs/api.md @@ -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" diff --git a/lib/Page.js b/lib/Page.js index 7fa7ce53403..e10ca51131f 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -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); diff --git a/test/test.js b/test/test.js index a41f5bccc1a..551a906b202 100644 --- a/test/test.js +++ b/test/test.js @@ -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'); })); }); diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index e93314c9a84..3eebc982a93 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -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',