angular-cli: karma jsdom launcher hangs

Bug Report

- [x] bug report -> please search issues before submitting

Area

- [x] `npm run test`   or  `ng test`

Versions

Angular CLI: 6.0.8 Node: 10.6.0 OS: linux x64 (Linux Mint) Angular: 6.0.9 Npm: 6.1.0 and 6.2.0

Reproduction steps

  1. ng new appWithJsdom
  2. cd appWithJsdom
  3. npm install
  4. npm install karma-jsdom-launcher jsdom --save-dev
  5. modify src/karma.conf.js
diff --git a/src/karma.conf.js b/src/karma.conf.js
index b6e0042..c9f81b7 100644
--- a/src/karma.conf.js
+++ b/src/karma.conf.js
@@ -8,6 +8,7 @@ module.exports = function (config) {
     plugins: [
       require('karma-jasmine'),
       require('karma-chrome-launcher'),
+      require('karma-jsdom-launcher'),
       require('karma-jasmine-html-reporter'),
       require('karma-coverage-istanbul-reporter'),
       require('@angular-devkit/build-angular/plugins/karma')
@@ -24,8 +25,8 @@ module.exports = function (config) {
     port: 9876,
     colors: true,
     logLevel: config.LOG_INFO,
-    autoWatch: true,
-    browsers: ['Chrome'],
-    singleRun: false
+    autoWatch: false,
+    browsers: ['jsdom'],
+    singleRun: true
   });
 };

The log given by the failure

Then ng test displays build statements in CLI:

16 07 2018 13:06:35.821:WARN [karma]: Port 9876 in use
16 07 2018 13:06:35.823:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9878/
16 07 2018 13:06:35.823:INFO [launcher]: Launching browsers jsdom with unlimited concurrency
16 07 2018 13:06:35.842:INFO [launcher]: Starting browser jsdom
16 07 2018 13:06:40.252:INFO [Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.11.0]: Connected on socket p6lvGGcG6uRr_zm5AAAB with id 26520884

The the console is cleared, nothings happens. Ctrl-c eventually leads me back to the console.

This is repeatable. No other user is connected to the desktop, no other node instances are running concurrently. Can’t really run too many processes on it anyway.

When I use ‘Chrome’ or ‘ChromeHeadless’, the browser pops up etc, runs the tests all green. Eveidently, I have the Chrome browser installed locally.

Desired functionality

I need a way to run the UI tests in a build process. Tried PhantomJS - no luck.

Would like to use jsdom as test browser for builds - as it does headless mode with minimal effort. Can’t install a browser on the build server. Though puppeteer and ChromeHeadless, the karma launcher fails with not finding libX11.so …

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 16 (10 by maintainers)

Most upvoted comments

I’ve found a fix, but it’s a bit hacky. The problem is something to do with the way JSDom performs synchronous requests, which are used for loading <script src="..."> elements. For some reason, the Karma server doesn’t respond to those requests. I’m not sure whether the problem is in Karma or in JSDom; or possibly in the way Karma launches JSDom.

My hack is to force JSDom to treat all scripts as asynchronous. In theory this could break your application; but at least for Angular apps, it doesn’t seem to matter.

Here is the hack:

  1. Start editing node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js
  2. At line 599, add the following: flag.synchronous = false; // hack The resulting file will look like:
    598: }
    599: flag.synchronous = false; // hack
    600: if (flag.synchronous) {
    
  3. Save the file
  4. Run ng test

Please let me know if this works for you.

No, it isn’t an Angular CLI issue. The problem lies in karma-jsdom-launcher.

Most other karma launchers (e.g. karma-chrome-launcher, karma-phantomjs-launcher) use Node’s child_process.spawn method to launch the browser as a separate process. But karma-jsdom-launcher runs jsdom in-process, which is the same process as Angular’s web server. When JSDom tries to perform a synchronous request to the Angular server, it’s like a snake eating its own tail: the server can’t respond until JSDom finishes its request, but JSDom is waiting for the server to respond. The result is deadlock.

JSDom isn’t without blame. It really ought to use async/await to handle synchronous XHR, but that would require major refactoring.

I’m exploring the possibility of adding a runtime argument to JSDom which would force all requests to be asynchronous, then making karma-jsdom-launcher use that option. I don’t know when or if I’ll be able to do that, or whether such a change would even be welcomed by JSDom’s maintainers. In the meantime, anyone with urgent requirements is advised to use my hack above. (I use a postinstall script to patch the file.)

Two and a half months later, I revisit this defect.

I am not able to reproduce it. The same project configuration now runs and terminates nicely, returning to the command prompt.

Closing this issue.