[ACCEPTED]-Why do I see "define not defined" when running a Mocha test with RequireJS?-mocha.js

Accepted answer
Score: 18

The reason your test isn't running is because 17 src/utils.js is not a valid Node.js library.

According 16 to the RequireJS documentation, in order 15 to co-exist with Node.js and the CommonJS 14 require standard, you need to add a bit of boilerplate to the top 13 of your src/utils.js file so RequireJS's define function is 12 loaded.

However, since RequireJS was designed 11 to be able to require "classic" web 10 browser-oriented source code, I tend to 9 use the following pattern with my Node.js 8 libraries that I also want running in the 7 browser:

if(typeof require != 'undefined') {
    // Require server-side-specific modules
}

// Insert code here

if(typeof module != 'undefined') {
    module.exports = whateverImExporting;
}

This has the advantage of not requiring 6 an extra library for other Node.js users 5 and generally works well with RequireJS 4 on the client.

Once you get your code running 3 in Node.js, you can start testing. I personally 2 still prefer expresso over mocha, even though 1 its the successor test framework.

Score: 5

The Mocha documentation is lacking on how 9 to set this stuff up, and it's perplexing 8 to figure out because of all the magic tricks 7 it does under the hood.

I found the keys 6 to getting browser files using require.js to work 5 in Mocha under Node: Mocha has to have the 4 files added to its suites with addFile:

mocha.addFile('lib/tests/Main_spec_node');

And second, use 3 beforeEach with the optional callback to load your 2 modules asynchronously:

describe('Testing "Other"', function(done){
    var Other;
    beforeEach(function(done){
        requirejs(['lib/Other'], function(_File){
            Other = _File;
            done(); // #1 Other Suite will run after this is called
        });
    });

    describe('#1 Other Suite:', function(){
        it('Other.test', function(){
            chai.expect(Other.test).to.equal(true);
        });
    });
});

I created a bootstrap 1 for how to get this all working: https://github.com/clubajax/mocha-bootstrap

Score: 1

You are trying to run JS modules designed 16 for browsers (AMD), but in the backend it 15 might not work (as modules are loaded the 14 commonjs way). Because of this, you will 13 face two issues:

  1. define is not defined
  2. 0 tests run

In the browserdefine will be defined. It 12 will be set when you require something with 11 requirejs. But nodejs loads modules the 10 commonjs way. define in this case is not defined. But 9 it will be defined when we require with 8 requirejs!

This means that now we are requiring 7 code asynchronously, and it brings the second 6 problem, a problem with async execution. https://github.com/mochajs/mocha/issues/362

Here 5 is a full working example. Look that I had 4 to configure requirejs (amd) to load the 3 modules, we are not using require (node/commonjs) to 2 load our modules.

> cat $PROJECT_HOME/test/test.js

var requirejs = require('requirejs');
var path = require('path')
var project_directory = path.resolve(__dirname, '..')

requirejs.config({
  nodeRequire: require, 
  paths: {
    'widget': project_directory + '/src/js/some/widget'
  }
});

describe("Mocha needs one test in order to wait on requirejs tests", function() {
  it('should wait for other tests', function(){
    require('assert').ok(true);
  });
});


requirejs(['widget/viewModel', 'assert'], function(model, assert){

  describe('MyViewModel', function() {
    it("should be 4 when 2", function () {
        assert.equal(model.square(2),4)
    })
  });

})

And for the module that 1 you want to test:

> cat $PROJECT_HOME/src/js/some/widget/viewModel.js

define(["knockout"], function (ko) {

    function VideModel() {
        var self = this;

        self.square = function(n){
            return n*n;
        }

    }

    return new VideModel();
})
Score: 0

Just in case David's answer was not clear enough, I just 4 needed to add this:

if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

To the top of the js 3 file where I use define, as described in RequireJS 2 docs ("Building node modules with AMD or RequireJS") and in the same folder add the amdefine package:

npm install amdefine

This 1 creates the node_modules folder with the amdefine module inside.

More Related questions