How to execute jasmine tests for node modules from grunt - javascript

I want to run some Jasmine 2.x tests for node.js modules in a Grunt build. My setup looks like this:
src/foo.js
exports.bar = 23;
spec/foo.spec.js
var foo = require("../src/foo.js");
define("foo", function() {
it("exports bar as 23", function() {
expect(foo.bar).toBe(23);
});
});
With grunt-contrib-jasmine the node module system is not available and I get
>> ReferenceError: Can't find variable: require at
>> spec/foo.spec.js:1
There is grunt-jasmine-node, but it depends on jasmine-node which is unmaintained and includes Jasmine 1.3.1, so this is not an option.
Jasmine supports node.js out of the box, by including a file jasmine.json in the spec directory, I can run the tests with the jasmine cli. Is there any clean way to run the same tests from grunt as well?

You could use grunt-exec, which just executes the value as if typed on the command line:
module.exports = function (grunt) {
grunt.initConfig({
exec: {
jasmine: "jasmine"
},
env: {
test: {
NODE_ENV: "test"
}
}
});
grunt.loadNpmTasks("grunt-exec");
grunt.loadNpmTasks("grunt-env");
grunt.registerTask("test", [
"env:test",
"exec:jasmine"
]);
};
This will allow you to keep jasmine up to date as well as use it with other grunt tasks.

Related

How to expose a dependency when writing a grunt module

I'm building a module grunt-foo which is utilizing grunt-galvanize (e.g. its in my package.json as a dependency). Something like this:
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt)
grunt.registerMultiTask('foo', 'do your foo', function() {
grunt.task.run('bar');
});
grunt.registerTask('bar', function() {
// Add some galvanize configs
grunt.option('galvanizeConfig', { configs: { ... } });
grunt.task.run(['galvanize:baz'])
});
grunt.registerTask('baz', function() { grunt.log.ok('baz'); });
};
However, when I utilize this grunt module in an app and run grunt foo I get something like Warning: Task "galvanize:baz" not found. Use --force to continue.
I'm looking for a solution that does not involve my having to install grunt-galvanize as a dependency (dev or otherwise) within the apps that will utilize my grunt module.

grunt jasmine-node tests are running twice

