My use case is pretty simple:
First I want to run node server.js(start my Node.js app) - and after Node has started - I want to run mocha test (running some tests on the API provided by previous server.js) by executing npm run test.
The script: "test": "NODE_ENV=development node server.js && mocha test"
Node starts, but unfortunately the mocha testdoes not seem to be executed:
So how can I execute mocha test after node server.js?
The reason why you're running into this is because node server.js continuously runs until killed (Ctrl + C) or a fatal unhandled exception occurs. Since the node process keeps running mocha test never get executed.
One approach to this would be to use gulp as a task runner and utilize tasks implementing gulp-nodemon and gulp-mocha. If you've never used Gulp before or are unfamiliar with task runners I suggest you read the docs beforehand just to get an idea of how it works.
Add the gulpfile.js below to your app (adjust some of the settings as necessary) and modify your package.json scripts with the test script below and this should solve your issue.
gulpfile.js
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var nodemon = require('gulp-nodemon');
gulp.task('nodemon', (cb) => {
let started = false;
return nodemon({
script: 'server.js'
})
.on('start', () => {
if (!started) {
started = true;
return cb();
}
})
.on('restart', () => {
console.log('restarting');
});
});
gulp.task('test', ['nodemon'], function() {
return gulp.src('./test/*.js')
.pipe(mocha({reporter: 'spec' }))
once('error', function() {
process.exit(1);
})
.once('end', function() {
process.exit();
});
});
package.json scripts
{
"scripts": {
"test": "NODE_ENV=development gulp test"
}
}
Supertest Alternative
A more elegant solution ,and in my opinion the better option, would be to rewrite your tests to use supertest. Basically what you do with supertest is pass your Express instance to it and run assertions tests against it with the supertest package.
var mocha = require('mocha');
var request = require('supertest');
var server = require('server');
describe('test server.js', function() {
it('test GET /', function(done) {
request(server)
.get('/')
.expect(200, done);
});
});
add this code to your test case
after(function (done) {
done();
process.exit(1);
})
I have following hello World test to my __tests__ folder:
hello-test.js:
describe('hello world', function() {
it('basic test', function() {
expect(1).toBe(1);
});
});
My aim is to eventually write tests in es6 and run using a gulp task. I have tried running the above with the following gulp task:
gulp.task('jest', ['test-compile'], function(done){
jest.runCLI({
rootDir : __dirname,
//scriptPreprocessor : "../node_modules/babel-jest",
testFileExtensions : ["es6", "js"],
}, __dirname, function (result) {
if (result) {
console.log(result);
} else {
console.log('Tests Failed');
}
done();
});
});
I have also tried running jest using the globally install jest-cli and cannot get it to work, I also tried using the npm test way as shown on line but no matter which of these I try I just get Using Jest CLI v0.6.0 in the terminal, no errors no results.
I am very confused as I seem to be doing what all the doc's online say. I am using Node 4.2.1 if that has any bearing
following is the error i am facing while running mocha tests...
upquire#0.0.0 test D:\tecsol\mtv
mocha test/bootstrap.test.js test/unit/**/*.test.js
1) "before all" hook
0 passing (3m)
1 failing
1) "before all" hook:
Error: timeout of 50000ms exceeded. Ensure the done() callback is being called in this test.
at null.<anonymous> (D:\tecsol\mtv\node_modules\mocha\lib\runnable.js:189:19)
The following is my bootstrap.test.js file:
var Sails = require('sails');
var sails;
before(function(done) {
this.timeout(5000);
Sails.lift({
// configuration for testing purposes
}, function(err, server) {
sails = server;
if (err) return done(err);
// here you can load fixtures, etc.
done(err, sails);
});
});
after(function(done) {
// here you can clear fixtures, etc.
Sails.lower(done);
});
I'm fairly new to the Angular world and have been using the angular-fullstack generator + Yeoman to build out a project. I'm using Sublime (not Webstorm) and have been trying to figure out how to set up the project so that I can debug the mocha tests from the terminal, but am hitting a wall.
Here's the default things.spec.js that's generated with 'yo angular-fullstack' with a debugger statement added in.
var should = require('should');
var app = require('../../app');
var request = require('supertest');
describe('GET /api/things', function() {
it('should respond with JSON array', function(done) {
request(app)
.get('/api/things')
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
debugger;
if (err) return done(err);
res.body.should.be.instanceof(Array);
done();
});
});
});
By combining advice from the grunt-mocha-test documentation and this SO answer, I've updated the test script in package.json as follows:
"scripts": {
"test": "node-debug <PATH TO GRUNT-CLI>\\grunt test"
}
When I run 'npm test', node-inspector successfully boots up a browser instance and attaches the debug session to my test process. However, when I press "continue", the debugger breakpoint is NOT hit and the test fails with the following stack. Anyone have any clues as to what's causing this?
TypeError: Cannot read property '_host' of null
at ClientRequest.http.ClientRequest.onSocket (eval at WRAPPED_BY_NODE_INSPECTOR (\node_modules\node-inspector\node_modules\v8-debug\v8-debug.js:95:15), <anonymous>:381:28)
at new ClientRequest (http.js:1432:10)
at Object.exports.request (http.js:1843:10)
at Test.Request.request (\node_modules\supertest\node_modules\superagent\lib\node\index.js:615:28)
at Test.Request.end (\node_modules\supertest\node_modules\superagent\lib\node\index.js:677:18)
at Test.end (\node_modules\supertest\lib\test.js:123:7)
at Context.<anonymous> (\server\api\thing\thing.spec.js:14:8)
at Test.Runnable.run (\node_modules\grunt-mocha-test\node_modules\mocha\lib\runnable.js:196:15)
at Runner.runTest (\node_modules\grunt-mocha-test\node_modules\mocha\lib\runner.js:374:10)
at Runner.runTests.next (\node_modules\grunt-mocha-test\node_modules\mocha\lib\runner.js:452:12)
This looks like a bug in Node Inspector.
https://github.com/node-inspector/node-inspector/issues/698
I am trying to run karma tests from gulp task and I am getting this error:
Error: 1
at formatError (C:\Users\Tim\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:161:10)
at Gulp.<anonymous> (C:\Users\Tim\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:187:15)
at Gulp.emit (events.js:95:17)
at Gulp.Orchestrator._emitTaskDone (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\index.js:264:8)
at C:\path\to\project\node_modules\gulp\node_modules\orchestrator\index.js:275:23
at finish (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\lib\runTask.js:21:8)
at cb (C:\path\to\project\node_modules\gulp\node_modules\orchestrator\lib\runTask.js:29:3)
at removeAllListeners (C:\path\to\project\node_modules\karma\lib\server.js:216:7)
at Server.<anonymous> (C:\path\to\project\node_modules\karma\lib\server.js:227:9)
at Server.g (events.js:180:16)
My system is Windows 7, nodejs version is v0.10.32, gulp version:
[10:26:52] CLI version 3.8.8
[10:26:52] Local version 3.8.9
Also, the same error I am getting on Ubuntu 12.04 LTS while on newer Ubuntu (not sure what version) and mac os it is seems to be working ok. What can cause this error?
Update 5/11/2016: Before writing comment about the fact that accepted answer hide errors, please, see first two comments to that particular accepted answer. Use it only if know what you are doing. Related info: https://github.com/karma-runner/gulp-karma/pull/15
How are you running your tests with Gulp? I came up against this issue recently on OSX, running node v0.11.14 and gulp 3.8.10, whenever there were failing tests.
Changing from the recommended:
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done);
});
To:
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function() {
done();
});
});
...got rid of this error.
Seems to be down to how gulp handles error messages when an error is signalled in a callback. See Improve error messages on exit for more information.
None of these solutions worked correctly for me using gulp 3.9.1 and karma 1.1.1. Adding a reference to gulp-util npm install --save-dev gulp-util and updating the task to the below fix the error output very nicely, while maintaining exit status correctly.
var gutil = require('gulp-util');
gulp.task('test', function (done) {
new Server({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(err){
if(err === 0){
done();
} else {
done(new gutil.PluginError('karma', {
message: 'Karma Tests failed'
}));
}
}).start();
});
Below is a code snippet from gulp patterns on using Karma. It's a bit similar, but also uses the newer method how to start the karma.
/**
* Start the tests using karma.
* #param {boolean} singleRun - True means run once and end (CI), or keep running (dev)
* #param {Function} done - Callback to fire when karma is done
* #return {undefined}
*/
function startTests(singleRun, done) {
var child;
var excludeFiles = [];
var fork = require('child_process').fork;
var KarmaServer = require('karma').Server;
var serverSpecs = config.serverIntegrationSpecs;
if (args.startServers) {
log('Starting servers');
var savedEnv = process.env;
savedEnv.NODE_ENV = 'dev';
savedEnv.PORT = 8888;
child = fork(config.nodeServer);
} else {
if (serverSpecs && serverSpecs.length) {
excludeFiles = serverSpecs;
}
}
var server = new KarmaServer({
configFile: __dirname + '/karma.conf.js',
exclude: excludeFiles,
singleRun: singleRun
}, karmaCompleted);
server.start();
////////////////
function karmaCompleted(karmaResult) {
log('Karma completed');
if (child) {
log('shutting down the child process');
child.kill();
}
if (karmaResult === 1) {
done('karma: tests failed with code ' + karmaResult);
} else {
done();
}
}
}
What worked for me and gave a nice formatted error message is to provide an Error instance to the done callback.
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(result) {
if (result > 0) {
return done(new Error(`Karma exited with status code ${result}`));
}
done();
});
});
If you want to return with an error code, and want to see Karma's error output but not Gulp's (probably unrelated) stack trace:
gulp.task('test', function() {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, function(karmaExitStatus) {
if (karmaExitStatus) {
process.exit(1);
}
});
});
Not sure about Ubuntu, but I was getting a similar error on Windows, and installing one version back fixed it right away like this:
npm install -g gulp#3.8.8
npm install gulp#3.8.8
this is gulp's way of telling your tests have failed and that karma exited with a return code of 1. Why you would want to call done yourself and not pass the error as a message baffles me.
The right way to solve this according to Karma's documentation and https://github.com/pkozlowski-opensource, is to rely on Karma's watch mechanism rather than Gulp's:
gulp.task('tdd', function (done) {
karma.start({
configFile: __dirname + '/karma.conf.js'
}, done);
});
Note the omission of singleRun: true.
#McDamon's workaround will work for gulp.watch, but you don't want to swallow exit codes like that when running on a CI server.
Gulp is also reworking how they handle exit codes in scenarios just like this one. See https://github.com/gulpjs/gulp/issues/71 and the other dozen or so related issues.
gulp.task('test', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: false
}, done);
});
passing singleRun: false argument will prevent the process from returning a value different of 0 (which would signify an error and exit gulp).
Run with singleRun: true if you only launching your test from a command line, not part of a continuous integration suite.
In case anyone else comes here, do not use the accepted solution. It will hide failed tests. If you need a quick solution to modify your gulp test task, you can use the solution found in this comment in this github thread.
gulp.src(src)
// pipeline...
.on('error', function (error) {
console.error('' + error);
});