From e16edfc15924b46f72f0ce6225846087d04b94dc Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Mon, 15 Sep 2014 23:39:39 +0200 Subject: [PATCH 01/12] added the notion of router hierarchy Now all routers are automatically added to a list and enabled the use of this.navigate('../other_route') which then takes the parent route to execute navigae on. Not tested but this should also enable this.navigate('../../other/route') --- lib/RouterMixin.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index a20390c..e559115 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -17,17 +17,23 @@ var RouterMixin = { }, childContextTypes: { - router: React.PropTypes.any + router: React.PropTypes.any, + routers: React.PropTypes.any }, getChildContext: function() { + var routers = this.context.routers || [] + routers.unshift(this) + return { - router: this + router: this, + routers: routers }; }, contextTypes: { - router: React.PropTypes.any + router: React.PropTypes.any, + routers: React.PropTypes.any }, getInitialState: function() { @@ -137,6 +143,12 @@ var RouterMixin = { cb = navigation; navigation = {}; } + + if (path.indexOf('../') !== -1) { + this.context.routers[1].navigate(path.slice(2), navigation, cb) + return + } + navigation = navigation || {}; path = join(this.state.prefix, path); this.getEnvironment().setPath(path, navigation, cb); From 06dab84cdd5b41b9caf2e007942a0e9be49e8e9e Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Tue, 16 Sep 2014 00:23:28 +0200 Subject: [PATCH 02/12] fixed a raise situation on load ensure that there are no duplicate routers in the list --- lib/RouterMixin.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index e559115..ec99480 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -23,7 +23,9 @@ var RouterMixin = { getChildContext: function() { var routers = this.context.routers || [] - routers.unshift(this) + if (routers.indexOf(this) === -1) { + routers.unshift(this) + } return { router: this, From a954365c2dba4e15cadc171e1c13f75492c179fb Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Tue, 16 Sep 2014 20:38:15 +0200 Subject: [PATCH 03/12] fixed a bug with multiple parent routers --- lib/RouterMixin.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index ec99480..957e3e5 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -146,8 +146,9 @@ var RouterMixin = { navigation = {}; } - if (path.indexOf('../') !== -1) { - this.context.routers[1].navigate(path.slice(2), navigation, cb) + var strippedPath = this.stripPath(path); + if (path !== strippedPath) { + this.context.routers[1].navigate(strippedPath, navigation, cb); return } @@ -156,6 +157,25 @@ var RouterMixin = { this.getEnvironment().setPath(path, navigation, cb); }, + /** + * Returns path for parent router. + * + * This function is called by navigate. + * + * @private + * + * @param {String} path + */ + stripPath: function(path) { + if (path.slice(4) === "/../") { + return path.slice(3); + } + if (path.slice(3) === "../") { + return path.slice(2); + } + return path; + }, + /** * Set new path. * From cd547fe8e89bb217adaff9f56229a387f2ad90ed Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Tue, 16 Sep 2014 21:39:45 +0200 Subject: [PATCH 04/12] refactored the previous fix to reduce if statements --- lib/RouterMixin.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index 957e3e5..f8e99f9 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -167,13 +167,11 @@ var RouterMixin = { * @param {String} path */ stripPath: function(path) { - if (path.slice(4) === "/../") { - return path.slice(3); + var index = path.indexOf('../'); + if (index === -1) { + return path; } - if (path.slice(3) === "../") { - return path.slice(2); - } - return path; + return path.substr(index + 2); }, /** From 372c7039c75768b5729d1b267c14acbf66a199b0 Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Wed, 17 Sep 2014 00:02:40 +0200 Subject: [PATCH 05/12] added tests and fixed a bug --- lib/RouterMixin.js | 25 ++------ tests/browser.js | 153 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 21 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index 731baa5..c2f59fc 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -141,9 +141,11 @@ var RouterMixin = { * @param {Callback} cb */ navigate: function(path, navigation, cb) { - var strippedPath = this.stripPath(path); - if (path !== strippedPath) { - this.context.routers[1].navigate(strippedPath, navigation, cb); + var levels = path.split('../'); + if (levels.length > 1) { + var newPath = "/" + levels[levels.length-1]; + var gotoContext = levels.length-1; + this.context.routers[gotoContext].navigate(newPath, navigation, cb); return; } @@ -151,23 +153,6 @@ var RouterMixin = { this.getEnvironment().setPath(path, navigation, cb); }, - /** - * Returns path for parent router. - * - * This function is called by navigate. - * - * @private - * - * @param {String} path - */ - stripPath: function(path) { - var index = path.indexOf('../'); - if (index === -1) { - return path; - } - return path.substr(index + 2); - }, - /** * Set new path. * diff --git a/tests/browser.js b/tests/browser.js index 88f6cfb..7a7ddf5 100644 --- a/tests/browser.js +++ b/tests/browser.js @@ -345,7 +345,7 @@ describe('Routing with async components', function() { }); beforeEach(function() { - mainWasInLoadingState = false; + mainWasInLoadingState = false; aboutWasInLoadingState = false; mainSeenPendingUpdate = false; @@ -553,6 +553,33 @@ describe('Contextual routers', function() { if (!historyAPI) return; + var SubSubCat = React.createClass({ + + render: function() { + return div(null, + Router.Locations({ref: 'router', contextual: true}, + Router.Location({ + path: '/', + handler: function(props) { return div(null, 'subcat/subsubcat/root') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent') + } + }), + Router.Location({ + path: '/back_to_root', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../../__zuul'}, 'subcat/subsubcat/back_to_root') + } + }) + )); + } + }); + var SubCat = React.createClass({ render: function() { @@ -575,6 +602,18 @@ describe('Contextual routers', function() { handler: function(props) { return Router.Link({global: true, href: '/__zuul'}, 'subcat/escape') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../__zuul'}, 'subcat/back_to_parent') + } + }), + Router.Location({ + path: '/subsubcat/*', + handler: SubSubCat, + ref: 'subsubcat' }) )); } @@ -652,6 +691,42 @@ describe('Contextual routers', function() { }); }); }); + + it('does navigate to root context from nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/back_to_parent', function() { + assertRendered('subcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + + it('does navigate to nested context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/subsubcat/back_to_parent', function() { + assertRendered('subcat/subsubcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('subcat/root'); + done(); + }); + }); + }); + + it('does navigate to root context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/subsubcat/back_to_root', function() { + assertRendered('subcat/subsubcat/back_to_root'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); }); describe('Multiple active routers', function() { @@ -833,6 +908,33 @@ describe('Hash routing', function() { describe('Contextual Hash routers', function() { + var SubSubCat = React.createClass({ + + render: function() { + return div(null, + Router.Locations({ref: 'router', contextual: true}, + Router.Location({ + path: '/', + handler: function(props) { return div(null, 'subcat/subsubcat/root') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent') + } + }), + Router.Location({ + path: '/back_to_root', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../../'}, 'subcat/subsubcat/back_to_root') + } + }) + )); + } + }); + var SubCat = React.createClass({ render: function() { @@ -848,6 +950,18 @@ describe('Contextual Hash routers', function() { handler: function(props) { return Router.Link({globalHash: true, href: '/'}, 'subcat/escape'); } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/back_to_parent') + } + }), + Router.Location({ + path: '/subsubcat/*', + handler: SubSubCat, + ref: 'subsubcat' }) )); } @@ -889,6 +1003,43 @@ describe('Contextual Hash routers', function() { }); }); + + it('does navigate to root context from nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/back_to_parent', function() { + assertRendered('subcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + + it('does navigate to nested context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/subsubcat/back_to_parent', function() { + assertRendered('subcat/subsubcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('subcat/root'); + done(); + }); + }); + }); + + it('does navigate to root context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/subsubcat/back_to_root', function() { + assertRendered('subcat/subsubcat/back_to_root'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + }); }); From 91d57f9c1b49e8249276af20aff07e13770e5561 Mon Sep 17 00:00:00 2001 From: Mark Nijhof Date: Mon, 15 Sep 2014 23:39:39 +0200 Subject: [PATCH 06/12] added the notion of router hierarchy Now all routers are automatically added to a list and enabled the use of this.navigate('../other_route') which then takes the parent route to execute navigae on. Not tested but this should also enable this.navigate('../../other/route') --- lib/RouterMixin.js | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index a20390c..f8e99f9 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -17,17 +17,25 @@ var RouterMixin = { }, childContextTypes: { - router: React.PropTypes.any + router: React.PropTypes.any, + routers: React.PropTypes.any }, getChildContext: function() { + var routers = this.context.routers || [] + if (routers.indexOf(this) === -1) { + routers.unshift(this) + } + return { - router: this + router: this, + routers: routers }; }, contextTypes: { - router: React.PropTypes.any + router: React.PropTypes.any, + routers: React.PropTypes.any }, getInitialState: function() { @@ -137,11 +145,35 @@ var RouterMixin = { cb = navigation; navigation = {}; } + + var strippedPath = this.stripPath(path); + if (path !== strippedPath) { + this.context.routers[1].navigate(strippedPath, navigation, cb); + return + } + navigation = navigation || {}; path = join(this.state.prefix, path); this.getEnvironment().setPath(path, navigation, cb); }, + /** + * Returns path for parent router. + * + * This function is called by navigate. + * + * @private + * + * @param {String} path + */ + stripPath: function(path) { + var index = path.indexOf('../'); + if (index === -1) { + return path; + } + return path.substr(index + 2); + }, + /** * Set new path. * From 9aa223fb6c71249b93bb1b76fd96fd89dd65e61d Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 09:48:36 -0400 Subject: [PATCH 07/12] Fix middle-click and meta+click (new tab) on . Fixes #83. --- lib/Link.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Link.js b/lib/Link.js index b0af071..66dc3f2 100644 --- a/lib/Link.js +++ b/lib/Link.js @@ -26,7 +26,10 @@ var Link = React.createClass({ if (this.props.onClick) { this.props.onClick(e); } - if (!e.defaultPrevented) { + if (!e.defaultPrevented && + // Don't break middle-click or (meta|ctrl)+click (new tab) + !(e.button == 1 || e.metaKey || e.ctrlKey) + ) { e.preventDefault(); this._navigate(this.props.href, function(err) { if (err) { From 20c6e22e49eaae3a1567f4877af38b6badaefd80 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 09:54:46 -0400 Subject: [PATCH 08/12] 0.20.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c65af1..11e9f1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-router-component", - "version": "0.20.1", + "version": "0.20.2", "description": "Declarative router component for React", "main": "index.js", "dependencies": { From f9a1ece437349044f5aeeb60e5bae78350e3cdf2 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 10:14:10 -0400 Subject: [PATCH 09/12] Add note about zuul tests for contributors. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 146e73a..30dcf5b 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ lint: @jshint index.js `find lib -name '*.js'` test: test-unit test-server + @echo "The browser test suite should be run before commit. Run 'make test-local' to run it." test-unit: @mocha -R spec -b tests/matchRoutes.js From 6cdee8b1881828449001befb8d512cb888d1a4d5 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 10:15:27 -0400 Subject: [PATCH 10/12] Simplify arities of setPath/navigate(). Fixes #81. --- lib/RouterMixin.js | 33 ++++++----------------------- lib/environment/DummyEnvironment.js | 7 +++++- lib/environment/Environment.js | 10 ++++++--- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/lib/RouterMixin.js b/lib/RouterMixin.js index f8e99f9..c2f59fc 100644 --- a/lib/RouterMixin.js +++ b/lib/RouterMixin.js @@ -141,39 +141,18 @@ var RouterMixin = { * @param {Callback} cb */ navigate: function(path, navigation, cb) { - if (typeof navigation === 'function' && cb === undefined) { - cb = navigation; - navigation = {}; + var levels = path.split('../'); + if (levels.length > 1) { + var newPath = "/" + levels[levels.length-1]; + var gotoContext = levels.length-1; + this.context.routers[gotoContext].navigate(newPath, navigation, cb); + return; } - var strippedPath = this.stripPath(path); - if (path !== strippedPath) { - this.context.routers[1].navigate(strippedPath, navigation, cb); - return - } - - navigation = navigation || {}; path = join(this.state.prefix, path); this.getEnvironment().setPath(path, navigation, cb); }, - /** - * Returns path for parent router. - * - * This function is called by navigate. - * - * @private - * - * @param {String} path - */ - stripPath: function(path) { - var index = path.indexOf('../'); - if (index === -1) { - return path; - } - return path.substr(index + 2); - }, - /** * Set new path. * diff --git a/lib/environment/DummyEnvironment.js b/lib/environment/DummyEnvironment.js index ca65d6c..a67dd47 100644 --- a/lib/environment/DummyEnvironment.js +++ b/lib/environment/DummyEnvironment.js @@ -17,7 +17,12 @@ DummyEnvironment.prototype.constructor = DummyEnvironment; DummyEnvironment.prototype.getPath = emptyFunction.thatReturnsNull; -DummyEnvironment.prototype.setPath = function(path, cb) { +DummyEnvironment.prototype.setPath = function(path, navigation, cb) { + // Support old (path, cb) arity + if (typeof navigation === 'function' && cb === undefined) { + cb = navigation; + navigation = {}; + } this.path = path; cb(); }; diff --git a/lib/environment/Environment.js b/lib/environment/Environment.js index f4d39fd..f37c9b6 100644 --- a/lib/environment/Environment.js +++ b/lib/environment/Environment.js @@ -44,14 +44,18 @@ Environment.prototype.makeHref = function makeHref(path) { } Environment.prototype.navigate = function navigate(path, navigation, cb) { + return this.setPath(path, navigation, cb); +} + +Environment.prototype.setPath = function(path, navigation, cb) { + // Support (path, cb) arity. if (typeof navigation === 'function' && cb === undefined) { cb = navigation; navigation = {}; } - return this.setPath(path, navigation, cb); -} + // Support (path) arity. + if (!navigation) navigation = {}; -Environment.prototype.setPath = function(path, navigation, cb) { if (!navigation.isPopState) { if (navigation.replace) { this.replaceState(path, navigation); From 05cca067502fa8b6cf4c5a12bbc4f904f87deafc Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 10:18:41 -0400 Subject: [PATCH 11/12] 0.20.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11e9f1b..46f30a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-router-component", - "version": "0.20.2", + "version": "0.20.3", "description": "Declarative router component for React", "main": "index.js", "dependencies": { From bb45cf765a7df37340770ab9e91e3eff0ea9fe57 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 16 Sep 2014 10:19:03 -0400 Subject: [PATCH 12/12] Update CHANGELOG added tests and fixed a bug --- CHANGELOG.md | 7 +++ tests/browser.js | 153 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5119554..b46d4e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +## 0.20.3 + - Fixed mismatch in arities when using `navigate()` and `setPath()`. + +## 0.20.2 + - Fixed middle-click and ctrl/meta click on components not opening + in a new tab. + ## 0.20.1 - Fixed `reactify` devdep in examples. diff --git a/tests/browser.js b/tests/browser.js index 88f6cfb..7a7ddf5 100644 --- a/tests/browser.js +++ b/tests/browser.js @@ -345,7 +345,7 @@ describe('Routing with async components', function() { }); beforeEach(function() { - mainWasInLoadingState = false; + mainWasInLoadingState = false; aboutWasInLoadingState = false; mainSeenPendingUpdate = false; @@ -553,6 +553,33 @@ describe('Contextual routers', function() { if (!historyAPI) return; + var SubSubCat = React.createClass({ + + render: function() { + return div(null, + Router.Locations({ref: 'router', contextual: true}, + Router.Location({ + path: '/', + handler: function(props) { return div(null, 'subcat/subsubcat/root') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent') + } + }), + Router.Location({ + path: '/back_to_root', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../../__zuul'}, 'subcat/subsubcat/back_to_root') + } + }) + )); + } + }); + var SubCat = React.createClass({ render: function() { @@ -575,6 +602,18 @@ describe('Contextual routers', function() { handler: function(props) { return Router.Link({global: true, href: '/__zuul'}, 'subcat/escape') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../__zuul'}, 'subcat/back_to_parent') + } + }), + Router.Location({ + path: '/subsubcat/*', + handler: SubSubCat, + ref: 'subsubcat' }) )); } @@ -652,6 +691,42 @@ describe('Contextual routers', function() { }); }); }); + + it('does navigate to root context from nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/back_to_parent', function() { + assertRendered('subcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + + it('does navigate to nested context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/subsubcat/back_to_parent', function() { + assertRendered('subcat/subsubcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('subcat/root'); + done(); + }); + }); + }); + + it('does navigate to root context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/__zuul/subcat/subsubcat/back_to_root', function() { + assertRendered('subcat/subsubcat/back_to_root'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); }); describe('Multiple active routers', function() { @@ -833,6 +908,33 @@ describe('Hash routing', function() { describe('Contextual Hash routers', function() { + var SubSubCat = React.createClass({ + + render: function() { + return div(null, + Router.Locations({ref: 'router', contextual: true}, + Router.Location({ + path: '/', + handler: function(props) { return div(null, 'subcat/subsubcat/root') } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/subsubcat/back_to_parent') + } + }), + Router.Location({ + path: '/back_to_root', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../../'}, 'subcat/subsubcat/back_to_root') + } + }) + )); + } + }); + var SubCat = React.createClass({ render: function() { @@ -848,6 +950,18 @@ describe('Contextual Hash routers', function() { handler: function(props) { return Router.Link({globalHash: true, href: '/'}, 'subcat/escape'); } + }), + Router.Location({ + path: '/back_to_parent', + ref: 'link', + handler: function(props) { + return Router.Link({href: '../'}, 'subcat/back_to_parent') + } + }), + Router.Location({ + path: '/subsubcat/*', + handler: SubSubCat, + ref: 'subsubcat' }) )); } @@ -889,6 +1003,43 @@ describe('Contextual Hash routers', function() { }); }); + + it('does navigate to root context from nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/back_to_parent', function() { + assertRendered('subcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + + it('does navigate to nested context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/subsubcat/back_to_parent', function() { + assertRendered('subcat/subsubcat/back_to_parent'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('subcat/root'); + done(); + }); + }); + }); + + it('does navigate to root context from double nested', function(done) { + assertRendered('mainpage'); + router.navigate('/subcat/subsubcat/back_to_root', function() { + assertRendered('subcat/subsubcat/back_to_root'); + clickOn(router.refs.subcat.refs.router.refs.subsubcat.refs.router.refs.link); + delay(function() { + assertRendered('mainpage'); + done(); + }); + }); + }); + }); });