I set up grunt to run node.js jasmine tests. For some reason, with this config, the results always show double the tests.
Here is my config:
I'm using jasmine-node which plugs into grunt.
/spec/some-spec.js:
var myModule = require('../src/myModule.js');
describe('test', function(){
it('works', function(done){
setTimeout(function(){
expect(1).toBe(1);
done();
}, 100);
});
});
Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
jasmine_node: {
options: {
forceExit: true
},
all: ['spec/']
}
});
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.registerTask('default', ['jasmine_node']);
};
This results in two tests running rather than one.
> grunt
Running "jasmine_node:all" (jasmine_node) task
..
Finished in 0.216 seconds
2 tests, 2 assertions, 0 failures, 0 skipped
I was able to reproduce the behavior. This is what seems to be happening:
The task looks in the specified folder (spec in your case) for files with spec in the name.
Then it looks again in every folder in the whole project for files with spec in the name.
What it ends up with is 2 overlapping sets of test files to run.
My first attempt at trying to coerce it into more logical behavior was to set specNameMatcher: null (default is 'spec'), and leave the folder set to 'spec/'. This results in no tests being run, since apparently both conditions (name and folder) must be met for files in the specified folder. You get the same problem if specNameMatcher is left at the default value, but the files in the folder don't have 'spec' in the name.
What does work is to set the folder (or 'test set' or whatever you want to call it) to []:
jasmine_node: {
options: {
forceExit: true
},
all: []
}
The catch is that if you have any other files somewhere else in the project with 'spec' in the name, they'll be mistaken for tests by jasmine.
I would consider this behavior a bug, and it should probably be reported via the project's github issues page.
This grunt plugin ( https://github.com/jasmine-contrib/grunt-jasmine-node ) seems to be dead ( https://github.com/jasmine-contrib/grunt-jasmine-node/issues/60 ).
Maybe it is a better to switch to https://github.com/onury/grunt-jasmine-nodejs ?
The jasmine-node project is pretty old. The latest commit is from July of 2014. The grunt-jasmine-node plugin appears to be active, but running against something that is going stale seems a little pointless IMHO.
To test CommonJS modules using Jasmine I'd recommend using Karma along with the
karma-jasmine and karma-commonjs plugins. I got your example working with the following files:
package.json
{
"private": "true",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-jasmine-node": "^0.3.1",
"grunt-karma": "^0.10.1",
"jasmine-core": "^2.3.4",
"karma": "^0.12.31",
"karma-commonjs": "0.0.13",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4"
}
}
karma.conf.js
module.exports = function(config) {
config.set({
basePath: '.',
frameworks: ['jasmine', 'commonjs'],
files: [{
pattern: 'src/**/*.js'
}, {
pattern: 'spec/**/*.js'
}],
preprocessors: {
'src/**/*.js': ['commonjs'],
'spec/**/*.js': ['commonjs']
},
reporters: ['progress'],
browsers: ['PhantomJS']
});
};
Gruntfile.js (optional if you still want to use grunt)
module.exports = function(grunt) {
grunt.initConfig({
karma: {
unit: {
configFile: 'karma.conf.js',
options: {
singleRun: true
}
}
}
});
grunt.loadNpmTasks('grunt-karma');
grunt.registerTask('default', ['karma:unit']);
};
You should also install the karma command line runner globally, just like you probably did with grunt. npm install -g karma-cli
From your command line you can start karma by typing karma start. It will run the tests and then watch your files and re-run them on every save. (VERY NICE)
Alternatively you can run karma start --single-run to have it just run your tests once and exit. If you also updated your Gruntfile you can also just run grunt to run the tests once.
The current up voted answer isn't the solution. You simply modify the expression that's going to match your tests. The answer is as follows:
module.exports = function(grunt) {
grunt.initConfig({
jasmine_node: {
options: {
forceExit: true
},
all: ['spec/*spec.js']
}
});
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.registerTask('default', ['jasmine_node']);
};
Here you can see that 'all' is set to *'spec/spec.js'. This will search for all tests.
Secondly, just because a project hasn't had a recently commit, doesn't mean it's "old". jasmine-node is simply stable.
I have the same issue using grunt-jasmine-node, and as aeryaguzov points out, that project is no longer maintained. Switching to grunt-jasmine-node-new solves the issue for me.
grunt-jasmine-node-new is a fork of grunt-jasmine-node that is actively maintained, and can be found here: https://www.npmjs.com/package/grunt-jasmine-node-new

Karma: Running a single test file from command line

So, I've been looking all over for this, found "similar" answers here, but not exactly what I want.
Right now if I want to test a single file with karma, I need to do fit(), fdescribe() on the file in question...
However, what I do want is to be able to just call karma, with the config file, and direct it to a specific file, so I don't need to modify the file at all, ie:
karma run --conf karma.conf.js --file /path/to/specific/test_file.js
is it possible to do this? Or with any helper? (using grunt or gulp?)
First you need to start karma server with
karma start
Then, you can use grep to filter a specific test or describe block:
karma run -- --grep=testDescriptionFilter
Even though --files is no longer supported, you can use an env variable to provide a list of files:
// karma.conf.js
function getSpecs(specList) {
if (specList) {
return specList.split(',')
} else {
return ['**/*_spec.js'] // whatever your default glob is
}
}
module.exports = function(config) {
config.set({
//...
files: ['app.js'].concat(getSpecs(process.env.KARMA_SPECS))
});
});
Then in CLI:
$ env KARMA_SPECS="spec1.js,spec2.js" karma start karma.conf.js --single-run
This option is no longer supported in recent versions of karma:
see https://github.com/karma-runner/karma/issues/1731#issuecomment-174227054
The files array can be redefined using the CLI as such:
karma start --files=Array("test/Spec/services/myServiceSpec.js")
or escaped:
karma start --files=Array\(\"test/Spec/services/myServiceSpec.js\"\)
References
karma-runner source: cli.js
karma-runner source: config.js
I tried #Yuriy Kharchenko's solution but ran into a Expected string or object with "pattern" property error.
Therefore I made the following modifications to his answer and now I'm able to run single files using Karma:
function getSpecs(specList) {
if (specList) {
return specList.toString();
} else {
return ['**/*_spec.js'] // whatever your default glob is
}
}
module.exports = function(config) {
config.set({
//...
files: [
{ pattern: getSpecs(process.env.KARMA_SPECS), type: "module"}
]
});
});
Note: This solution only works with a single file mentioned in the KARMA_SPECS env variable. Ex: export KARMA_SPECS="src/plugins/muc-views/tests/spec1.js"

