What a Nightmare!


Ever heard of NightmareJS? Me either until today. Just in time too, I was beginning to pull my hair out using PhantomJS to run a suite of JavaScript unit tests.

The problem with PhantomJS

During my Visual Studio Team Services build I was experiencing quite a few sporadic failures where PhantonJS failed to connect. The result of this was none of my unit tests were ran and my build failed (a good thing since the tests didn’t run). After many hours of trying to figure out what the right combination of Node, Karma, Jasmine, and PhantomJS could be causing this I decided to look for another solution.

The PhantomJS Error of Death (PEoD)

Here is the exact error that we were receiving:

[32m09 03 2017 10:28:54.632:INFO [karma]: Karma v0.13.22 server started at http://localhost:22200/
2017-03-09T16:28:54.6322872Z 09 03 2017 10:28:54.632:INFO [launcher]: Starting browser PhantomJS
2017-03-09T16:28:56.3259069Z 09 03 2017 10:28:56.325:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket -I7m1ca0zjoJo8roAAAA with id 12617843
2017-03-09T16:29:26.3329205Z 09 03 2017 10:29:26.332:WARN [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Disconnected (1 times), because no message in 30000 ms.
2017-03-09T16:29:26.3509918Z [10:29:26] 'test-minified' errored after 32 s
2017-03-09T16:29:26.3509918Z [10:29:26] Error: 1
2017-03-09T16:29:26.3509918Z     at formatError (D:\A1\_work\22\s\Source\WebUI\node_modules\gulp\bin\gulp.js:169:10)
2017-03-09T16:29:26.3509918Z     at Gulp.<anonymous> (D:\A1\_work\22\s\Source\WebUI\node_modules\gulp\bin\gulp.js:195:15)
2017-03-09T16:29:26.3509918Z     at emitOne (events.js:82:20)
2017-03-09T16:29:26.3509918Z     at Gulp.emit (events.js:169:7)
2017-03-09T16:29:26.3509918Z     at Gulp.Orchestrator._emitTaskDone (D:\A1\_work\22\s\Source\WebUI\node_modules\orchestrator\index.js:264:8)
2017-03-09T16:29:26.3509918Z     at D:\A1\_work\22\s\Source\WebUI\node_modules\orchestrator\index.js:275:23
2017-03-09T16:29:26.3509918Z     at finish (D:\A1\_work\22\s\Source\WebUI\node_modules\orchestrator\lib\runTask.js:21:8)
2017-03-09T16:29:26.3509918Z     at cb (D:\A1\_work\22\s\Source\WebUI\node_modules\orchestrator\lib\runTask.js:29:3)
2017-03-09T16:29:26.3509918Z     at removeAllListeners (D:\A1\_work\22\s\Source\WebUI\node_modules\karma\lib\server.js:336:7)
2017-03-09T16:29:26.3509918Z     at Server.<anonymous> (D:\A1\_work\22\s\Source\WebUI\node_modules\karma\lib\server.js:347:9)
2017-03-09T16:29:26.3509918Z     at Server.g (events.js:260:16)
2017-03-09T16:29:26.3509918Z     at emitNone (events.js:72:20)
2017-03-09T16:29:26.3509918Z     at Server.emit (events.js:166:7)
2017-03-09T16:29:26.3509918Z     at emitCloseNT (net.js:1537:8)
2017-03-09T16:29:26.3509918Z     at nextTickCallbackWith1Arg (node.js:431:9)
2017-03-09T16:29:26.3509918Z     at process._tickCallback (node.js:353:17)

Nightmare to the rescue

Nightmare is a very nicely documented and human readable browser API. Under the hood it uses Electon which is suppose to be 2x faster than PhantomJS! I’m sold!

Why did I use it?

I was previously using PhantomJS through karma to run all of our JavaScript unit test but we kept getting sporadic failures where Phantom couldn’t connect.

How to use Nightmare with karma

  1. Install the nightmare launcher

yarn add -D karma-nightmare

  1. Add Nighmare as your karma browser either within your karma config or within your karma API call. Here’s an example using the Karma API directly.
function runKarma(files, reporters, browser, singleRun, done) {
    log('starting karma');

    return new Server({
        port: 9999,
        browsers: ['Nightmare'],        
        files: files,
        singleRun: true,
        action: 'run',
        logLevel: 'info',
        captureTimeout: 30000,
        browserNoActivityTimeout: 30000,
        frameworks: ['jasmine']        
    }, function (err) {
            handleKarmaError(err, done);