UNPKG

wayfarer

Version:

Composable trie based router

369 lines (324 loc) 8.98 kB
var wayfarer = require('../') var noop = require('noop2') var tape = require('tape') tape('router', function (t) { t.test('should match a path', function (t) { t.plan(1) var r = wayfarer() r.on('/', function () { t.pass('called') }) r('/') }) t.test('should match a nested path', function (t) { t.plan(1) var r = wayfarer() r.on('/foo/bar', function () { t.pass('called') }) r('/foo/bar') }) t.test('should match a default path', function (t) { t.plan(1) var r = wayfarer('/404') r.on('/404', function () { t.pass('default') }) r('/nope') }) t.test('should allow passing of extra values', function (t) { t.plan(2) var foo = {} var bar = {} var r = wayfarer() r.on('/foo', function (params, arg1, arg2) { t.equal(arg1, foo, 'arg1 was passed') t.equal(arg2, bar, 'arg2 was passed') }) r('/foo', foo, bar) }) t.test('.on() should catch type errors', function (t) { t.plan(2) var r = wayfarer() t.throws(r.on.bind(r, 123), /string/, 'string') t.throws(r.on.bind(r, '/hi', 123), /function/, 'function') }) t.test('.emit() should match paths', function (t) { t.plan(2) var r = wayfarer() r.on('/foo/bar', function (param) { t.pass('bar called') }) r.on('/foo/baz', function (param) { t.pass('baz called') }) r('/foo/bar') r('/foo/baz') }) t.test('.match() should match paths', function (t) { t.plan(2) var r = wayfarer() r.on('/foo/bar', function () { t.fail('should not call callback') }) r.on('/foo/baz', noop) var bar = r.match('/foo/bar') t.equal(bar.route, '/foo/bar') var baz = r.match('/foo/baz') t.equal(baz.route, '/foo/baz') }) t.test('.emit() should match partials', function (t) { t.plan(1) var r = wayfarer() r.on('/:user', function (param) { t.equal(param.user, 'tobi', 'param matched') }) r('/tobi') }) t.test('.match() should match partials', function (t) { t.plan(1) var r = wayfarer() r.on('/:user', noop) var toby = r.match('/tobi') t.equal(toby.params.user, 'tobi') }) t.test('.emit() should match paths before partials', function (t) { t.plan(1) var r = wayfarer() r.on('/foo', function () { t.pass('called') }) r.on('/:user', noop) r('/foo') }) t.test('.emit() should allow path overriding', function (t) { t.plan(1) var r = wayfarer() r.on('/:user', function () { t.fail('wrong callback called') }) r.on('/:user', function () { t.pass('called') }) r('/foo') }) t.test('.emit() should match nested partials', function (t) { t.plan(2) var r = wayfarer() r.on('/:user/:name', function (param) { t.equal(param.user, 'tobi', 'param matched') t.equal(param.name, 'baz', 'param matched') }) r('/tobi/baz') }) t.test('.emit() should parse encoded params', function (t) { t.plan(1) var r = wayfarer() r.on('/:channel', function (param) { t.equal(param.channel, '#choo', 'param matched') }) r('/%23choo') }) t.test('.emit() should throw if no matches are found', function (t) { t.plan(1) var r1 = wayfarer() t.throws(r1.bind(r1, '/woops'), /route/, 'no matches found') }) t.test('.emit() should return values', function (t) { t.plan(1) var r1 = wayfarer() r1.on('/foo', function () { return 'hello' }) t.equal(r1('foo'), 'hello', 'returns value') }) t.test('.emit() mount subrouters', function (t) { t.plan(5) var r4 = wayfarer() var r3 = wayfarer() r4.on('/kidlette', function () { t.pass('nested 2 levels') }) r3.on('/mom', r4) r3('/mom/kidlette') var r1 = wayfarer() var r2 = wayfarer() r2.on('/', function () { t.pass('nested 1 level') }) r1.on('/home', r2) r1('/home') var r5 = wayfarer() var r6 = wayfarer() r6.on('/child', function (param) { t.equal(typeof param, 'object', 'param is passed') t.equal(param.parent, 'hello', 'nested 2 levels with params') }) r5.on('/:parent', r6) r5('/hello/child') var r7 = wayfarer() var r8 = wayfarer() var r9 = wayfarer() r9.on('/bar', function (param) { t.pass('called', 'nested 3 levels') }) r8.on('/bin', r9) r7.on('/foo', r8) r7('/foo/bin/bar') }) t.test('.emit() should match nested partials of subrouters', function (t) { t.plan(3) var r1 = wayfarer() var r2 = wayfarer() var r3 = wayfarer() r3.on('/:grandchild', function (param) { t.equal(param.parent, 'bin', 'nested 3 levels with params') t.equal(param.child, 'bar', 'nested 3 levels with params') t.equal(param.grandchild, 'baz', 'nested 3 levels with parmas') }) r2.on('/:child', r3) r1.on('/foo/:parent', r2) r1('/foo/bin/bar/baz') }) t.test('.match() should return nested partials of subrouters', function (t) { t.plan(3) var r1 = wayfarer() var r2 = wayfarer() var r3 = wayfarer() r3.on('/:grandchild', noop) r2.on('/:child', r3) r1.on('/foo/:parent', r2) var matched = r1.match('/foo/bin/bar/baz') t.equal(matched.params.parent, 'bin') t.equal(matched.params.child, 'bar') t.equal(matched.params.grandchild, 'baz') }) t.test('.match() returns a handler of a route', function (t) { t.plan(1) var r = wayfarer() r.on('/:user', function () { t.pass('called') }) var toby = r.match('/tobi') toby.cb() }) t.test('nested routes should call parent default route', function (t) { t.plan(4) var r1 = wayfarer('/404') var r2 = wayfarer() var r3 = wayfarer() r2.on('/bar', r3) r1.on('foo', r2) r1.on('/404', pass) r1('') r1('foo') r1('foo/bar') r1('foo/beep/boop') function pass (params) { t.pass('called') } }) t.test('aliases', function (t) { t.plan(1) var r = wayfarer() t.equal(r, r.emit) }) t.test('wildcards', function (t) { t.plan(3) var r = wayfarer() r.on('/bar/*', function (params) { t.equal(params.wildcard, 'foo/beep/boop') }) r.on('/foo/:match/*', function (params) { t.equal(params.match, 'bar') t.equal(params.wildcard, 'beep/boop') }) r('/bar/foo/beep/boop') r('/foo/bar/beep/boop') }) t.test('wildcards dont conflict with params', function (t) { t.plan(3) var router router = wayfarer() router.on('/*', function (params) { t.fail('wildcard called') }) router.on('/:match', function (params) { t.pass('param called') }) router('/foo') router = wayfarer() router.on('/*', function (params) { t.fail('wildcard called') }) router.on('/:match/foo', function (params) { t.pass('param called') }) router('/foo/foo') router = wayfarer() router.on('/*', function (params) { t.pass('wildcard called') }) router.on('/:match/foo', function (params) { t.fail('param called') }) router('/foo/bar') }) t.test('safe decodeURIComponent', function (t) { t.plan(1) var r = wayfarer('/404') r.on('/test/:id', function (params) { t.fail('we should not be here') }) r.on('/404', function () { t.pass('called') }) r('/test/hel%"Flo') }) t.test('safe decodeURIComponent - nested route', function (t) { t.plan(1) var r = wayfarer('/404') r.on('/test/hello/world/:id/blah', function (params) { t.fail('we should not be here') }) r.on('/404', function () { t.pass('called') }) r('/test/hello/world/hel%"Flo/blah') }) t.test('safe decodeURIComponent - wildcard', function (t) { t.plan(1) var r = wayfarer('/404') r.on('/test/*', function (params) { t.fail('we should not be here') }) r.on('/404', function () { t.pass('called') }) r('/test/hel%"Flo') }) t.test('should expose .route property', function (t) { t.plan(1) var r = wayfarer() r.on('/foo', function () {}) t.equal(r.match('/foo').route, '/foo', 'exposes route property') }) t.test('should be called with self', function (t) { t.plan(1) var r = wayfarer() r.on('/foo', function callback () { t.equal(this, callback, 'calling context is self') }) r('/foo') }) t.test('can register callback on many routes', function (t) { t.plan(6) var r = wayfarer() var routes = ['/foo', '/bar'] r.on('/foo', callback) r.on('/bar', callback) for (var i = 0, len = routes.length, matched; i < len; i++) { matched = r.match(routes[i]) t.equal(matched.cb, callback, 'matched callback is same') t.equal(matched.route, routes[i], 'matched route is same') r(routes[i]) } function callback () { t.equal(this, callback, 'calling context is same') } }) })