Squire fails to load dependecy
rikkertkoppes opened this issue · 4 comments
Working with karma, jasmine and requirejs. My test-main in karma is defined as follows:
var tests = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (/Spec\.js$/.test(file)) {
tests.push(file);
}
}
}
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base/src/js',
paths: {
'squire': '/base/node_modules/squirejs/src/Squire'
},
// ask Require.js to load these files (all our tests)
deps: tests,
// start test run, once Require.js is done
callback: window.__karma__.start
});
Which is pretty normal as I understand. It loads a single test file:
define(['squire'],function(Squire) {
var injector = new Squire();
// describe('test',function() {
// it('should pass',function() {
// expect(true).toBe(true);
// });
// });
//
console.log(injector);
injector.require(['services/fs-nw'],function(fs) {
console.log('fs');
describe('test',function() {
it('should pass',function() {
expect(true).toBe(true);
});
});
},function() {
console.log('fail');
});
});
And it doen't run any test, somehow, the factory function is not executed, nor is the error callback. Without squire, like so:
define(['services/fs-nw'],function(fs) {
console.log('fs');
describe('test',function() {
it('should pass',function() {
expect(true).toBe(true);
});
});
});
it works like a charm. Any ideas?
Karma will have finished running your test and reported back before Squire had a chance to run the callback you provided to injector.require.
So you need to find a way to pause Karma whilst SquireJS pulls in your dependencies. Jasmine.async is a tool they suggest in the readme:
Thanks a million! I never realized that karma was already home before I could tag it at first base.
This is how I resolved it:
I amended the require
method of squire to return a promise in injector.js
:
define(['squire','q'],function(Squire,Q) {
var r = Squire.prototype.require;
Squire.prototype.require = function(deps,cb,eb) {
var def = Q.defer();
r.call(this,deps,function() {
var res = cb.apply(this,arguments);
def.resolve(res);
},function() {
var res = eb.apply(this,arguments);
def.resolve(res);
});
return def.promise;
};
return Squire;
});
Next I made sure all tests returned that promise in their factory:
define(['injector'],function(Injector) {
var injector = new Injector();
return injector.require(['services/fs-nw'],function(fs) {
describe('test',function() {
it('should pass',function() {
expect(true).toBe(true);
});
});
});
});
And finally, I wait for all test to resolve their promise before firing of Karma (in test-main.js
):
require(['q'],function(Q) {
require(tests,function(resolvedTests) {
Q.all(arguments).then(function() {
window.__karma__.start();
});
});
});
I am facing similar issue with using karma and qunit tests which use squire, although running karma in continuous integration mode seems to run the tests successfully, but my use case doesnot allow me to run in continuous integration mode . Also just wanted to know if the solution posted by rikkertkoppes will be pulled into Squire, as it seems promising.
Another easy work around is to invoke your require calls in accordance with your given frameworks async mechanism... E.G. Mocha
it('should create a new finder', function(done) {
injector.require(['bits/ui/Finder'], function(Finder2) {
expect(new Finder2({delegate: delegate})).to.be.an('object');
done();
});
});