From 5d504fe18813e7c2ce01d76521989d7a12c07d70 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 5 Jun 2015 07:22:38 +0530 Subject: [PATCH 01/11] Add trigger utils --- client/triggers.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 client/triggers.js diff --git a/client/triggers.js b/client/triggers.js new file mode 100644 index 0000000..35f9eae --- /dev/null +++ b/client/triggers.js @@ -0,0 +1,89 @@ +/* + Refactor info: + * Triggers are fully handled in the router layer + * Run all the enter triggers just before invalidating + * If redirected, don't invalidate + * implement exit handler for each route and run triggers + * call that handler for each route + * Run global exit handlers in global page exit handler +*/ +// a set of utility functions for triggers + +Triggers = {}; + +Triggers.applyFilters = functions(triggers, filter) { + if(!(triggers instanceof Array)) { + triggers = [triggers]; + } + + if(!filter) { + return triggers; + } + + if(filter.only && filter.except) { + throw new Error("Triggers don't support only and except filters at once"); + } + + if(!(filter.only instanceof Array)) { + throw new Error("only filters needs to be an array"); + } + + if(!(filter.except instanceof Array)) { + throw new Error("except filters needs to be an array"); + } + + if(filter.only) { + return createTriggers(triggers, filter.only); + } + + if(filter.except) { + return createTriggers(triggers, filter.except, true); + } + + throw new Error("Provided a filter but not supported"); +}; + +Triggers.createTriggers = function(triggers, names, negate) { + var namesMap = {}; + _.each(names, function(name) { + namesMap[name] = true; + }); + + var filteredTriggers = _.map(triggers, function(trigger) { + var modifiedTrigger = function(context, next) { + var routeName = context.route.name; + if(namesMap[routeName] && !negate) { + context(context, next); + } else { + next(); + } + + }; + return modifiedTrigger; + }); + + return filteredTriggers; +}; + +Triggers.runTriggers = functions(triggers, context, redirectFn, after) { + var abort = false; + for(var lc=0; lc Date: Fri, 5 Jun 2015 07:31:18 +0530 Subject: [PATCH 02/11] Update docs --- client/triggers.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/client/triggers.js b/client/triggers.js index 35f9eae..16638b9 100644 --- a/client/triggers.js +++ b/client/triggers.js @@ -11,6 +11,10 @@ Triggers = {}; +// Apply filters for a set of triggers +// @triggers - a set of triggers +// @filter - filter with array fileds with `only` and `except` +// support only either `only` or `except`, but not both Triggers.applyFilters = functions(triggers, filter) { if(!(triggers instanceof Array)) { triggers = [triggers]; @@ -43,6 +47,10 @@ Triggers.applyFilters = functions(triggers, filter) { throw new Error("Provided a filter but not supported"); }; +// create triggers by bounding them to a set of route names +// @triggers - a set of triggers +// @names - list of names to be bound (trigger runs only for these names) +// @negate - negate the result (triggers won't run for above names) Triggers.createTriggers = function(triggers, names, negate) { var namesMap = {}; _.each(names, function(name) { @@ -65,6 +73,11 @@ Triggers.createTriggers = function(triggers, names, negate) { return filteredTriggers; }; +// run triggers and abort if redirected +// @triggers - a set of triggers +// @context - context we need to pass (it must have the route) +// @redirectFn - function which used to redirect +// @after - called after if only all the triggers runs Triggers.runTriggers = functions(triggers, context, redirectFn, after) { var abort = false; for(var lc=0; lc Date: Thu, 18 Jun 2015 12:49:38 +0530 Subject: [PATCH 03/11] Add tests for 'Triggers.runTriggers' --- client/triggers.js | 29 +++++++--- package.js | 53 +++++++++-------- test/client/triggers.js | 124 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 30 deletions(-) create mode 100644 test/client/triggers.js diff --git a/client/triggers.js b/client/triggers.js index 16638b9..1bf268c 100644 --- a/client/triggers.js +++ b/client/triggers.js @@ -15,7 +15,7 @@ Triggers = {}; // @triggers - a set of triggers // @filter - filter with array fileds with `only` and `except` // support only either `only` or `except`, but not both -Triggers.applyFilters = functions(triggers, filter) { +Triggers.applyFilters = function(triggers, filter) { if(!(triggers instanceof Array)) { triggers = [triggers]; } @@ -78,8 +78,11 @@ Triggers.createTriggers = function(triggers, names, negate) { // @context - context we need to pass (it must have the route) // @redirectFn - function which used to redirect // @after - called after if only all the triggers runs -Triggers.runTriggers = functions(triggers, context, redirectFn, after) { +Triggers.runTriggers = function(triggers, context, redirectFn, after) { var abort = false; + var inCurrentLoop = true; + var alreadyRedirected = false; + for(var lc=0; lc Date: Thu, 18 Jun 2015 13:48:17 +0530 Subject: [PATCH 04/11] Add tests for Triggers.createRouteBoundTriggers and Triggers.applyFilters --- client/triggers.js | 24 +++---- test/client/triggers.js | 155 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 12 deletions(-) diff --git a/client/triggers.js b/client/triggers.js index 1bf268c..a625e2a 100644 --- a/client/triggers.js +++ b/client/triggers.js @@ -28,20 +28,20 @@ Triggers.applyFilters = function(triggers, filter) { throw new Error("Triggers don't support only and except filters at once"); } - if(!(filter.only instanceof Array)) { + if(filter.only && !(filter.only instanceof Array)) { throw new Error("only filters needs to be an array"); } - if(!(filter.except instanceof Array)) { + if(filter.except && !(filter.except instanceof Array)) { throw new Error("except filters needs to be an array"); } if(filter.only) { - return createTriggers(triggers, filter.only); + return Triggers.createRouteBoundTriggers(triggers, filter.only); } if(filter.except) { - return createTriggers(triggers, filter.except, true); + return Triggers.createRouteBoundTriggers(triggers, filter.except, true); } throw new Error("Provided a filter but not supported"); @@ -49,23 +49,23 @@ Triggers.applyFilters = function(triggers, filter) { // create triggers by bounding them to a set of route names // @triggers - a set of triggers -// @names - list of names to be bound (trigger runs only for these names) +// @names - list of route names to be bound (trigger runs only for these names) // @negate - negate the result (triggers won't run for above names) -Triggers.createTriggers = function(triggers, names, negate) { +Triggers.createRouteBoundTriggers = function(triggers, names, negate) { var namesMap = {}; _.each(names, function(name) { namesMap[name] = true; }); - var filteredTriggers = _.map(triggers, function(trigger) { + var filteredTriggers = _.map(triggers, function(originalTrigger) { var modifiedTrigger = function(context, next) { var routeName = context.route.name; - if(namesMap[routeName] && !negate) { - context(context, next); - } else { - next(); - } + var matched = (namesMap[routeName])? 1: -1; + matched = (negate)? matched * -1 : matched; + if(matched === 1) { + originalTrigger(context, next); + } }; return modifiedTrigger; }); diff --git a/test/client/triggers.js b/test/client/triggers.js index 7602b68..655f851 100644 --- a/test/client/triggers.js +++ b/test/client/triggers.js @@ -108,6 +108,161 @@ function(test, done) { Triggers.runTriggers([trigger], context, function() {}, function() {}); }); +Tinytest.addAsync( +'Triggers - createRouteBoundTriggers - matching trigger', +function(test, done) { + var context = {route: {name: "abc"}}; + var redirect = function() {}; + + var trigger = function(c, r) { + test.equal(c, context); + test.equal(r, redirect); + done(); + }; + + var triggers = Triggers.createRouteBoundTriggers([trigger], ["abc"]); + triggers[0](context, redirect); +}); + +Tinytest.addAsync( +'Triggers - createRouteBoundTriggers - multiple matching triggers', +function(test, done) { + var context = {route: {name: "abc"}}; + var redirect = function() {}; + var doneCount = 0; + + var trigger = function(c, r) { + test.equal(c, context); + test.equal(r, redirect); + doneCount++; + }; + + var triggers = Triggers.createRouteBoundTriggers([trigger, trigger], ["abc"]); + triggers[0](context, redirect); + triggers[1](context, redirect); + + test.equal(doneCount, 2); + done(); +}); + +Tinytest.addAsync( +'Triggers - createRouteBoundTriggers - no matching trigger', +function(test, done) { + var context = {route: {name: "some-other-route"}}; + var redirect = function() {}; + var doneCount = 0; + + var trigger = function(c, r) { + test.equal(c, context); + test.equal(r, redirect); + doneCount++; + }; + + var triggers = Triggers.createRouteBoundTriggers([trigger], ["abc"]); + triggers[0](context, redirect); + + test.equal(doneCount, 0); + done(); +}); + +Tinytest.addAsync( +'Triggers - createRouteBoundTriggers - negate logic', +function(test, done) { + var context = {route: {name: "some-other-route"}}; + var redirect = function() {}; + var doneCount = 0; + + var trigger = function(c, r) { + test.equal(c, context); + test.equal(r, redirect); + doneCount++; + }; + + var triggers = Triggers.createRouteBoundTriggers([trigger], ["abc"], true); + triggers[0](context, redirect); + + test.equal(doneCount, 1); + done(); +}); + +Tinytest.addAsync( +'Triggers - applyFilters - no filters', +function(test, done) { + var original = []; + test.equal(Triggers.applyFilters(original), original); + done(); +}); + +Tinytest.addAsync( +'Triggers - applyFilters - single trigger to array', +function(test, done) { + var original = function() {}; + test.equal(Triggers.applyFilters(original)[0], original); + done(); +}); + +Tinytest.addAsync( +'Triggers - applyFilters - only and except both', +function(test, done) { + var original = []; + try { + Triggers.applyFilters(original, {only: [], except: []}); + } catch(ex) { + test.isTrue(/only and except/.test(ex.message)); + done(); + } +}); + +Tinytest.addAsync( +'Triggers - applyFilters - only is not an array', +function(test, done) { + var original = []; + try { + Triggers.applyFilters(original, {only: "name"}); + } catch(ex) { + test.isTrue(/to be an array/.test(ex.message)); + done(); + } +}); + +Tinytest.addAsync( +'Triggers - applyFilters - except is not an array', +function(test, done) { + var original = []; + try { + Triggers.applyFilters(original, {except: "name"}); + } catch(ex) { + test.isTrue(/to be an array/.test(ex.message)); + done(); + } +}); + +Tinytest.addAsync( +'Triggers - applyFilters - unsupporeted filter', +function(test, done) { + var original = []; + try { + Triggers.applyFilters(original, {wowFilter: []}); + } catch(ex) { + test.isTrue(/not supported/.test(ex.message)); + done(); + } +}); + +Tinytest.addAsync( +'Triggers - applyFilters - just only filter', +function(test, done) { + var bounded = Triggers.applyFilters(done, {only: ["abc"]}); + bounded[0]({route: {name: "abc"}}); +}); + +Tinytest.addAsync( +'Triggers - applyFilters - just except filter', +function(test, done) { + var bounded = Triggers.applyFilters(done, {except: ["abc"]}); + bounded[0]({route: {name: "some-other"}}); +}); + function MakeTriggers(count, store) { var triggers = []; From 1c2bd8b6aa5571f572c3932d0b155263c3ff8379 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 14:01:17 +0530 Subject: [PATCH 05/11] ByeBye triggers --- client/route.js | 11 ----- client/router.js | 106 +---------------------------------------------- 2 files changed, 1 insertion(+), 116 deletions(-) diff --git a/client/route.js b/client/route.js index f9eadbe..a8b53f7 100644 --- a/client/route.js +++ b/client/route.js @@ -42,15 +42,6 @@ Route.prototype.getAllSubscriptions = function() { return this._subsMap; }; - -Route.prototype._processTriggersEnter = function(context) { - _.each(this._triggersEnter, function(fn) { - if (typeof fn === 'function') { - fn(context); - } - }); -}; - Route.prototype._processMiddlewares = function(context, after) { var currentIndex = 0; var self = this; @@ -76,8 +67,6 @@ Route.prototype._processMiddlewares = function(context, after) { Route.prototype.callAction = function(current) { var self = this; - self._processTriggersEnter(current); - self._processMiddlewares(current.context, function() { self._action(current.params, current.queryParams); }); diff --git a/client/router.js b/client/router.js index 60e5934..12377da 100644 --- a/client/router.js +++ b/client/router.js @@ -10,8 +10,6 @@ Router = function () { this._globalRoute = new Route(this); - this._triggersEnter = []; - this._triggersExit = []; this._middleware = []; this._routes = []; this._routesMap = {}; @@ -22,10 +20,6 @@ Router = function () { this.safeToRun = false; var self = this; - this.triggers = { - enter: self._getRegisterTriggersFn(self._triggersEnter), - exit: self._getRegisterTriggersFn(self._triggersExit) - }; }; Router.prototype.route = function(path, options, group) { @@ -317,8 +311,6 @@ Router.prototype._buildTracker = function() { Tracker.nonreactive(function() { var currentContext = self._current; - self._processTriggersEnter(currentContext); - var isRouteChange = currentContext.oldRoute !== currentContext.route; var isFirstRoute = !currentContext.oldRoute; // first route is not a route change @@ -355,99 +347,6 @@ Router.prototype._invalidateTracker = function() { this._tracker.invalidate(); }; -Router.prototype._getRegisterTriggersFn = function(triggers) { - var fn = function(triggerFns, options) { - options = options || {}; - - if (options.only && options.except) { - var message = "triggers does not support 'only' and 'except' at the same time."; - throw new Error(message); - } - - _.each(triggerFns, function(fn) { - if (typeof fn !== 'function') { - return; - } - - if (options.only) { - fn._only = {}; - _.each(options.only, function(name) { - fn._only[name] = 1; - }); - } - - if (options.except) { - fn._except = {}; - _.each(options.except, function(name) { - fn._except[name] = 1; - }); - } - - triggers.push(fn); - }); - }; - - return fn; -}; - -Router.prototype._shouldCallTrigger = function(current, fn) { - var name = current.route.name; - var shouldCall; - - if (typeof fn !== 'function') { - return false; - } - - if (fn._only) { - shouldCall = !!fn._only[name]; - } else if (fn._except) { - shouldCall = !fn._except[name]; - } else { - shouldCall = true; - } - - return shouldCall; -}; - -Router.prototype._processTriggersEnter = function(current) { - var self = this; - - _.each(this._triggersEnter, function(fn) { - if (self._shouldCallTrigger(current, fn)) { - fn(current); - } - }); -}; - -Router.prototype._processTriggersExit = function(ctx, next) { - var self = this; - - _.each(self._triggersExit, function(fn) { - if (self._shouldCallTrigger(self._current, fn)) { - fn(self._current); - } - }); - - next(); -}; - -Router.prototype._registerRouteTriggersExit = function(route) { - var self = this; - - if (route._triggersExit.length > 0) { - // add route's exit triggers - self._page.exit(route.path, function(ctx, next) { - _.each(route._triggersExit, function(fn) { - if (typeof fn === 'function') { - fn(self._current); - } - }); - - next(); - }); - } -}; - Router.prototype._updateCallbacks = function () { var self = this; @@ -461,15 +360,12 @@ Router.prototype._updateCallbacks = function () { _.each(self._routes, function(route) { self._page(route.path, route._handler); - self._registerRouteTriggersExit(route); }); - self._page.exit("*", self._processTriggersExit.bind(self)); - self._page("*", function(context) { self._notfoundRoute(context); }); }; Router.prototype._page = page; -Router.prototype._qs = qs; +Router.prototype._qs = qs; \ No newline at end of file From fa113a8e6ae83c327672c47b88e73d9c17a4cdeb Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 14:50:14 +0530 Subject: [PATCH 06/11] Implemented clean triggers API --- client/router.js | 52 ++++++++++++++++++++++++++++++--- test/client/trigger.spec.js | 57 +------------------------------------ 2 files changed, 49 insertions(+), 60 deletions(-) diff --git a/client/router.js b/client/router.js index 12377da..8619940 100644 --- a/client/router.js +++ b/client/router.js @@ -10,6 +10,8 @@ Router = function () { this._globalRoute = new Route(this); + this._triggersEnter = []; + this._triggersExit = []; this._middleware = []; this._routes = []; this._routesMap = {}; @@ -19,7 +21,8 @@ Router = function () { // when doing subscriptions this.safeToRun = false; - var self = this; + this._redirectFn = this._page.redirect.bind(this._page); + this._initTriggersAPI(); }; Router.prototype.route = function(path, options, group) { @@ -32,7 +35,8 @@ Router.prototype.route = function(path, options, group) { var self = this; var route = new Route(this, path, options, group); - route._handler = function (context, next) { + // calls when the page route being activates + route._actionHandle = function (context, next) { var oldRoute = self._current.route; self._current = { @@ -47,7 +51,31 @@ Router.prototype.route = function(path, options, group) { // to backward compatibility self._current.params.query = self._current.queryParams; - self._invalidateTracker(); + // we need to invalidate if all the triggers have been completed + // if not that means, we've been redirected to another path + // then we don't need to invalidate + var afterAllTriggersRan = function() { + self._invalidateTracker(); + }; + + var triggers = self._triggersEnter.concat(route._triggersEnter); + Triggers.runTriggers( + triggers, + self._current, + self._redirectFn, + afterAllTriggersRan + ); + }; + + // calls when you exit from the page js route + route._exitHandle = function(context, next) { + var triggers = self._triggersExit.concat(route._triggersExit); + Triggers.runTriggers( + triggers, + self._current, + self._redirectFn, + next + ); }; this._routes.push(route); @@ -359,7 +387,8 @@ Router.prototype._updateCallbacks = function () { }); _.each(self._routes, function(route) { - self._page(route.path, route._handler); + self._page(route.path, route._actionHandle); + self._page.exit(route.path, route._exitHandle); }); self._page("*", function(context) { @@ -367,5 +396,20 @@ Router.prototype._updateCallbacks = function () { }); }; +Router.prototype._initTriggersAPI = function() { + var self = this; + this.triggers = { + enter: function(triggers, filter) { + triggers = Triggers.applyFilters(triggers, filter); + _.extend(self._triggersEnter, triggers); + }, + + exit: function(triggers, filter) { + triggers = Triggers.applyFilters(triggers, filter); + _.extend(self._triggersExit, triggers); + } + }; +}; + Router.prototype._page = page; Router.prototype._qs = qs; \ No newline at end of file diff --git a/test/client/trigger.spec.js b/test/client/trigger.spec.js index 22a1cf5..ca72728 100644 --- a/test/client/trigger.spec.js +++ b/test/client/trigger.spec.js @@ -1,58 +1,3 @@ -Tinytest.add('Client - Triggers - should call trigger', function(test) { - var current = {route: {}}; - var fn = null; - - // tests for route without name - - test.isFalse(FlowRouter._shouldCallTrigger(current, fn)); - - fn = function() {}; - test.isTrue(FlowRouter._shouldCallTrigger(current, fn)); - - fn._only = {'foo': 1}; - test.isFalse(FlowRouter._shouldCallTrigger(current, fn)); - - fn._except = {'foo': 1}; - fn._only = null; - test.isTrue(FlowRouter._shouldCallTrigger(current, fn)); - - // tests for route with name - - current.route.name = 'bar'; - fn._except = null; - - fn._only = {'foo': 1}; - test.isFalse(FlowRouter._shouldCallTrigger(current, fn)); - - fn._only = {'bar': 1}; - test.isTrue(FlowRouter._shouldCallTrigger(current, fn)); - - fn._only = null; - - fn._except = {'foo': 1}; - test.isTrue(FlowRouter._shouldCallTrigger(current, fn)); - - fn._except = {'bar': 1}; - test.isFalse(FlowRouter._shouldCallTrigger(current, fn)); -}); - -Tinytest.add('Client - Triggers - get register triggers function', function(test) { - var triggers = []; - - var registerFn = FlowRouter._getRegisterTriggersFn(triggers); - test.equal(typeof registerFn, 'function'); - - // does not accept "only" and "except" at the same time - test.throws(function() { - registerFn([], {only: ['foo'], except: ['bar']}); - }); - - var fn = function() {}; - registerFn([fn, 'trigger'], {only: ['foo']}); - - test.equal(triggers.length, 1); -}); - Tinytest.addAsync('Client - Triggers - global enter triggers', function(test, next) { var rand = Random.id(), rand2 = Random.id(); var log = []; @@ -408,4 +353,4 @@ Tinytest.addAsync('Client - Triggers - group exit triggers', function (test, nex setTimeout(next, 100); }, 100); }, 100); -}); +}); \ No newline at end of file From bf83235dc1dd775b828f617f4b192cbc97ac556b Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 16:46:14 +0530 Subject: [PATCH 07/11] Add tests for redirections --- client/router.js | 1 + test/client/trigger.spec.js | 74 ++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/client/router.js b/client/router.js index 8619940..6e3393f 100644 --- a/client/router.js +++ b/client/router.js @@ -373,6 +373,7 @@ Router.prototype._buildTracker = function() { Router.prototype._invalidateTracker = function() { this.safeToRun = true; this._tracker.invalidate(); + Tracker.flush(); }; Router.prototype._updateCallbacks = function () { diff --git a/test/client/trigger.spec.js b/test/client/trigger.spec.js index ca72728..4ea2eb9 100644 --- a/test/client/trigger.spec.js +++ b/test/client/trigger.spec.js @@ -323,7 +323,6 @@ Tinytest.addAsync('Client - Triggers - group exit triggers', function (test, nex var log = []; var triggerFn = function (context) { - test.equal(context.path, '/' + rand); log.push(4); }; @@ -353,4 +352,77 @@ Tinytest.addAsync('Client - Triggers - group exit triggers', function (test, nex setTimeout(next, 100); }, 100); }, 100); +}); + +Tinytest.addAsync('Client - Triggers - redirect from enter', function(test, next) { + var rand = Random.id(), rand2 = Random.id(); + var log = []; + + FlowRouter.route('/' + rand, { + triggersEnter: [function(context, redirect) { + redirect("/" + rand2); + }, function() { + throw new Error("should not execute this trigger"); + }], + action: function(_params) { + log.push(1); + }, + name: rand + }); + + FlowRouter.route('/' + rand2, { + action: function(_params) { + log.push(2); + }, + name: rand2 + }); + + FlowRouter.go('/' + rand); + + setTimeout(function() { + test.equal(log, [2]); + next(); + }, 300); +}); + +Tinytest.addAsync('Client - Triggers - redirect from exit', function(test, next) { + var rand = Random.id(), rand2 = Random.id(), rand3 = Random.id(); + var log = []; + + FlowRouter.route('/' + rand, { + action: function() { + log.push(1); + }, + triggersExit: [ + function(context, redirect) { + redirect('/' + rand3); + }, + function() { + throw new Error("should not call this trigger"); + } + ] + }); + + FlowRouter.route('/' + rand2, { + action: function() { + log.push(2); + } + }); + + FlowRouter.route('/' + rand3, { + action: function() { + log.push(3); + } + }); + + FlowRouter.go('/' + rand); + + setTimeout(function() { + FlowRouter.go('/' + rand2); + + setTimeout(function() { + test.equal(log, [1, 3]); + next(); + }, 100); + }, 100); }); \ No newline at end of file From fe58b0accb8bbf457f053c96f4e98c50c3aee770 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 16:52:18 +0530 Subject: [PATCH 08/11] Add some comments --- client/router.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/router.js b/client/router.js index 6e3393f..f74ac58 100644 --- a/client/router.js +++ b/client/router.js @@ -373,6 +373,8 @@ Router.prototype._buildTracker = function() { Router.prototype._invalidateTracker = function() { this.safeToRun = true; this._tracker.invalidate(); + // we need to trigger the above invalidations immediately + // otherwise, we need to face some issues with route context swapping Tracker.flush(); }; From 3490a3f4ce8b576673d31e30cf3b4b75e6fca223 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 17:05:15 +0530 Subject: [PATCH 09/11] Use _.bind for backward compatibility We don't support older browsers But at least, this allow us to run tests inside Phantom --- client/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/router.js b/client/router.js index f74ac58..339de1d 100644 --- a/client/router.js +++ b/client/router.js @@ -21,7 +21,7 @@ Router = function () { // when doing subscriptions this.safeToRun = false; - this._redirectFn = this._page.redirect.bind(this._page); + this._redirectFn = _.bind(this._page.redirect, this._page); this._initTriggersAPI(); }; From 2231fead9ddb2bc4abfa298837130bfd316c2654 Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Fri, 19 Jun 2015 17:06:15 +0530 Subject: [PATCH 10/11] Remove older comments --- client/triggers.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/client/triggers.js b/client/triggers.js index a625e2a..2fc0f2f 100644 --- a/client/triggers.js +++ b/client/triggers.js @@ -1,12 +1,3 @@ -/* - Refactor info: - * Triggers are fully handled in the router layer - * Run all the enter triggers just before invalidating - * If redirected, don't invalidate - * implement exit handler for each route and run triggers - * call that handler for each route - * Run global exit handlers in global page exit handler -*/ // a set of utility functions for triggers Triggers = {}; From ced2b6305f59abe1d72cd223b5ffcd67fd32c69d Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Sun, 21 Jun 2015 06:43:15 +0530 Subject: [PATCH 11/11] Gaurd Track.flush to prevent doing in inside an autorun --- client/router.js | 5 ++++- test/client/trigger.spec.js | 44 ++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/client/router.js b/client/router.js index 339de1d..950082a 100644 --- a/client/router.js +++ b/client/router.js @@ -375,7 +375,10 @@ Router.prototype._invalidateTracker = function() { this._tracker.invalidate(); // we need to trigger the above invalidations immediately // otherwise, we need to face some issues with route context swapping - Tracker.flush(); + // if this is a running autorun we don't need to flush it + if(!Tracker.currentComputation) { + Tracker.flush(); + } }; Router.prototype._updateCallbacks = function () { diff --git a/test/client/trigger.spec.js b/test/client/trigger.spec.js index 4ea2eb9..7a9dd1f 100644 --- a/test/client/trigger.spec.js +++ b/test/client/trigger.spec.js @@ -377,6 +377,7 @@ Tinytest.addAsync('Client - Triggers - redirect from enter', function(test, next name: rand2 }); + FlowRouter.go('/'); FlowRouter.go('/' + rand); setTimeout(function() { @@ -425,4 +426,45 @@ Tinytest.addAsync('Client - Triggers - redirect from exit', function(test, next) next(); }, 100); }, 100); -}); \ No newline at end of file +}); + +Tinytest.addAsync( +'Client - Triggers - invalidate inside an autorun', +function(test, next) { + var rand = Random.id(), rand2 = Random.id(); + var log = []; + var paths = ['/' + rand2, '/' + rand]; + var done = false; + + FlowRouter.route('/' + rand, { + action: function(_params) { + log.push(1); + } + }); + + FlowRouter.route('/' + rand2, { + action: function(_params) { + log.push(2); + } + }); + + FlowRouter.triggers.enter([function(context) { + if(done) return; + test.equal(context.path, paths.pop()); + log.push(0); + }]); + + Tracker.autorun(function(c) { + FlowRouter.go('/' + rand); + }); + + setTimeout(function() { + FlowRouter.go('/' + rand2); + + setTimeout(function() { + test.equal(log, [0, 1, 0, 2]); + done = true; + setTimeout(next, 100); + }, 100); + }, 100); +});