Squire.js
Your friendly dependency injector for testing Require.js modules.
I want to write JS tests. The production code is written with RequireJS.
I found a test lib named Squire.js: https://github.com/iammerrick/Squire.js/
From the Squire.js website
Run generates a function that will receive a done callback and execute it after your test function is complete. Particularly useful for frameworks where asynchrony is handled with a callback. Here is an example with Mocha.js. Jasmine can offer this callback approach using Jasmin.Async."
I don't know how to use this with Jasmine async. A small example would be very useful.
Source: (StackOverflow)
I'm looking to use squire.js with karma and want to do a squire.clean() to clean away all the mocks before the next test suite (I'm using jasmine) is run but I cannot see a way to configure karma to run something before (or after) a test suite.
Is there a way?
Source: (StackOverflow)
I'm trying out Squire.js as a dependency loader for RequireJS. Using a totally normal web browser for running unit tests. I want to use store
to get a handle to my mocks. But can't stop Squire loading the actual module.
mock
works fine:
define(['lib/squire'], function (squire) {
var injector = new squire();
injector
.mock('modules/dependency', {
run: function () {
console.log("fake dependency run");
}
})
.require(['modules/module-under-test'], function (module) {
module.run();
});
});
Console output
module under test loaded module-under-test.js:2
module under test run module-under-test.js:5
fake module run module-test.js:8
But when I use store
like this:
define(['lib/squire'], function (squire) {
var injector = new squire();
injector
.store('modules/dependency')
.require(['modules/module-under-test', 'mocks'], function (module, mocks) {
mocks.store["modules/dependency"] = {
run: function () {
console.log("fake dependency run");
}
};
module.run();
});
});
The real one is used and run:
real dependency loaded dependency.js:2
module under test loaded module-under-test.js:2
module under test run module-under-test.js:5
real dependency run dependency.js:5
Squire says on the front page of the docs that this is ok to do. Using latest version of Squire.js from Github, and also latest RequireJS from requirejs.org. What am I doing wrong?
Source: (StackOverflow)
I am attempting to run some Jasmine unit tests for a Backbone view, mocking out dependencies in Squire.
The dependencies of my view are a Baseview
, an ICanHaz template and an i18n translation.
I mock out the dependencies after defining Squire and Backbone, and then use a Squire injector to require my view. However, when I run the tests through Grunt, I get the warning message:
Warning: No specs executed, is there a configuration error? Use --force to continue.
Here is my spec:
define(['squire', 'backbone'], function (Squire, Backbone) {
var injector = new Squire();
mocks = {
'views/baseview': function () {
return Backbone.View.extend({
grabTemplate: function (options) { }
});
},
'text!templates/menu.htm': '',
'i18n!nls/menu': {}
};
injector.mock(mocks);
injector.require(['menu'], function (Menu) {
describe('Menu View', function () {
it('should be initialisable', function () {
var menu = new Menu();
expect(menu).toBeDefined();
});
});
});
});
Does anyone know why my basic unit test is not getting picked up?
Source: (StackOverflow)
We're using Karma and Mocha along with Squire for mocking dependencies loaded with RequireJs. Without Squire, our tests run fine however as soon as we initialize a Squire object, everything start breaking:
define(['squire'], function (Squire) {
var injector = new Squire(); // comment this out and everything works again
});
We found that sometimes Karma reported that no tests were run (even though breakpoints set inside test functions would be hit) and sometimes it would report random errors that shouldn't have been failing. Karma just goes a bit crazy.
How do I use Squire without my tests going crazy?
Source: (StackOverflow)
I am using SquireJS and Mocha to test some code that uses Backbone and Backbone-relational. I am getting the following error when trying to mock an object that contains a Backbone.RelationalModel
constructor:
TypeError: this.set is not a function
at Backbone.Model (path/to/backbone.js:256:10)
Here is a simplified example of my source code(source.js):
define([ './myObjDependency'], function(myObj){
return Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'myModel',
relatedModel: myObj.Model
}
]
});
});
Then in my tests, I have this:
require(['Squire'], function(Squire) {
var injector = new Squire();
squire = injector
.mock("./myObjDependency", {
Model: Backbone.RelationalModel.extend({})
});
squire.require(['./source'], function (src) {
var srcModelInstance = new src();
// ... more code here ... //
});
});
It seems like the Backbone.RelationalModel
is calling its parent constructor (Backbone.Model
), and is somehow giving it the incorrect this
context.
Here is the full stack-trace in case it is helpful:
TypeError: this.set is not a function
at Backbone.Model (/path/to/_bower/components/backbone.js:256:10)
at Backbone.RelationalModel.Backbone.Model.extend.constructor (/path/to/_bower/components/backbone-relational.js:1225:20)
at child [as relatedModel] (/path/to/_bower/components/backbone.js:1566:41)
at Function._.result (/path/to/_bower/components/underscore.js:1168:40)
at Backbone.Relation (/path/to/_bower/components/backbone-relational.js:604:26)
at new child (/path/to/_bower/components/backbone.js:1566:41)
at _.extend.initializeRelation (/path/to/_bower/components/backbone-relational.js:185:15)
at null.<anonymous> (/path/to/_bower/components/backbone-relational.js:1305:31)
at Array.forEach (native)
at Function._.each._.forEach (/path/to/_bower/components/underscore.js:79:11)
Does anyone have any ideas on how to fix this or what the root cause of the problem is? Thanks.
Source: (StackOverflow)
The code I'm trying to test relies on RequireJs loader plugins. Example with requirejs/text:
require(['text!templates/foo'], function (data) {
// handle loaded data
});
For a specific unit test, I'm trying to mock the response for text!templates/foo
and override with one relevant for the test:
it('should load a template', function (done) {
// TODO: mock 'text!templates/foo' here to return 'mock_data'
// templateViewer uses the text plugin internally to do the actual loading
templateViewer.templateFor('foo', function (error, templateData) {
expect(templateData).toEqual('mock_data');
done();
});
});
I've looked at RequireJs dependency mock solutions, especially Squire.js but it seems they are all suited for mocking regular dependencies and not plugin responses.
I've also looked at stub libraries like sinon to maybe replace the actual require
call but that seems problematic.
What's the recommended practice? I prefer not to replace the entire text
plugin with a mock one in my requirejs configuration, just override some of its responses in specific tests.
My setup is node+mocha+requirejs
Edit
Please see this example fiddle project to see my issue with Squire:
http://runnable.com/VUBoI0ex6v9Gs-BJ/squirejs-with-plugins-for-node-js-and-hello-world
Source: (StackOverflow)
I am trying to use RequireJS in node, and found difficulties with path issues.
Here is a simple foo method that returns "foo"
$ cat src/foo.js
define([], function() {
var foo = function() {
return "foo";
};
return { foo:foo};
});
Here is bar that requires foo, but it works only when specifying relative path. Is that how it's supposed to be?
$ cat src/bar.js
define(['./foo.js'], function(foo) {
var bar = function() {
return foo.foo().replace("foo","bar");
};
return { bar : bar };
});
Things get much trickier in the mocha test:
- Loading foo and bar requires __dirname workarounds.
- The async loading of bar fails (see test 3 and 4).
- Importing Squire needs exact path, since it is installed using npm install, but does not conform to the standard node require syntax and does not include the amdefine workaround:
Here is the test code:
$ cat test/footests.js
var requirejs = require('requirejs');
var chai = requirejs("chai");
var should = chai.should();
var Squire = requirejs(__dirname + "/../node_modules/squirejs/src/Squire.js");
describe('when calling foo.foo()', function () {
it('should return "foo"', function() {
var foo = requirejs(__dirname + "/../src/foo.js");
foo.foo().should.equal("foo");
});
});
describe('when calling bar.bar()', function () {
var bar = requirejs(__dirname + "/../src/bar.js");
it('should return "bar"', function() {
bar.bar().should.equal("bar");
});
});
describe('when calling bar.bar() with async requirejs', function () {
it('should return "bar"', function(done) {
requirejs(__dirname + "/../src/bar.js", function(bar) {
bar.bar().should.equal("bar");
done();
})
});
});
describe('when mocking foo.foo() and calling bar.bar()', function () {
it('should return "barbar"', function(done) {
var injector = new Squire();
var fooMock = {
foo : function() {
return "foofoo"; /* instead of just foo */
}
};
injector
.mock('./foo.js', fooMock)
.require(__dirname + "/../src/bar.js", function(bar) {
bar.bar().should.equal("barbar");
done();
});
});
});
I've setup a reproduction on github https://github.com/itaifrenkel/node-requirejs-example
Source: (StackOverflow)
Code:
...
if (this.getCurrentRoute() === '') {
require(['modules/project/project.module', 'modules/topic/topic.module'], function() {
TopicEditor.navigate('project/new/books/' + bookIds + '/template/' + TopicEditor.config.library.bookTemplateId + '/', {
trigger: true
});
});
}
...
This code is part of the file being tested.
When I run the tests, I get a bunch of 404 errors related to the dependencies of the above modules despite being mocked via injector.mock
. I think it has something to do with the asynchronous nature of requirejs
. From what I can tell, the require statements are being executed outside of squirejs's context, which means the modules are loading normally.
Has anyone else ever ran into this kind of testing scenario?
Source: (StackOverflow)
I'm using requirejs with inline requires, for instance:
define(['someDep'], function(someDep) {
return {
someFn: function() {
require(['anotherDep'], function(anotherDep) {
anotherDep.anotherFn();
});
}
}
});
In my particular case, I cannot include anotherDep
in the define.
When testing with mocha, I have a test case like this:
define(['squire'], function(Squire) {
var squire = new Squire();
describe('testcase', function() {
it('should mock anotherDep', function(done) {
var spy = sinon.spy();
squire.mock('anotherDep', {
anotherFn: spy
});
squire.require(['someDep'], function(someDep) {
someDep.someFn();
expect(spy).to.have.been.calledOnce;
done();
});
});
});
});
fails because anotherDep
calls require
directly and not squire.require
. The work-around is to replace require
in the global scope,
var originalRequire;
before(function() {
originalRequire = require;
require = _.bind(squire.require, squire);
});
after(function() {
require = originalRequire;
});
This works (note that squire.require
must be bound to the squire
object in some way, I'm using underscore to do this) except that the spy will still not be called because of timing. The test also has to change to
it('should mock anotherDep', function(done) {
squire.mock('anotherDep', {
anotherFn: function() {
done();
}
});
squire.require(['someDep'], function(someDep) {
someDep.someFn();
});
});
Is there a better way? If not, hope this provides a solution for others running into the same problem.
Source: (StackOverflow)
I'm using Karma, Jasmine, Jasmine.Async, Sinon and Chai.
The good news...this test works correctly. The dependency is mocked, spies get called, and intentionally breaking the test subject results in failed tests.
define(['chai', 'squire'], function (chai, Squire) {
var should = chai.should(),
async = new AsyncSpec(this),
subject, injector = new Squire();
describe('EventsView', function () {
describe('when an event is clicked', function () {
var mockModel, stub;
async.beforeEach(function (done) {
setFixtures('<div id="screen"></div>');
mockModel = {
toJSON: function () {
return {
dimensions: "hu1 vu2",
events: [{
date: "8/29/2013",
id: "8923",
title: "Fancy Show",
venue: "Lovely venue",
}, {
date: "8/29/2013",
id: "9034",
title: "Exciting Game",
venue: "Lovely stadium"
}],
id: 3566,
kind: "events",
title: "Top events this week"
};
},
fetch: function () {}
};
stub = sinon.stub();
injector.mock('tiles/events-tile/events-detail-model', Squire.Helpers.constructs({
fetch: stub
}));
injector.require(["tiles/events-tile/events-view"], function (ev) {
subject = new ev(mockModel);
done();
});
});
async.afterEach(function (done) {
injector.clean();
injector.remove();
done();
});
async.it('should attempt to fetch the event details', function (done) {
$('#screen').html(subject.$el);
$('.event').first().click();
stub.called.should.be.true;
done();
});
});
});
});
The bad news...a shed load of other tests that were previously fine are now failing for weird reasons. For example:
Error: Backbone.history has already been started
and
TypeError: 'undefined' is not an object (evaluating 'Backbone.Validation.mixin')
If I comment out the snippet
injector.require(["tiles/events-tile/events-view"], function (ev) {
subject = new ev(mockModel);
done();
});
Then the other tests work again. I've had stuff like this happen before and it has usually been down to a sinon mock not getting restored. The injector.clean()
call doesn't seem to be providing the magic bullet I was hoping for.
Source: (StackOverflow)