diff --git a/shared/base/router.js b/shared/base/router.js index 3b3bdcb4..9cb8dfd3 100644 --- a/shared/base/router.js +++ b/shared/base/router.js @@ -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); @@ -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); } } } diff --git a/test/shared/base/router.test.js b/test/shared/base/router.test.js index e6efa556..9a430e01 100644 --- a/test/shared/base/router.test.js +++ b/test/shared/base/router.test.js @@ -183,41 +183,41 @@ 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', [ @@ -225,8 +225,28 @@ describe('BaseRouter', function () { { 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); }); });