Vague version question:
- How can I use require inside a spec with grunt?
Context:
I'm working on an existent node project that has no tests yet, so I read some and realized to use karma and jasmine.
I read some tutos (including these):
- http://kwilson.me.uk/blog/use-karma-and-grunt-to-run-your-jasmine-tests-in-real-time/
- http://ahexamples.blogspot.com.br/2014/03/example-of-jasmine-karma-sonar-grunt.html
So I'm trying to run my specs with grunt and getting this error:
X encountered a declaration exception ReferenceError: Can't find variable: require in file:///(...)-spec.js (line 2) (1)
The line is something like:
var myHelper = require(...);
But if I use via terminal "node-jasmine test" it works like a charm...
My project structure:
- controllers/
- helpers/
- models/
- node_modules/
- resources/
- test/
- test/spec/
- views/
- app.js
- Gruntfile.js
- package.json
In my spec (inside test/spec/) I use a require('../../helpers/helper.js') and that's ok for node-jasmine, but no with grunt.
node-jasmine test:
.....
Finished in 0.015 seconds 5 tests, 5 assertions, 0 failures, 0 skipped
grunt:
Running "jasmine:pivotal" (jasmine) task Testing jasmine specs via PhantomJS
ReferenceError: Can't find variable: require at app.js:1 Service Helper Tests X encountered a declaration exception ReferenceError: Can't find variable: require in file:///(...)/test/spec/serviceHelper-spec.js (line 2) (1)
1 spec in 0.005s.
1 failures Warning: Task "jasmine:pivotal" failed. Use --force to continue.
Aborted due to warnings.
I have all packages installed into node_modules (nothing in dependencies in package.json) and my Gruntfile.js is:
'use strict';
module.exports = function(grunt) {
var $srcFiles = 'app.js';
var $testFiles = 'test/spec/*-spec.js';
var $outputDir = 'test/target'
var $junitResults = $outputDir + '/junit-test-results.xml';
var $jasmineSpecRunner = $outputDir + '/_SpecRunner.html';
var $coverageOutputDir = $outputDir + '/coverage';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Jasmine test
jasmine: {
pivotal: {
src: $srcFiles,
options: {
specs: $testFiles,
outfile: $jasmineSpecRunner,
keepRunner: 'true' // keep SpecRunner/outfile file
}
}
},
// coverage using Karma
karma: {
continuous: {
singleRun: 'true',
browsers: [ 'PhantomJS' ]
},
options: {
plugins: [
'karma-jasmine',
'karma-phantomjs-launcher',
'karma-junit-reporter',
'karma-coverage'
],
frameworks: [ 'jasmine' ],
files: [ $srcFiles, $testFiles ],
reporters: [ 'junit', 'coverage' ],
junitReporter: {
outputFile: $junitResults
},
preprocessors: {
// source files must be a literal string
'helpers/*.js': [ 'coverage' ]
},
coverageReporter: {
type: 'lcov',
dir: $coverageOutputDir
}
}
},
// export Karma coverage to SonarQube
karma_sonar: {
your_target: {
// properties for SonarQube dashboard
project: {
key: 'net.ahexample:ahexample-jasmine-karma-sonar',
name: 'Jasmine with Karma and SonarQube Example',
version: '0.0.1'
}
// sources property is set at runtime (see below)
}
},
clean: [ $outputDir ]
});
/*
* Task to set karma_sonar's sources property.
* This is needed because karma (coverage) stores its results in a
* directory whose name uses the browser's user agent info
* (name/version and the platform name).
* The latter may well he different to the OS name and so its needs an
* OS to platform translator.
* For example, OS name for Apple Mac OS X is Darwin.
*/
grunt.registerTask('set-karma-sonar-sources-property', function() {
var $done = this.async();
var $phantomjs = require('karma-phantomjs-launcher/node_modules/phantomjs');
var $spawn = require('child_process').spawn;
var $phantomUserAgent = $spawn($phantomjs.path,
// phantomjs script to print user agent string
[ 'lib/phantomjs-useragent.js' ]
);
/*
* Construct coverage LCOV file path from PhantomJS'
* user agent string, then use it to set karma_sonar's
* sources property.
*/
$phantomUserAgent.stdout.on('data', function(msg) {
var $useragent = require('karma/node_modules/useragent');
var $agent = $useragent.parse(msg);
// An example of dirName is 'PhantomJS 1.9.7 (Mac OS X)'
var $dirName = $agent.toAgent() + ' (' + $agent.os + ')';
var $coverageResults = $coverageOutputDir + '/' + $dirName + '/lcov.info';
var $sonarSources = makeSonarSourceDirs($srcFiles, $coverageResults);
var $karmaSonarConfig = 'karma_sonar';
var $ksConfig = grunt.config($karmaSonarConfig);
grunt.log.writeln('coverage LCOV file: ' + $coverageResults);
$ksConfig['your_target']['sources'] = $sonarSources;
grunt.config($karmaSonarConfig, $ksConfig);
});
$phantomUserAgent.on('close', function(exitCode) {
$done();
});
/*
* Create sonar source object for each directory of source file pattern.
*/
function makeSonarSourceDirs($filesPattern, $coverageResults) {
var $path = require('path');
var $dirs = [];
grunt.file.expand(
{
filter: function($filePath) {
$dirs.push({
path: $path.dirname($filePath),
prefix: '.', // path prefix in lcov.info
coverageReport: $coverageResults,
testReport: $junitResults
});
}
},
$filesPattern
);
return $dirs;
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-karma-sonar');
grunt.registerTask('test', [ 'jasmine', 'karma:continuous' ]);
grunt.registerTask('sonar-only', [ 'set-karma-sonar-sources-property', 'karma_sonar' ]);
grunt.registerTask('sonar', [ 'test', 'sonar-only' ]);
grunt.registerTask('default', 'test');
}
Thank you for your attention.