Skip to content

Commit

Permalink
module.mock / module.unmock
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Baumgart committed Aug 21, 2012
1 parent 4fc1683 commit 4ec5db4
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 6 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -97,6 +97,19 @@ myscript.js:
If you execute a bundle with external dependencies without a DOM (e.g. in node.js), the dependencies will be silently ignored. If you execute a bundle with external dependencies without a DOM (e.g. in node.js), the dependencies will be silently ignored.




### Mocking / stubbing modules

In order to make unit testing your modules easier, jsbundle provides a mocking API:

module.mock('some-module-name.js', { my: 'mock module.exports object' });
var someModule = require('../path/to/some-module-name.js');
// test code here
module.unmock('some-module-name.js');

<code>module.mock(moduleIdSubstring, mockExportsObject)</code> takes a string as its first parameter and an arbitrary object as its second parameter. After calling <code>module.mock</code>, all <code>require</code> thereafter will return the mockExportsObject if the required module's ID matches the moduleIdSubstring. Note that if you specified mangleNames: true, the module ID is a somewhat unpredictable mangled numeric name, so it is not recommended to use module.mock with mangleNames turned on.

<code>module.unmock(moduleIdSubstring)</code> disables a previous call to <code>module.mock</code>. The moduleIdSubstring must match the one from the corresponding <code>module.mock</code> call exactly.

### devcdn ### devcdn


[JSBUNDLE_ENV=<env>] devcdn [port] [JSBUNDLE_ENV=<env>] devcdn [port]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -3,7 +3,7 @@
"name": "jsbundle", "name": "jsbundle",
"description": "Simple, clean, and automatic bundling of your Node modules and packages for use in the browser.", "description": "Simple, clean, and automatic bundling of your Node modules and packages for use in the browser.",
"keywords": "browser require bundle module package static-analysis", "keywords": "browser require bundle module package static-analysis",
"version": "0.13.5", "version": "0.14.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/proxv/jsbundle.git" "url": "git://github.com/proxv/jsbundle.git"
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/abc.js
Expand Up @@ -10,6 +10,17 @@ var def = require(
.js' .js'
)(); )();


module.mock('xyz.js', { mock: true });
module.mock('3', { mock: true });
if (!require('./xyz.js').mock) {
throw new Error('mocking failed');
}
module.unmock('xyz.js');
module.unmock('3');
if (require('./xyz.js').mock) {
throw new Error('unmocking failed');
}

if (typeof alert !== 'undefined') { if (typeof alert !== 'undefined') {
alert(def); alert(def);
} else { } else {
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/xyz.js
@@ -0,0 +1,3 @@
module.exports = {
mock: false
};
2 changes: 1 addition & 1 deletion test/test-module.js
Expand Up @@ -16,7 +16,7 @@ vows.describe('test Module').addBatch({
"dependencies / extraDependencies": function(mod) { "dependencies / extraDependencies": function(mod) {
var deps = mod.dependencies().sort(); var deps = mod.dependencies().sort();
var extraDeps = mod.extraDependencies().sort(); var extraDeps = mod.extraDependencies().sort();
assert.equal(deps.length, 3); assert.equal(deps.length, 4);
assert.equal(extraDeps.length, 1); assert.equal(extraDeps.length, 1);
assert.match(deps[0], /def\.js$/); assert.match(deps[0], /def\.js$/);
assert.match(extraDeps[0], /underscore.js$/); assert.match(extraDeps[0], /underscore.js$/);
Expand Down
42 changes: 38 additions & 4 deletions tmpl/bundle.tmpl
Expand Up @@ -3,16 +3,51 @@
var _$_modules = {}; var _$_modules = {};
var _$_mainModuleId = @mainModuleId; var _$_mainModuleId = @mainModuleId;
var _$_moduleMap = @moduleMap; var _$_moduleMap = @moduleMap;
var _$_mockedModules;
var _$_hasOwnProp = Object.prototype.hasOwnProperty;

function _$_mock(idSubstring, mockExports) {
if (!_$_mockedModules) {
_$_mockedModules = {};
}
_$_mockedModules[idSubstring] = mockExports;
}

function _$_unmock(idSubstring) {
if (_$_mockedModules[idSubstring]) {
delete _$_mockedModules[idSubstring];
} else {
throw new Error('Substring "' + idSubstring + '" not registered for module mocking, so cannot unmock.');
}
}

function _$_getModule(id) {
id = String(id);
if (_$_mockedModules) {
for (var idSubstring in _$_mockedModules) {
if (_$_hasOwnProp.call(_$_mockedModules, idSubstring)) {
if (id.indexOf(idSubstring) >= 0) {
return {
exports: _$_mockedModules[idSubstring]
};
}
}
}
}
return _$_modules[id];
}


function _$_require(id) { function _$_require(id) {
var moduleFn = _$_moduleFns[id]; var moduleFn = _$_moduleFns[id];
if (moduleFn) { if (moduleFn) {
var mod = _$_modules[id]; var mod = _$_getModule(id);
if (!mod) { if (!mod) {
mod = _$_modules[id] = { mod = _$_modules[id] = {
id: id, id: id,
exports: {}, exports: {},
bundleUrl: JSBUNDLE_URL bundleUrl: JSBUNDLE_URL,
mock: _$_mock,
unmock: _$_unmock
}; };
if (id === _$_mainModuleId) { if (id === _$_mainModuleId) {
_$_require.main = mod; _$_require.main = mod;
Expand All @@ -21,7 +56,7 @@
} }
return mod.exports; return mod.exports;
} else { } else {
throw new Error("Cannot find module '" + id + "'"); throw new Error("Cannot find module '" + id + "'.");
} }
} }


Expand All @@ -38,7 +73,6 @@
} }


(function() { (function() {
var hasOwnProp = Object.prototype.hasOwnProperty;


function registerScriptLoad(url, index) { function registerScriptLoad(url, index) {
_$_scriptsToLoad[index] = null; _$_scriptsToLoad[index] = null;
Expand Down

0 comments on commit 4ec5db4

Please sign in to comment.