How to use inside spec-grunt + karma + jasmine in node

Question with undefined version:

  • How can I use require inside spec with grunt?

Context:

I am working on an existing node project that has no tests yet, so I read some and realized that I am using karma and jasmine.

I read several tutons (including them):

So, I'm trying to run my specs with a grunt and get this error:

X encountered a ReferenceError declaration exception: Cannot find variable: require in file: /// (...) -spec.js (line 2) (1)

The line looks something like this:

var myHelper = require(...); 

But if I use the node-jasmine test through the terminal, it works like a charm ...

My project structure:

  • Controllers /
  • helpers /
  • models /
  • node_modules /
  • resources /
  • test /
  • test / specifications /
  • view /
  • app.js
  • Gruntfile.js
  • package.json

In my specification (inside test / spec /) I use require ("../../helpers/helper.js") and this is normal for node-jasmine, but not with grunt.

node-jasmine test:

.....

Finished in 0.015 seconds 5 tests, 5 statements, 0 failures, 0 skipped

grunt:

Accomplishment of the task "Jasmine: key" (jasmine). Testing Jasmine Specifications Through PhantomJS

ReferenceError: Cannot find variable: require at app.js: 1 X Support Tester detected an exception due to declaration ReferenceError: Cannot find variable: require in file: /// (...) / test / spec / serviceHelper- spec.js (line 2) (1)

1 spec at 0.005s.

1 failures Warning: The Jasmine: Key task failed. Use -force to continue.

Interrupted due to warnings.

I have all the packages installed in node_modules (nothing in the dependencies in package.json), and my Gruntfile.js:

 '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 sources property. * This is needed because karma (coverage) stores its results in a * directory whose name uses the browser 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.

+5
source share
1 answer

how

It depends:

  • If you have application code that needs to be tested against a browser (for example, Angular , Backbone , etc.) - use Karma and do not use require . Then just make sure your helpers.js file helpers.js loaded before the tests themselves.

     // @file Gruntfile.js // https://github.com/karma-runner/grunt-karma grunt.initConfig({ karma: { client: { options: { files: ['client/*.js', 'helpers/*.js', 'test/*.js'] } } } }); // @file helpers.js (function () { window.helpers = { foo: function () { return 'bar'; } }; })(); // @file spec.js (function (helpers) { it('does the thing', function () { expect(helpers.foo()).toBe('bar'); }); })(window.helpers); 
  • If you do not need to run tests against the browser (i.e. you are strictly checking NodeJS code), you can simplify the setup by removing Karma and strictly using Jasmine :

     // @file Gruntfile.js // https://github.com/gruntjs/grunt-contrib-jasmine grunt.initConfig({ jasmine: { server: { src: 'server/*.js', options: { specs: 'test/*.js', helpers: 'helpers/*.js' } } } }); // @file helpers.js (function () { module.exports = { foo: function () { return 'bar'; } }; })(); // @file spec.js (function () { var helpers = require('helpers'); // require is available it('does the thing', function () { expect(helpers.foo()).toBe('bar'); }); })(); 

Why

require does not exist because you use Karma to run your tests. Karma simply downloads the files in the browser of your choice and executes them in the order specified in karma.conf.js . It internally uses the test framework you provided (in this case Jasmine ) to run tests against the browser (s) you provide (in this case PhantomJS ).

As with all JavaScript, the context of a variable is determined by the closure in which it is contained.

  • The Jasmine binary expression internally uses NodeJS , which emulates CommonJS require , which makes the require function available to you in the context of your node application.

  • Karma runner does what is equivalent to writing <script src="[path]"> tags in a browser, which then each uploads the corresponding file to PhantomJS . As a result, your javascript context is global, and your files only have access to the global context. In the browser, the global context is defined by everything associated with the window object, and window.require does not exist essentially.

+4
source

All Articles