Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do print the console output of the page in puppeter as it would appear in the browser?

I keep seeing this WRONG CODE

page.on('console', msg => console.log(msg.text()));

That FAILS

console.log('Hello %s', 'World');

produces

Hello World     // browser
Hello %s World  // puppeteer

Ok, So I thought maybe I could do this

page.on('console', msg => console.log(...msg.args()));

NOPE: That dumps out some giant JSHandle thing.

Ok, So maybe

page.on('console', msg => console.log(...msg.args().map(a => a.toString());

NOPE: That prints

JSHandle: Hello %s JSHandle: World

I suppose I can hack it by removing the first 9 characters.

I also tried

page.on('console', msg => console.log(...msg.args().map(a => a.jsonValue())));

NOPE: That prints

Promise { <pending> } Promise { <pending> }

Okay how about

page.on('console', async(msg) => {
  const args = Promise.all(msg.args().map(a => a.jsonValue()));
  console.log(...args);
});

Nope, That prints

UnhandledPromiseRejectionWarning: TypeError: Found non-callable @@iterator
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 95)

Another go

page.on('console', async(msg) => {
  const args = Promise.all(msg.args().map(async(a) => {
    return await a.jsonValue();
  }));
  console.log(...args);
});

same as before

UnhandledPromiseRejectionWarning: TypeError: Found non-callable @@iterator
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a 

I even traced through msg.text() but all it does is return a premade string so it's too late to use that.

How do I get the same output as the browser's console.log in puppeteer?


PS: as mentioned above, this hack works in puppeteer 1.20.0

  page.on('console', (msg) => {
    console.log(...msg.args().map(v => v.toString().substr(9)));
  });

but it's clearly a hack and I expect it will break at some point so looking for the correct solution.

like image 777
gman Avatar asked Sep 24 '19 23:09

gman


People also ask

Which console method can be used to print?

print(): print() method in Java is used to display a text on the console. This text is passed as the parameter to this method in the form of String. This method prints the text on the console and the cursor remains at the end of the text at the console. The next printing takes place from just here.

How do I print this on console in JavaScript?

You should use the console. log() method to print to console JavaScript. The JavaScript console log function is mainly used for code debugging as it makes the JavaScript print the output to the console. To open the browser console, right-click on the page and select Inspect, and then click Console.

What is Page on in puppeteer?

The Puppeteer page class extends Node. js's native EventEmitter , which means that whenever you call page. on() , you are setting up an event listener using Node.

Does puppeteer run JavaScript?

And finally, we're using Puppeteer's built-in method called evaluate() . This method lets us run custom JavaScript code as if we were executing it in the DevTools console. Anything returned from that function gets resolved by the promise.


2 Answers

  page.on('console', async e => {
    const args = await Promise.all(e.args().map(a => a.jsonValue()));
    console.log(...args);
  });

or

  page.on('console', async e => {
    const args = await Promise.all(e.args().map(a => a.jsonValue()));
    console[e.type() === 'warning' ? 'warn' : e.type()](...args);
  });

works

like image 85
gman Avatar answered Oct 02 '22 05:10

gman


You can use msg.args(), and the workaround will be like this.

page.on('console', async msg => {
  const args = await msg.args()
  args.forEach(async (arg) => {
    const val = await arg.jsonValue()
    // value is serializable
    if (JSON.stringify(val) !== JSON.stringify({})) console.log(val)
    // value is unserializable (or an empty oject)
    else {
      const { type, subtype, description } = arg._remoteObject
      console.log(`type: ${type}, subtype: ${subtype}, description:\n ${description}`)
    }
  })
});

Or something like this, to print only the Error

page.on('console', async msg => {
  // serialize my args the way I want
  const args = await Promise.all(msg.args.map(arg => arg.executionContext().evaluate(arg => {
    // I'm in a page context now. If my arg is an error - get me its message.
    if (arg instanceof Error)
      return arg.message;
    // return arg right away. since we use `executionContext.evaluate`, it'll return JSON value of
    // the argument if possible, or `undefined` if it fails to stringify it.
    return arg;
  }, arg)));
  console.log(...args);
});
like image 27
Edi Imanto Avatar answered Oct 02 '22 05:10

Edi Imanto