Karma jasmine tests: Highlight diff in terminal

I'm using Karma with Jasmine for my tests. In some tests, I have large objects that the test relies on. When I do something like
expect(obj).toEqual(expectedObj);
and obj != expectedObj, I get an error message in my terminal. But this error is really long, because it includes both of the objects, and it's very hard to see, in what parts the two objects are different.
So, is there any highlighter for the terminal, that can be used along with karma? This way, it would be much more easy to figure out, what's wrong.
I had the same problem and what did it for me was karma-jasmine-diff-reporter.
Just install it:
npm install karma-jasmine-diff-reporter --save-dev
and configure it as a reporter, eg:
// karma.conf.js
module.exports = function(config) {
config.set({
reporters: ['jasmine-diff']
});
};
You can configure it to pretty print:
// karma.conf.js
module.exports = function(config) {
config.set({
reporters: ['jasmine-diff'],
jasmineDiffReporter: {
pretty: true, // 2 spaces by default for one indent level
matchers: {
toEqual: {
pretty: false // disable pretty print for toEqual
}
}
}
});
};
Output will be something like this:

How to run JSTestDriver from the commandline if JSTD TestCase method is wrapped by RequireJS?

I recently added RequireJS to my project and now have rewritten my JSTestDriver testcases in such a way that they are wrapped by requireJS:
//this does run when running from within WebStorm
require(['backbone', 'models/ParametersModel'],function (backbone, params) {
TestCase("test aTestCaseInside", {
setUp: function () {
assertNotUndefined('backbone is undefined', backbone);
assertNotUndefined('params is undefined', params);
this.p = new params();
},
//todo: without the backbone dependency everything runs as expected!
testClass: function () {
console.log("running a test INSIDE the requireJS context");
assertEquals("", this.p.getValue(), 'a value from param')
}
});
});
When I run this test through the JSTD plugin for JetBrain's Webstorm IDE, it runs fine.
But I would like to be able to run the JSTestDriver from the commandline as well. This does not work however. If I execute this command:
java -jar test\vendor\JsTestDriver\1.3.5\jar\JsTestDriver.jar --config jsTestDriver.jstd --browser "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --port 14999 --tests all --captureConsole --runnerMode PROFILE
I get this output:
feb 13, 2014 10:56:41 AM com.google.jstestdriver.server.handlers.pages.SlavePageRequest createCaptureUrl
SEVERE: Invalid/No runner type specified: null falling back to BROWSER
Total 0 tests (Passed: 0; Fails: 0; Errors: 0) (0,00 ms)
feb 13, 2014 10:56:41 AM com.google.jstestdriver.ActionRunner runActions
INFO:
In the console of the browser I get:
Failed to load resource http://127.0.0.1:14999/query/1392285643189
Failed to load resource http://127.0.0.1:14999/test/vendor/backbone/1.0.0/js/backbone.js
The command on the commandline is correct, since the when I create a TestCase outside of the require function, it does show that the tests have run and passed!
How to configure JSTD with Requiere JS to able to run the tests from the commandline?
Thank you.
Use the AMD plugin for RequireJS. Here are some examples:
Backbone Testing with JSTestDriver and RequireJS
How to setup RequireJS + Jasmine + JSTestDriver
JSTestDriver + QUnit + RequireJS
Jasmine + RequireJS + JSTD Scaffold

Categories

Resources