Skip to content

Commit

Permalink
Fix context.next() for multiple nested routes (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenzzy authored Apr 20, 2017
1 parent a1c9c81 commit ef51005
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 42 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.

## [Unreleased][unreleased]

- Fix `context.next()` for multiple nested routes
([#91](https://github.com/kriasoft/universal-router/pull/91))
- Add `pretty` option for `generateUrls(router, options)` to prettier encoding of URI path segments
([#88](https://github.com/kriasoft/universal-router/pull/88))
- Add source maps for minified builds ([#87](https://github.com/kriasoft/universal-router/pull/87))
Expand Down
36 changes: 26 additions & 10 deletions dist/universal-router.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/universal-router.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/universal-router.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/universal-router.min.js.map

Large diffs are not rendered by default.

36 changes: 25 additions & 11 deletions src/Router.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import matchPath from './matchPath';
import matchRoute from './matchRoute';
import resolveRoute from './resolveRoute';

function isChildRoute(parentRoute, childRoute) {
let route = childRoute;
while (route) {
route = route.parent;
if (route === parentRoute) {
return true;
}
}
return false;
}

class Router {
constructor(routes, options = {}) {
if (Object(routes) !== routes) {
Expand All @@ -30,12 +41,19 @@ class Router {
typeof pathOrContext === 'string' ? { path: pathOrContext } : pathOrContext);
const match = matchRoute(this.root, this.baseUrl, context.path.substr(this.baseUrl.length));
const resolve = this.resolveRoute;
let matches;
let parent;
let matches = null;
let nextMatches = null;

function next(resume) {
parent = matches ? matches.value.route.parent : null;
matches = match.next();
function next(resume, parent = matches.value.route) {
matches = nextMatches || match.next();
nextMatches = null;

if (!resume) {
if (matches.done || !isChildRoute(parent, matches.value.route)) {
nextMatches = matches;
return Promise.resolve(null);
}
}

if (matches.done) {
return Promise.reject(Object.assign(
Expand All @@ -52,18 +70,14 @@ class Router {
return result;
}

if (resume || parent === matches.value.route.parent) {
return next(resume);
}

return result;
return next(resume, parent);
});
}

context.url = context.path;
context.next = next;

return next(true);
return next(true, this.root);
}
}

Expand Down
65 changes: 47 additions & 18 deletions test/Router.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,23 +231,52 @@ describe('router.resolve({ path, ...context })', () => {
{
path: '/test',
children: [
{ path: '/', action() { log.push(2); } },
{
path: '/',
action() { log.push(2); },
children: [
{
path: '/',
action({ next }) {
log.push(3);
return next().then(() => { log.push(6); });
},
children: [
{
path: '/',
action({ next }) {
log.push(4);
return next().then(() => { log.push(5); });
},
},
],
},
],
},
{
path: '/',
action() { log.push(7); },
children: [
{ path: '/', action() { log.push(8); } },
{ path: '*', action() { log.push(9); } },
],
},
],
async action({ next }) {
log.push(1);
const result = await next();
log.push(3);
log.push(10);
return result;
},
},
{ path: '/:id', action() { log.push(4); } },
{ path: '/test', action() { return log.push(5); } },
{ path: '/*', action() { log.push(6); } },
{ path: '/:id', action() { log.push(11); } },
{ path: '/test', action() { log.push(12); return 'done'; } },
{ path: '/*', action() { log.push(13); } },
]);

const result = await router.resolve('/test');
expect(log).to.be.deep.equal([1, 2, 3, 4, 5]);
expect(result).to.be.equal(5);
expect(log).to.be.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
expect(result).to.be.equal('done');
});

it('should support next(true) across multiple routes', async () => {
Expand All @@ -256,45 +285,45 @@ describe('router.resolve({ path, ...context })', () => {
path: '/',
action({ next }) {
log.push(1);
return next().then(() => log.push(8));
return next().then((result) => { log.push(9); return result; });
},
children: [
{
path: '/a/b/c',
action({ next }) {
log.push(2);
return next(true).then(() => log.push(7));
return next(true).then((result) => { log.push(8); return result; });
},
},
{
path: '/a',
action() {
log.push(3);
},
action() { log.push(3); },
children: [
{
path: '/b',
action({ next }) {
log.push(4);
return next().then(() => log.push(6));
return next().then((result) => { log.push(6); return result; });
},
children: [
{
path: '/c',
action() {
log.push(5);
},
action() { log.push(5); },
},
],
},
{
path: '/b/c',
action() { log.push(7); return 'done'; },
},
],
},
],
});

const result = await router.resolve('/a/b/c');
expect(log).to.be.deep.equal([1, 2, 3, 4, 5, 6, 7, 8]);
expect(result).to.be.equal(8);
expect(log).to.be.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9]);
expect(result).to.be.equal('done');
});

it('should support parametrized routes 1', async () => {
Expand Down

0 comments on commit ef51005

Please sign in to comment.