I seem to be having a problem setting up my unit tests for my NodeJS app and then running them with Jasmine. The problem comes in using the done
function of Jasmine. Whenver I include the done
function in my test, I get an error that reads: Warning: Cannot read property 'clearTimeout' of undefined Use --force to continue.
I'm pretty sure I'm not doing something right, but what that something is continues to elude me.
My Gruntfile.js:
module.exports = function(grunt){
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
grunt.initConfig({
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: [
'Gruntfile.js',
'app/scripts/Directives/**/*.js',
'app/scripts/Services/**/*.js',
'app/scripts/app.js'
]
},
// Empties folders to start fresh
clean: {
options: { force: true },
dist: {
files: [
{
dot: true,
src: [
'/dist/*'
]
}
]
},
coverage: {
files: [
{
dot: true,
src: [
'.coverage/'
]
}
]
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [
{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt,json,js,shtml,template}',
'images/{,*/}*.{webp}',
'fonts/*',
'images/**/*.svg',
'api-documentation/**/**/*',
'api-explorer/**/*',
'styles/*.{ttf,woff,svg,css}',
'docs/**/*',
'template/**/*.{htm,html}',
'locale/*',
'config/*'
],
rename: function(dest, src){
if(src.indexOf('customizations.html.template') !== -1 ||
src.indexOf('customizations.js.template') !== -1){
console.log( dest + '/' + src.replace('.template', ''));
return dest + '/' + src.replace('.template', '');
}
return dest + '/' + src;
}
},
{
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: [
'generated/*'
]
},
{
expand:true,
cwd: '.tmp/styles',
dest: '<%= yeoman.dist %>/styles',
src:['customer.css']
}
]
}
},
// Test settings
karma: {
unit: {
configFile: 'karma.conf.js',
singleRun: true,
reporters: ['dots']
},
coverage: {
configFile: 'karma.coverage.conf.js',
singleRun: true,
reporters: ['spec', 'coverage'],
coverageReporter: {
type: 'html',
dir: '.coverage/'
}
},
node:{
configFile:'karma.node.conf.js',
singleRun:true,
reporters:['spec', 'coverage'],
coverageReporter: {
type: 'html',
dir: '.nodeCoverage/'
}
}
},
open : {
coverage : {
path: 'http://127.0.0.1:8888/src'
},
covReport: {
path: 'http://localhost:63342/ClassroomLibrary/' + grunt.file.expand('.coverage/Phantom*/index.html')
}
},
jasmine_nodejs:{
options:{
specNameSuffix:'node.spec.js',
reporters:{
console:{
colors:true,
cleanStack:1,
verbosity:4,
listStyle:'indent',
activity:false
}
}
},
all:{
options:{
useHelpers:true
},
specs:[
'tests/Node/**'
]
}
},
nodemon:{
tests:{
script:'app/index.js'
}
},
concurrent:{
nodeTests:['nodemon', 'jasmine_nodejs']
},
run_node:{
start:{
files:{src:['app/index.js']}
}
},
stop_node:{
stop:{
files:{src:['app/index.js']}
}
}
});
grunt.loadNpmTasks('grunt-jasmine-nodejs');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-run-node');
grunt.registerTask('test', [
'karma:unit'
]);
grunt.registerTask('coverage', [
'clean:coverage',
'karma:coverage',
'open:covReport'
]);
grunt.registerTask('nodeTests', ['concurrent:nodeTests']);
grunt.registerTask('testingNode', ['run_node', 'jasmine_nodejs', 'stop_node']);
//grunt.registerTask('karmaNode', ['run_node', 'karma:node', 'stop_node']);
};
The test suite in question:
var request = require('http');
describe('Node server', function(){
'use strict';
//http://www.randomjavascript.com/2012/12/using-jasmine-node-to-test-your-node.html
var serverUrl = 'http://127.0.0.1:2425';
it('should respond to /', function(done){
request.get(serverUrl, function(response){
expect(response.statusCode).toBe(200);
done();
});
});
});
Obviously I've tried a couple of different ways to get this to work. Running them via Karma was more trouble than it was worth (I left that config in there to show what I have tried.) While I have been happy with the output of nodeMon and jasmine-nodejs I still can't get the whole thing to run front to back because without the done
function things hang just like you would expect them to. It is supposed to be just THERE but for me it isn't. My package.json contains:
{
"name": "myProject",
"version": "0.0.1",
"dependencies":{},
"devDependencies": {
"karma": "~0.13",
"karma-coverage": "~0.5",
"karma-phantomjs-launcher": "~1.0",
"karma-ng-html2js-preprocessor": "~0.1",
"phantomjs-prebuilt": "~2.1",
"grunt": "~1.0",
"grunt-contrib-clean": "~0.7",
"grunt-contrib-uglify": "~0.11",
"grunt-contrib-concat": "~0.5",
"grunt-contrib-copy": "~1.0",
"grunt-concurrent":"~2.3",
"grunt-jasmine-nodejs":"~1.5",
"grunt-jasmine-node-coverage":"0.5.0",
"grunt-open":"~0.2",
"grunt-nodemon":"~0.4",
"grunt-run-node":"~0.1",
"grunt-karma": "~0.12",
"jasmine-core": "~2.4",
"jasmine-node":"~1.14",
"karma-jasmine": "~0.3",
"karma-jasmine-matchers": "~2.0",
"karma-spec-reporter":"~0.0",
"karma-requirejs":"~1.0",
"load-grunt-tasks": "~3.4",
"uglify-js": "~2.6",
"grunt-sass": "~1.1",
"jshint":"~2.9"
},
"engines": {
"node": ">=0.12.0"
},
"scripts": {
"global": "npm i karma-cli grunt-cli -g"
}
}
Can someone please tell me where the process is missing what it needs?
One thought--can you confirm the version of Jasmine you're actually using matches what you're intending to use? I think the 'done' callback was added in 2.0, so I could see this error occurring on an older version...
EDIT: you're using the "jasmine-node" package which is version 1.3.1, so that feature won't be available.