19

I have a React/Redux app that I am testing using Puppeteer. Based on the documentation, I am using the following code to show the console outputs:

page.on('console', msg => {
    for(let i = 0; i < msg.args().length; ++i) {
        let text = msg.args()[i];
        console.log(`${i}: ${text}`);
    }
});

However, when the redux-logger logs an object to console (prevState, nextState), Puppeeter shows JSHandle@object in my console outputs instead. How do I see the keys and properties inside this object?

Grant Miller
  • 27,532
  • 16
  • 147
  • 165
aditi
  • 585
  • 1
  • 7
  • 14
  • 1
    Have you tried using JSHandle `toString()` or `jsonValue()`? – Ram Pasala Aug 08 '18 at 09:38
  • 1
    Just a note on the `jsonValue()`: it needs to be passed into a `console.log` rather than part of a template string to avoid the `'[object Object]'` stringification. See [How do print the console output of the page in puppeter as it would appear in the browser?](https://stackoverflow.com/questions/58089425/how-do-print-the-console-output-of-the-page-in-puppeter-as-it-would-appear-in-th). – ggorlen Nov 24 '20 at 21:27

2 Answers2

10

You can get args from JSHandle with await for it.

The best way for me was next to describe errors from the browser and catch needed types of console notifications:

import { ConsoleMessage, Page, JSHandle } from 'puppeteer';
const chalk = require('chalk');

export const listenPageErrors = async (page: Page) => {
  // make args accessible
  const describe = (jsHandle) => {
    return jsHandle.executionContext().evaluate((obj) => {
      // serialize |obj| however you want
      return `OBJ: ${typeof obj}, ${obj}`;
    }, jsHandle);
  }

  const colors: any = {
    LOG: chalk.grey, // (text: any) => text,
    ERR: chalk.red,
    WAR: chalk.yellow,
    INF: chalk.cyan,
  };

  // listen to browser console there
  page.on('console', async (message: ConsoleMessage) => {
    const args = await Promise.all(message.args().map(arg => describe(arg)));
    // make ability to paint different console[types]
    const type = message.type().substr(0, 3).toUpperCase();
    const color = colors[type] || chalk.blue;
    let text = '';
    for (let i = 0; i < args.length; ++i) {
      text += `[${i}] ${args[i]} `;
    }
    console.log(color(`CONSOLE.${type}: ${message.text()}\n${text} `));
  });
}

Put it between const page = await browser.newPage(); and page.goto(URL), and it will work as should

const page = await browser.newPage();
await listenPageErrors(page); // <- like there
page.goto(URL)

scythargon
  • 3,363
  • 3
  • 32
  • 62
Igor Kurkov
  • 4,318
  • 2
  • 30
  • 31
  • Lol what, you wrote this only 2 hours ago and I've already found this! Hi! For me it breaks on `jsHandle as JSHandle` - `Unexpected token, expected ","` – scythargon Mar 25 '21 at 16:39
  • And then the `message` here is undefined: `const type = message.type().` – scythargon Mar 25 '21 at 16:41
  • about `jsHandle as JSHandle - Unexpected token, expected ","` maybe delete `as JSHandle` type description, it may cause by your Tslint/eslint options – Igor Kurkov Mar 25 '21 at 16:48
  • Was still wrong at the `Promise.all(msg.args()` part, I've fixed it for you. And thank you! – scythargon Mar 25 '21 at 16:49
  • Hey, Igor!:) I'm struggling with another puppeteer issue here, thought that you might know the solution but could not find you in Telegram to ask. Is it possible to know if puppeteer page is currently being loaded? The analogue of the "refresh button" current state, may be? – scythargon Apr 05 '21 at 08:56
8

If you place the consoleMessage.args() directly inside console.log() without enclosing them in template literals, you can print the keys and values of the JSHandles that represent each argument passed to console.log() in the page context:

page.on('console', msg => {
  for (let i = 0; i < msg.args().length; i++) {
    console.log(msg.args()[i]);
  }
});

The beginning of the result will look something like this:

JSHandle {
  _context:
   ExecutionContext {
     _client:
      CDPSession {
        domain: null,
        _events: [Object],
        ...
Grant Miller
  • 27,532
  • 16
  • 147
  • 165