rinogo
rinogo

Reputation: 9163

How to access errors when using WebdriverJS?

We are using the superb WebdriverJS (with Selenium) to perform acceptance testing on our web app. Everything works fine, and our tests execute successfully when we use Firefox and Safari.

However, when we use PhantomJS, our tests fail with unhelpful errors. It's almost as if... Javascript isn't even running inside the client page! Something that would cause this would be if PhantomJS' javascript environment ran into errors. Unfortunately, I can't seem to find a way to access Javascript errors when using PhantomJS with WebdriverJS.

If we were using PhantomJS directly, we could simply do (from the PhantomJS site):

page.onError = function(msg, trace) {
  console.log(msg);
  trace.forEach(function(item) {
    console.log('  ', item.file, ':', item.line);
  });
}

Unfortunately, I don't know how to access this mysterious page object when using PhantomJS within WebdriverJS. Any thoughts?

Upvotes: 2

Views: 1680

Answers (2)

xBill
xBill

Reputation: 233

You can actually access JS errors in your PhantomJS stdout log at INFO level.

$ phantomjs --webdriver 4444 --webdriver-loglevel=INFO

You can even push things forward by setting the log level to DEBUG and see what actually PhantomJS does to execute the commands you send through Webdriver / Ghostdriver.

Upvotes: 3

rinogo
rinogo

Reputation: 9163

I figured out a workable solution! Essentially, it involves using an onerror event handler to intercept (and store) the Javascript errors. Then, once the DOM is ready, we report the errors via hidden DOM elements. This allows Selenium to look for specific elements (e.g. ".javascript-errors"), which is something it's naturally quite good at. Thanks go to myriad other blog posts and SO questions for getting me to this point.

The code:

//For detecting and reporting Javascript errors via Selenium.  Note that this should be in its own file to allow this code to reliably detect syntax errors in other files.
var errors = [];

//Handle all errors
window.onerror = function(message, url, line) {
    errors.push({"message":message, "url":url, "line":line});
}

//Report errors visually via HTML once the DOM is ready
window.onload = function() {
    if(errors.length==0)
        return;

  var div = document.createElement("div");
  div.className = 'javascript-errors';
  div.innerHTML = '';
    var style = "position:absolute; left:-10000px; top:auto; width:1px; height:1px;"; //CSS to hide the errors; we can't use display:none, or Selenium won't be able to read the error messages.  Adapted from http://webaim.org/techniques/css/invisiblecontent/

    for(var i=0; i<errors.length; i++)
      div.innerHTML += '<div class="javascript-error" style="' + style +'"><span class="message">' + errors[i].message.replace('<', '&lt;').replace('>', '&gt;') + '</span><br/><span class="url">' + errors[i].url + '</span><br/><span class="line">' + errors[i].line + '</span></div>';

    document.body.appendChild(div);
}

Upvotes: 2

Related Questions