Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions shared/base/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ _.extend(BaseRouter.prototype, Backbone.Events, {
* Adds a single route definition.
*/
route: function(pattern, controller, options) {
var realAction, action, handler, route, routeObj, self = this;
var realAction, action, handler, route, routeObj, routerContext = this;

route = parseRouteDefinitions([controller, options]);
realAction = this.getAction(route);
Expand All @@ -160,27 +160,28 @@ _.extend(BaseRouter.prototype, Backbone.Events, {
action = realAction;
} else {
action = function(params, callback) {
var self = this;
var myLoadNumber = ++loadNumber;
function next() {
// To prevent race conditions we ensure that no future requests have been processed in the mean time.
if (myLoadNumber === loadNumber) {
callback.apply(this, arguments);
callback.apply(self, arguments);
}
}
// in AMD environment realAction is the string containing path to the controller
// which will be loaded async (might be preloaded)
// Only used in AMD environment
if (typeof realAction === 'string') {
self._requireAMD([realAction], function(controller) {
routerContext._requireAMD([realAction], function(controller) {
// check we have everything we need
if (typeof controller[route.action] != 'function') {
throw new Error("Missing action \"" + route.action + "\" for controller \"" + route.controller + "\"");
}
controller[route.action].call(this, params, next);
controller[route.action].call(self, params, next);
});
}
else {
realAction.call(this, params, next);
realAction.call(self, params, next);
}
}
}
Expand Down
44 changes: 32 additions & 12 deletions test/shared/base/router.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,50 +183,70 @@ describe('BaseRouter', function () {
after(clientTestHelper.after);

describe('route', function() {
var getHandler, handler, getAction, controllerPath;
var getHandler, handler, getAction, controllerPath, requireAMD, actionCallback, requireSpy;

beforeEach(function() {
BaseRouter.setAMDEnvironment(true);
controllerPath = 'controllers/home';
handler = sinon.spy();
getHandler = sinon.stub(router, 'getHandler').returns(handler);

actionCallback = sinon.spy();
requireSpy = sinon.spy();

sinon.stub(router, 'getAction').returns(controllerPath);

sinon.stub(router, '_requireAMD').returns(requireSpy);

});

after(function() {
router._requireAMD.restore();
router.getAction.restore();
BaseRouter.setAMDEnvironment(false);
});

it('for AMD version: should trigger an event, pass the correct route object and load the right controller', function() {
BaseRouter.setAMDEnvironment(true);

var trigger = sinon.stub(router, 'trigger');

var callback = sinon.spy();

var requireSpy = sinon.spy();

var requireAMD = sinon.stub(router, '_requireAMD').returns(requireSpy);

router.route('/home', 'home#index');

var getHandlerCall = getHandler.getCall(0);

// call action function
getHandlerCall.callArgWith(0, {}, callback);
getHandlerCall.callArgWith(0, {}, actionCallback);

// controller file path
requireAMD.getCall(0).args[0][0].should.be.equal('controllers/home');
router._requireAMD.getCall(0).args[0][0].should.be.equal('controllers/home');

trigger.should.have.been.calledOnce;
trigger.should.have.been.calledWithExactly('route:add', [
'/home',
{ controller: 'home', action: 'index' },
handler
]);
});

it('call router method with the right context', function() {
var homeController = {index: function() {}};
var controllerSpy = sinon.stub(homeController);

var context = {name: 'foo'};

router.route.call(context, '/home', 'home#index');

var getHandlerCall = getHandler.getCall(0);

// call action function with the right context
getHandlerCall.args[0].call(context, {}, actionCallback);

var requireAMDCall = router._requireAMD.getCall(0);

requireAMDCall.callArgWith(1, controllerSpy);

// check the controller is called with the right context
controllerSpy.index.should.have.been.calledOn(context);

BaseRouter.setAMDEnvironment(false);
});

});
Expand Down