npm + Mocha + RequireJS - node.js

I'm having quite the time trying to set up node/npm with Mocha and RequireJS. Here's what I've done.
I've created a testing/ directory, with this structure:
testing/
|
+-- package.json
|
+-- README.md
|
+-- test/
|
+-- mocha.opts
|
+-- widgets/
|
+--mywidget/
|
+-- test.js
Here is what each relevant file contains:
package.json:
{
"name":"testing-project",
"version":"2.5.0",
"description":"Testing Project",
"keywords":["test"],
"engines": { "node": ">= 0.7.0 < 0.11.0" },
"scripts" : {
"test": "./node_modules/.bin/mocha"
},
"devDependencies": {
"mocha": ">= 1.18.2",
"requirejs": ">= 2.1.11",
"should": ">= 3.2.0",
"expect.js": ">= 0.3.1"
}
}
test/mocha.opts:
--require expect.js
--require should
--require requirejs
--require mocha
--reporter spec
--ui tdd
--recursive
--growl
test/widgets/mywidget/test.js
'use strict';
var requirejs = require('requirejs');
// Also tried with: require('../../../r.js') which I downloaded from RequireJS' site
requirejs.config({
baseUrl: '../../../../',
nodeRequire: require
});
console.log('before require');
requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){
console.log('after require');
var expect = require('expect.js');
// Instead of the above "requirejs['mywidget..." line, I've also tried:
// var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js'); AND:
// var myObj = requirejs('../../../../mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function(){
describe('my-widget#getInfo', function(){
it('should pass this test', function(done){
expect( myObj.returnString('test') ).to.equal( 'test' );
done();
})
})
});
});
console.log('done');
It will output the console lines "before require" and "done", but as long as I have the requirejs(['mywidget... line in, it will not hit the after require. If I remove the requirejs line (and the corresponding closing brace/paren line), and instead use the direct "var myObj =" line, I get "cannot find module", and if I use the second "var myObj" line, I get "Reference Error: define is not defined".
I'm trying to package this all, for convenience for other developers, with npm, such that I'm running the command "npm test" from within the top "testing/" directory.
I've been scouring for answers and trying so many things, but I can't seem to require a file using RequireJS and have "define()" defined. I can execute tests, that's not a problem... it's just trying to insert RequireJS into the mix that is when I start having the issues.
Any help would be tremendous!
Thank you!

There are multiple problems going on in what you are showing us. You are incorrectly using both RequireJS and Mocha.
RequireJS
I am pretty sure your baseUrl is incorrect. You seem to think that Mocha's current working directory will be set to test/widgets/mywidget/ when it executes the tests in test/widgets/mywidget/test.js. That's not the case. The working directory is wherever you happen to be when you run npm test. According to your description you are in testing/ when you run it. It is not clear to me what value your baseUrl should be because you do not provide enough information in your question but I trust that from the explanation I just gave you can figure it out.
Now you may think "surely, my baseUrl is correct because when I execute requirejs(['mywidget/trunk/src/mywidgetfile.js'], function(myObj){ I don't get an error". This would be an incorrect inference. While this requirejs invocation schedules the loading of your module, RequireJS does not get the opportunity to try loading it because Mocha exits before RequireJS tries to load it. You can check this by replacing your module path with complete garbage and you won't get an error.
Once you fix this baseUrl issue, using var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js') will work as you expect. So you'll be able to avoid using the asynchronous form of require (this is the form that uses an array of dependencies as the first argument). (The requirejs function you use is just an alias for the function normally called require in RequireJS' documentation.)
Mocha
Your tests are not running because Mocha does not see them. The way Mocha works is by reading all of the test files it finds and then executing them. The callbacks to each describe calls are executed right away, and the callbacks to each it calls are recorded as tests to be run. Once Mocha is done figuring out what tests exist, it runs them.
What happens with your test file is that Mocha executes it, as usual. However, there is no call to describe or it in the top scope of your test file. There are calls in your callback to requirejs but remember what I said above: RequireJS does not get the opportunity to load the module so it does not get the opportunity to run the callback. (And even if it did run it, it would be too late.) So Mocha does not see any tests and exits right away.
The Way Forward
Figure out the baseUrl you need, and then this should work:
'use strict';
var requirejs = require('requirejs');
requirejs.config({
baseUrl: <whatever value is needed here>,
nodeRequire: require
});
var myObj = requirejs('mywidget/trunk/src/mywidgetfile.js');
describe('My Widget', function() {
// etc...
You might also consider dropping RequireJS entirely from your test suite. I've written a library that works just as well in Node as in the browser. It is composed of AMD modules and is loaded by RequireJS in the browser, but I don't use RequireJS in the test suite. This is the loader I use to load my modules in Node. There's also amdefine which I've not used but should give similar capabilities.

Related

Mocha - Running test ReferenceError: regeneratorRuntime is not defined

I am trying to run tests with async/await using mocha. The project architecture was setup before I started working on it and I have been trying to update it's node version to 8.9.4. The project is an isomorphic application and uses babel, gulp and webpack to run.
To run the tests we run a gulp task. There are two .bablerc files in the project. One in the root folder of the project and another in the test fodler.
Both have the same configuration:
{
"presets": [
["env", {"exclude": ["transform-regenerator"]}],
"react",
"stage-1"
],
"plugins": [
"babel-plugin-root-import"
]
}
When I run the app locally there is no error returned anymore. However when I run the tests with gulp test:api I constantly get the error: ReferenceError: regeneratorRuntime is not defined
This is my gulp file in the test folder:
var gulp = require('gulp')
var gutil = require('gulp-util')
var gulpLoadPlugins = require('gulp-load-plugins')
var plugins = gulpLoadPlugins()
var babel = require('gulp-babel')
require('babel-register')({
presets:["es2015", "react", "stage-1"]
});
// This is a cheap way of getting 'test:browser' to run fully before 'test:api' kicks in.
gulp.task('test', ['test:browser'], function(){
return gulp.start('test:api')
});
gulp.task('test:api', function () {
global.env = 'test'
gulp.src(['test/unit-tests/server/**/*.spec.js'], {read: false})
.pipe(plugins.mocha({reporter: 'spec'}))
.once('error', function (error) {
console.log(error)
process.exit(1);
})
.once('end', function () {
process.exit(0);
})
});
gulp.task('default', ['test']);
Any help on why this is happening wouldd be much appreciated.
Node version 8 already has support for async/await so you do not need Babel to transform it; indeed, your root .babelrc includes this preset to exclude the regenerator that would transform async/await (and introduce a dependency on regeneratorRuntime):
["env", {"exclude": ["transform-regenerator"]}]
However, in your test file, the configuration does not specify this preset. Instead, it specifies the preset "es2015", which does include the unwanted transform-regenerator (as you can see at https://babeljs.io/docs/plugins/preset-es2015/). If you change this to match the presets in the root .babelrc, you'll get more consistent results.
Strangely i ran into this issue after i upgraded to Node v8.10.0 from v8.6.x . I had used babel-require like so in my test-setup.js
require('babel-register')();
and the testing tools are Mocha,chai,enzyme + JSDOM . I was getting the same issue when i was making a async call to a API, also while using generator functions via sagas. Adding babel-polyfill seemed to have solved the issue.
require('babel-register')();
require('babel-polyfill');
i guess even babel docs themselves advocate using polyfill for generators and such
Polyfill not included
You must include a polyfill separately when using features that require it, like generators.
Ran into the same issue when running mocha tests from within Visual Studio Code.
The solution was to add the necessary babel plugins in the Visual Studio Code settings.json :
"mocha.requires": [
"babel-register",
"babel-polyfill"
],
I've run into this error before myself when using async/await, mocha, nyc, and when attempting to run coverage. There's never an issue when leveraging mocha for running tests, just with mocha tests while leveraging nyc for running coverage.
11) Filesystem:removeDirectory
Filesystem.removeDirectory()
Should delete the directory "./tmp".:
ReferenceError: regeneratorRuntime is not defined
at Context.<anonymous> (build/tests/filesystem.js:153:67)
at processImmediate (internal/timers.js:461:21)
You can fix the issue a couple of different ways.
Method 1 - NPM's package.json:
...
"nyc": {
"require": [
"#babel/register",
"#babel/polyfill"
],
...
},
...
It really depends which polyfill package you're using. It's recommended to use the scoped (#babel) variant: #babel/pollyfill. However, if you're using babel-polyfill then ensure that's what you reference.
Method 2 - Direct Import
your-test-file.js (es6/7):
...
import '#babel/polyfill';
...
OR
your-test-file.js (CommonJS):
...
require("#babel/polyfill");
...
Don't assign it to a variable, just import or require the package. Again, using the package name for the variant you've sourced. It includes the polyfill and resolves the error.
HTH

How can you correctly require a module in mocha.opts?

I'm using mocha-mongoose to automatically clear mongo in between tests. In the documentation it says to require the module in your spec file or globally in your spec helper.
Doing it per spec works great, but I want to do it from mocha.opts to keep my code DRY.
Requiring it with mocha.opts doesn't work. Mongo is not cleared in between specs
mocha.opts:
--require ./test/common.js
--reporter spec
--ui bdd
--recursive
--colors
--timeout 60000
--slow 300
common.js:
require('mocha-mongoose')('mongodb://your-mongodb-url-here');
Requiring it in each spec file works
test.js
var should = require('chai').should()
, require('mocha-mongoose')('mongodb://your-mongodb-url-here');
describe("Example test", function() {
it(' Mongo will be automatically clear all collections',);
});
How can I correctly require mocha-mongoose in mocha.opts so I don't have to repeat it in every test?
The way it works is by checking for beforeEach and registering itself as a beforeEach hook. Here is the relevant source:
if (!options.noClear && !beforeEachRegistered) {
if ('function' == typeof beforeEach && beforeEach.length > 0) {
// we're in a test suite that hopefully supports async operations
beforeEach(clearDB);
beforeEachRegistered = true;
}
}
The problem is that beforeEach is not available to modules loaded by --require. So you cannot do it with --require.
The only thing I can imagine the author of mocha-mongoose to mean with "your spec helper" would be a module that contains a bunch of utility functions that each spec requires: instead of adding require('mocha-mongoose')(...); to each spec, you'd add it just once to the module that is required by each spec.

using require() in karma tests

I'm using Karma 0.12.28, Karma-Requirejs 0.2.2 (and Karam-jasmine) to run tests.
Config is almost identical to one from docs (test files in requirejs deps and window.__ karma __.start as callback).
Everything works just fine for basic tests. The problem starts when I use require() instead of define() or try to change context. Basically something like this:
var ctx = require.config({
context: 'my-context'
});
ctx(['dep1'], function(){
//....
});
The problem is dep1 fails to load. In DevTools I can see <script/> is created and I can see request in network tab with proper URL but status is canceled. I can open this URL using context menu so I'm sure it is correct but the question remains - why can't I use require() in karma tests?

Wiring up gulp to run mocha tests written in coffeescript

Stitching together things off of websites I tried this
var gulp = require('gulp');
var gutil = require('gulp-util');
var coffee = require('gulp-coffee');
var mocha = require('gulp-mocha');
gulp.task('test', function() {
return gulp.src(['tests/*.coffee'], { read: false })
.pipe(coffee({bare: true}).on('error', gutil.log))
.pipe(mocha({
reporter: 'spec',
globals: {
should: require('should')
}
}));
});
This always gives me an error on the first line of my tests/test.coffee file
require 'should'
describe "something", ->
it "fails", -> true.should.equal false
This error:
(function (exports, require, module, __filename, __dirname) { require 'should'
^^^^^^^^
In addition it doesn't seem right to do this in one task. Each one feels like it should be a task that depends on the output of the previous.
How do I make all these pieces come together?
I have almost identical gulp config as yours, what I did to fix it was:
npm install --save-dev should
The --save-dev part is optional, but I like to store my dependancies into package.json file for easier portability.
Edit:
I have noticed that you're first piping it to coffee. You don't need to use this if using Gulpfile.coffee (you guessed it, Gulpfile written in CoffeeScript), mocha will run it fine as CoffeeScript file.
This is my test task in Gulpfile.coffee:
gulp.task 'test', - >
gulp.src(testSources,
read: false
)
.pipe(mocha(
reporter: 'spec'
globals:
should: require('should')
))
To get Gulp to parse Gulpfile.coffee, save this as Gulpfile.js
require('coffee-script/register');
require('./Gulpfile.coffee');
Edit 2:
I have noticed that the JavaScript version isn't working as expected.
My only suggestion is to use Gulpfile written in CoffeeScript, that way it works fine. I could share mine to speed it up for you, but it takes less than 5 minutes to convert it to CoffeeScript manually, or even faster using Js2coffee.
Or look at this Gulpfile.js (not my work).
Or use Chai and use following code:
chai = require 'chai'
chai.should() # add should to Object.prototype
describe "Test", ->
it "should pass", ->
true.should.equal true
All you need to do to run coffeescript specs is npm install coffee-script.
No need to have a gulpfile in coffeescript.
If you have coffeesctipt installed it's enough to have test task like this in your gulpfile:
gulp.task('test', function(){
return gulp.src('./specs/**/*.spec.coffee')
.pipe(mocha({reporter:'nyan'}));
});
So, no need to pipe *.coffee files through gulp-mocha

How to run jasmine-node tests with RequireJS

How can I properly run jasmine tests using jasmine-node and RequireJS?
I already tried something like this, but doesnt work (CoffeeScript):
requirejs = require 'requirejs'
requirejs.config { baseUrl: __dirname + '/../' }
requirejs ['MyClasses', 'FooClass'], (MyClasses, FooClass) ->
describe "someProp", ->
it "should be true", ->
expect(MyClasses.FooClass.someProp).toEqual true
Finished in 0 seconds 0 tests, 0 assertions, 0 failures
My goal is to write modular classes using RequireJS, CoffeeScript and classes must be testable with jasmine-node (CI server).
How can I do that please?
Thank you!
EDIT:
I executing tests with command (at directory with tests):
jasmine-node ./
Jonathan Tran is right, it's the spec in the file name for me.
I have this:
"scripts": {
"install": "cake install",
"test": "node_modules/jasmine-node/bin/jasmine-node --verbose --coffee --runWithRequireJs --captureExceptions spec"
},
in my package.json and I installed jasmine-node from inside the project npm install jasmine-node
Minimal test file called RingBuffer.spec.coffee
require ["disrasher"], (mod) ->
describe "A test", ->
it "should fail", ->
expect(1).toEqual 0
It doesn't actually work at the moment because I haven't got the project hooked up with require properly I don't think. I'll post back here when it does.
If anyone is running into this, much has changed since this question was asked. The first thing to check is still that you're naming your files like thing.spec.coffee.
But if you're running the tests and still seeing the output "0 tests", you need to make a JavaScript file with your requirejs config. This must be JavaScript, not CoffeeScript.
// requirejs-setup.js
requirejs = require('requirejs');
requirejs.config({ baseUrl: __dirname + '/../' });
Then tell jasmine to use this setup file:
jasmine-node --coffee --requireJsSetup requirejs-setup.js ./
One nice thing about this is that you don't need to include the requirejs config in every spec file.
I've tested this on node v12.16, jasmine-node v3.0.0, and requirejs v2.3.6.
It seems that jasmine-node and require.js are completely incompatible. That said, it is possible to run jasmine tests on require.js modules in node using a bit of extra code. Take a look at https://github.com/geddski/amd-testing to see how.

Resources