Reputation: 11508
I'm building a module that I want to make available both for people that use AMD and for ones that don't. For example, I want to make it work with RequireJS:
require(['Module'], function (Module) {
// do stuff with module
});
But I also want it to work by manually inserting all dependencies (considering they also work without AMD).
How can I test that this behavior is correct?
Upvotes: 1
Views: 674
Reputation: 11508
A working approach I found was to use the module pattern in my script file so that there are no leaked dependencies. Afterwards, I build an internal function that receives my dependencies as parameters and returns the object that represents the module I want to export.
Then, I check if there is a define
function available and if it has the amd
property set on it. If yes, then I register the module with define, otherwise I export it as a global.
Here's a skeleton of the code for this. We'll assume that the module is named Module
and it has two dependencies, dep1
and dep2
:
(function (exports) {
"use strict";
var createModule = function (dep1, dep2) {
var Module;
// initialize the module
return Module;
}
if (typeof define === 'function' && define.amd) {
define(['dep1', 'dep2'], function (dep1, dep2) {
return createModule(dep1, dep2);
});
} else {
exports.Module = createModule(dep1, dep2);
}
})(this);
Regarding the tests, I'm currently using yeoman for it, with mocha
and PhantomJS
. Here's how to make testing work with require. The approach I've taken to test both cases (with and without AMD) is to have two separate html tests. First of all, you need to add the second page in the Gruntfile:
// headless testing through PhantomJS
mocha: {
all: ['http://localhost:3501/index.html', 'http://localhost:3501/no-amd.html']
},
In the first case, there's the normal require-based template:
<script src="lib/mocha/mocha.js"></script>
<!-- assertion framework -->
<script src="lib/chai.js"></script>
<!-- here, main includes all required source dependencies,
including our module under test -->
<script data-main="scripts/main" src="scripts/vendor/require.js"></script>
<script>
mocha.setup({ui: 'bdd', ignoreLeaks: true});
expect = chai.expect;
should = chai.should();
require(['../spec/module.spec'], function () {
setTimeout(function () {
require(['../runner/mocha']);
}, 100);
});
</script>
For testing non-amd, we need to explicitly include the module and all dependencies. After all is present in the page, we include the runner.
<script src="lib/mocha/mocha.js"></script>
<!-- assertion framework -->
<script src="lib/chai.js"></script>
<!-- include source files here... -->
<script src="scripts/vendor/dep1.js"></script>
<script src="scripts/vendor/dep2.js"></script>
<script src="scripts/Module.js"></script>
<script>
mocha.setup({ui: 'bdd', ignoreLeaks: true});
expect = chai.expect;
should = chai.should();
</script>
<script src="spec/romania.spec.js"></script>
<script src="runner/mocha.js"></script>
It doesn't make any sense to have two different specs, but the spec should also work with AMD and without it. The solution is similar to the one we used for the module.
(function () {
"use strict";
var testSuite = function (Module) {
// break the module into pieces :)
};
if (typeof require === 'function') {
require(['Module'], function (Module) {
testSuite(Module);
});
} else {
// if AMD is not available, assume globals
testSuite(Module);
}
})();
If you have different or more elegant ways to do this, please post them as answers here. I'd be happy to accept a better answer. :)
Upvotes: 1