31

Why when I use console.log in evaluate, it works:

casper.then(function() {
  this.evaluate( function() {
    console.log('hello'); 
  });
});

But this doesn't work:

casper.then(function() {
  this.evaluate( function() {
    setTimeout( function() {console.log('hello');}, 1000);
  });
});
davejagoda
  • 2,420
  • 1
  • 20
  • 27
Rustem
  • 2,884
  • 1
  • 17
  • 32
  • Related: [Output client-side console with casper/phantomjs](http://stackoverflow.com/a/10783675/1816580) – Artjom B. Feb 26 '16 at 10:01

4 Answers4

72

Because you're mixing up casperjs and remote page environments. The evaluate function will execute code within the remote page env, so the console.log call won't output anything.

If you want to catch remote console.log calls, listen to the remote.message event:

casper.on('remote.message', function(msg) {
    this.echo('remote message caught: ' + msg);
})

Btw, documentation for events is pretty much exhaustive, as well as the one for evaluate.

NiKo
  • 11,215
  • 6
  • 46
  • 56
  • 1
    The ```setTimeout``` is the difference in between OP's examples. How does ```setTimeout``` change this? they are both being executed in the remote environment. – nikk wong Oct 25 '15 at 08:32
  • @nikkwong Since the OP didn't specify what they mean by *"it works"* and *"doesn't work"*, we can only guess. I would think that they haven't noticed that they are breaking out of the control flow of CasperJS and therefore forgot to also wait in the `casper` control flow. They probably exited too early. I doubt that we can get to the bottom of this despite the activity of the OP. – Artjom B. Feb 26 '16 at 19:26
  • FYI - links are broken – evolutionxbox Sep 13 '16 at 11:06
19

@NiKo's answer is critical.

I would also suggest adding the following, since if there's an error, you might not even make it far enough to print out a console.log() msg, and instead end up with silence.

casper.on( 'page.error', function (msg, trace) {
    this.echo( 'Error: ' + msg, 'ERROR' );
});
Michael Yaworski
  • 13,410
  • 19
  • 69
  • 97
odigity
  • 7,568
  • 4
  • 37
  • 51
11

CasperJS includes ClientUtils, which can be used from the remote page to easily log to the console of the casper script:

__utils__.echo('This message is logged from the remote page to the CasperJS console');
pius
  • 2,344
  • 1
  • 23
  • 25
5

Building on @odigity's answer, this makes casperjs die with a more familiar error/stacktrace:

var util = require('util');

casper.on('page.error', function exitWithError(msg, stack) {
    stack = stack.reduce(function (accum, frame) {
        return accum + util.format('\tat %s (%s:%d)\n',
            frame.function || '<anonymous>',
            frame.file,
            frame.line
        );
    }, '');
    this.die(['Client-side error', msg, stack].join('\n'), 1);
});
c24w
  • 7,421
  • 7
  • 39
  • 47
  • 1
    Fantastic! I was just looking for something like this today too. Shouldn't the utility module be `utils` though? – Qcom May 06 '15 at 17:24
  • @Qcom, I think `utils` would be fine, since it's [_`sprintf` equivalent_](http://casperjs.readthedocs.org/en/latest/modules/utils.html#format). Where I was using it we already had [`util`](https://www.npmjs.com/package/util) available, so I just used that :) – c24w May 07 '15 at 14:00
  • Interesting, are you using casper in conjunction with node via SpookyJS or equivalent? To my knowledge casper doesn't integrate with the node module ecosystem by default. – Qcom May 07 '15 at 15:23
  • 1
    We're just using casperjs on its own. If you look at their [`patchedRequire`](https://github.com/n1k0/casperjs/blob/a2c47c0452b5a1ede70971a098cc665b49c3b2ca/bin/bootstrap.js#L276-L285) you can see that it will try and load from node_modules. – c24w May 07 '15 at 16:31
  • Ah, I see. Thanks for the link! Very nice to know. – Qcom May 07 '15 at 16:34