bernie bernie - 2 months ago 24
jQuery Question

Testing javascript code that uses require('jquery') in node

I am developing a node module that uses

jQuery
's
Deferred
s and can't figure out the best way to test it.

The file
src/MyModule.js
looks like this:

var $ = require('jquery');

var MyModule = module.exports = function() {
// constructor
};
// other module methods that use $.Deferred()


Example test code in
test/MyModuleTest.js
:

var test = require('tape');
var MyModule = require('../src/MyModule');

test('promise test', function(t) {
t.plan(1);

var module = new MyModule();
var promise = module.promiseReturningMethod();
promise.done(function() {
t.ok(true);
});
module.resolveThePromise();
});


I would like to simply execute the tests like this:
node test/MyModuleTest.js
.

The code will eventually be passed through Browserify which will shim the
require('jquery')
so it uses the global jQuery object
. My problem is how do I get the
require('jquery')
call from
MyModule.js
to work in the tests?

Running the test code currently gives the error:

TypeError: $.Deferred is not a function


This is because
reqyure('jquery')
requires a window object to actually create the jQuery object. Otherwise, an empty object is returned.

I know I can use the following to make
require('jquery')
work in the test:

var myWindow = require('jsdom').jsdom().defaultView;
var $ = require('jquery')(myWindow);


This could be part of an answer but it's not the answer by itself! The code in
MyModule.js
should not have to hack around its
require('jquery')
call. The test code or infrastructure should somehow take care of this. But how?

Answer

You can intercept the require() call from your test file, using the mock-require package:

// test.js
var mock = require('mock-require');

var myWindow = require('jsdom').jsdom().defaultView;
var $ = require('jquery')(myWindow);

mock('jquery', $);
mock.reRequire('jquery'); // This will prevent requrie() calls to return the
                          // originally cached version of jQuery

// When MyModule will require("jquery"), it will get the one which uses jsdom's window
var MyModule = require("./MyModule.js");