nathanboktae / mocha-phantomjs-core

Easiest way to run client-side Mocha tests in PhantomJS or SlimerJS :ghost:

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeError: 'undefined' is not an object (evaluating '= mochaScript'

tgirardi opened this issue · comments

I'm using phantomjs 1.9.8 and when I run my tests I get:

TypeError: 'undefined' is not an object (evaluating '= mochaScript')

   at browser-shim.js:54
   at browser-shim.js:105

When taking a look at what's happening inside browser-shim I can see that scriptTags contains just one item (the first script element that appears inside my HTML) when there should be more than 10. Also that one item is not mocha.js, so in line 27 ...

mochaScript.onreadystatechange = mochaScript.onload = function () {

... mochaScript is undefined, so the exception occurs.

I printed the content for document.body.innerHTML and saw that it ends just after the first script tags (so all other script tags are missing, including mocha.js).

I don't know if this is a bug in phantomjs or in this project, but probably changing the injection strategy...

page.onResourceReceived = function(resource) {
  if (resource.url.match(/mocha\.js$/)) {
    page.injectJs('browser-shim.js')
  }
}

... could solve the problem.

Probably at the moment onResourceReceivedgets called there is no warranty that the resource tag is inside the DOM

Can you share your test.html?

Of course. Also I've been able to isolate the problem, so here is a reduced version of my test.html that fails:

<!DOCTYPE html>
<html>

<head>

  <!-- THIS SEEMS TO BE THE PROBLEM -->
  <link href="http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,400,300,600,700" rel="stylesheet" type="text/css">
  <!-- END OF PROBLEM -->

  <!-- mocha css -->
  <link rel="stylesheet" href="vendor/mocha/mocha.css">
</head>

<body>
  <div id="mocha"></div>
  <!-- this is the only script tag that browser-shim can find -->
  <script src="js/dependencies/jquery.js"></script>

  <!-- mocha js and test js -->
  <script src="vendor/mocha/mocha.js"></script>
  <script src="vendor/chai/chai.js"></script>
  <script>
  mocha.ui('bdd');
  expect = chai.expect;
  </script>
  <script src="test.js"></script>
  <script>
  mocha.run();
  </script>
</body>

</html>

So the problem seem to be related with trying to load resources from remote URLs (although I also experimented with what happened if I loaded my test from http://localhost:1337/test.htmland loaded http://localhost:1337/style.css and it also failed, even though it was a resource from the same host as the web page).

I was able to reproduce this. It appears the onResourceRecieved event is not quite what I thought. it's fired when PhantomJS's WebKit loads the resource - it doesn't mean that the script element exists. Since that element is coming from the network not the disk, WebKit is reading ahead prefetching jquery, mocha, and chai, so the onResourceRecieve fires before the script element exists because the document rendering needs to wait for the CSS in the head to be fetched and applied, so it's not there. Oddly as other resources come in, including the font eventually, I am never able to see it from the phantom side. Even setting a setInterval at 1ms, I never see it appear until after mocha.ui is called. It appears phantom is sticking mocha, chai, and the inline script in the page all at the same time and evaluating it right away in nearly one turn of the event loop.

I think the only way to get this working is for you to call some explicit initialization like in mocha-phantomjs 3.x. I'll try to get this out for you soon.

commented

I also encountered this problem. see the travis-ci job here

@nathanboktae very nice explanation. Let me know if I can help. I've been using your code and it's been very helpful despite that this issue sometimes occur on tests that usually complete successfully