badeball / karma-jsdom-launcher

A Karma plugin. Launcher for jsdom.
MIT License
37 stars 16 forks source link

Exception when trying to run Angular's unit tests #1

Closed thorn0 closed 5 years ago

thorn0 commented 9 years ago

I decided to test how compatible Angular 1.x is with jsdom.

git clone https://github.com/angular/angular.js.git
cd angular.js
bower i
npm i
npm i karma-jsdom-launcher
grunt test:jquery --debug --browsers jsdom

Sometimes (seldom) it runs all the tests, but most often it ends like this:

Other 0.0.0 (Other): Executed 17 of 4579 (1 FAILED) (0 secs / 0.23 secs)
ERROR [karma]: Cannot read property 'call' of undefined
Other 0.0.0 (Other): Executed 17 of 4579 (1 FAILED) (0.56 secs / 0.23 secs)
Warning: Karma test(s) failed. Exit code: 1 Use --force to continue.

I.e. after executing 10 to 30 tests, Karma stops with this error: Cannot read property 'call' of undefined, and I can't figure out how to get the stack trace of this exception. Any ideas?

Windows 7 x64, Node.js 4.1.2

thorn0 commented 9 years ago

Adding virtualConsole: jsdom.createVirtualConsole().sendTo(console) to the jsdom.env call helps a lot in debugging.

badeball commented 9 years ago

Hi, @thorn0

Thanks for reporting this issue. I haven't quite figured it out yet, but I wanted to report back my preliminary findings.

If anyone else is attempting to recreate the issue, the node version is important. Angular.js@master at current time of writing depends upon utf-8-validate-1.1.0, which does not compile with node-4.2.1.

The following patch to karma-jsdom-launcher, as suggested above, will give more debug output.

--- a/index.js
+++ b/index.js
@@ -10,6 +10,7 @@ var jsdomBrowser = function (baseBrowserDecorator) {
         FetchExternalResources: ["script", "iframe"],
         ProcessExternalResources: ["script"]
       },
+      virtualConsole: jsdom.createVirtualConsole().sendTo(console),
       created: function (error, window) {
         // Do nothing.
       }

However, I also found that jsdom gives somewhat weird stack traces upon some errors. Eg. it gave the following stack trace.

Error: Uncaught [TypeError: Cannot read property 'call' of undefined]
    at reportException (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:58:24)
    at callListeners (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:180:9)
    at dispatchPhase (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:161:7)
    at EventTarget.dispatchEvent (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:117:3)
    at define.proto.dispatchEvent (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:321:55)
    at /home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/browser/resource-loader.js:35:13
    at Object.item.check (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:131:11)
    at Object.item.check (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:134:23)
    at Object.item.check (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:134:23)
    at Object.item.check (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:134:23) [TypeError: Cannot read property 'call' of undefined]

But by applying the following patch to ./karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js, I got the stack trace shown further below. This points to where the error is actually occurring.

--- runtime-script-errors.js    2015-10-26 10:42:55.998653979 +0100
+++ runtime-script-errors.js    2015-10-26 10:43:01.628805516 +0100
@@ -32,7 +32,6 @@
 }

 module.exports = function reportException(window, error, filenameHint) {
+  console.log(error.stack);
   // This function will give good results on real Error objects with stacks; poor ones otherwise

   const stack = error && error.stack;
TypeError: Cannot read property 'call' of undefined
    at angular.scenario.Application.executeAction (http://localhost:9880/base/src/ngScenario/Application.js?8d66afd57ee296796dce671ad1eaa443e27a1e74:119:18)
    at null.<anonymous> (http://localhost:9880/base/src/ngScenario/Application.js?8d66afd57ee296796dce671ad1eaa443e27a1e74:73:16)
    at jQuery.event.dispatch (http://localhost:9880/base/bower_components/jquery/dist/jquery.js?8d55aabf2b76486cc311fdc553a3613cad46aa3f:4409:9)
    at elemData.handle (http://localhost:9880/base/bower_components/jquery/dist/jquery.js?8d55aabf2b76486cc311fdc553a3613cad46aa3f:4095:28)
    at callListeners (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:172:34)
    at dispatchPhase (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:161:7)
    at EventTarget.dispatchEvent (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/events/EventTarget.js:117:3)
    at define.proto.dispatchEvent (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:321:55)
    at /home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/browser/resource-loader.js:35:13
    at Object.item.check (/home/jonas/projects/karma-jsdom-launcher/node_modules/jsdom/lib/jsdom/level2/html.js:131:11)

This led me to look into test/ngScenario/ApplicationSpec.js and I found the test that is the culprit. By applying the following patch, the test suite seems to run flawlessly every time (except for the fact that they don't actually pass).

--- a/test/ngScenario/ApplicationSpec.js
+++ b/test/ngScenario/ApplicationSpec.js
@@ -22,7 +22,7 @@ describe('angular.scenario.Application', function() {
   });

-  it('should return new $window and $document after navigateTo', function() {
+  xit('should return new $window and $document after navigateTo', function() {
     var called;
     var testWindow, testDocument, counter = 0;
     app.getWindow_ = function() {

Does this give you any hints?

thorn0 commented 9 years ago

I went that far too, but it's still not clear why jsdom crashes. I also tried to update jsdom to the version 7.0.2. The crash is still there. Basically it seems it's an uncaught exception in the load handler of an iframe that somehow causes the crash, but there is more to it than that as I failed to isolate the problem.

thorn0 commented 9 years ago

I just completely deleted test/ngScenario (because of the current issue) and test/ngAnimate(because jsdom doesn't support CSS animation anyway) folders for now. The results of running the tests are pretty interesting. Actually I'm investigating a difference in behavior my app reveals being run in jsdom. I thought there could've been something in $http that is incompatible with jsdom, but the tests don't confirm this hypothesis.

BTW, that utf-8-validate dependency of Karma is optional, so it doesn't matter that it doesn't compile.

badeball commented 5 years ago

Closing due to inactivity. If someone is still attempting to run Angular's tests in jsdom, then I might take another stab at it.