UNPKG

cycle-router

Version:
305 lines (257 loc) 8.76 kB
/* global describe, it */ /*eslint max-nested-callbacks: 0*/ import assert from 'assert' import Rx from 'rx' import {run} from '@cycle/core' import {makeRouterDriver} from '../src' function filterPush(location) { return location.action === 'PUSH' || location.action === 'REPLACE' } function runApp(path = '/') { function app() { return { router: Rx.Observable.just(path), } } return run(app, {router: makeRouterDriver()}) } describe('Cycle Router', () => { describe('makeRouterDriver', () => { it('should return a function', done => { const routerDriver = makeRouterDriver() assert.strictEqual(typeof routerDriver, 'function') done() }) }) describe('Routing', () => { it('should have an observable path', done => { const {sources} = runApp() sources.router.observable.subscribe(({pathname}) => { assert.strictEqual(pathname, '/') done() }) }) describe('path()', () => { it('should match a root path', done => { const {sources} = runApp() sources.router.path('/').observable .subscribe(({pathname}) => { assert.strictEqual(pathname, '/') done() }) }) it('should match a basic path', done => { const {sources} = runApp('/path') sources.router.path('/path').observable.filter(filterPush) .subscribe(({pathname}) => { assert.strictEqual(pathname, '/path') done() }) }) it('should match a deeply nested path', done => { const {sources} = runApp('/some/really/deep/nested/path') sources.router.path('/some/really/deep/nested/path').observable .filter(filterPush).subscribe(({pathname}) => { assert.strictEqual(pathname, '/some/really/deep/nested/path') done() }) }) it('should filter out unmatched paths', done => { const {sources} = runApp('/correct/path') sources.router.path('/wrong/path').observable.subscribe(assert.fail) sources.router.path('/correct/path').observable .filter(filterPush).subscribe(({pathname}) => { assert.strictEqual(pathname, '/correct/path') done() }) }) it('should allow matching paths using path().path()', done => { const {sources} = runApp('/correct/path') sources.router.path('/wrong').path('/path') .observable.filter(filterPush).subscribe(assert.fail) sources.router.path('/correct').path('/path') .observable.filter(filterPush).subscribe(({pathname}) => { assert.strictEqual(pathname, '/correct/path') done() }) }) it('should match a deeply nested path using multiple .path()s', done => { const {sources} = runApp('/some/really/deep/nested/path') sources.router.path('/some').path('/really/').path('/deep') .path('nested').path('/path').observable.filter(filterPush) .subscribe(({pathname}) => { assert.strictEqual(pathname, '/some/really/deep/nested/path') done() }) }) it('should match partials', done => { const {sources} = runApp('/some/really/deep/nested/path') sources.router.path('/some').path('/really').observable .filter(filterPush).subscribe(({pathname}) => { assert.strictEqual(pathname, '/some/really/deep/nested/path') done() }) }) }) describe('define()', () => { it('should have routeDefinitions object', done => { const {sources} = runApp() sources.router.define({ '/': 123, '/path': 234, }).subscribe(({routeDefinitions}) => { assert.notStrictEqual(routeDefinitions, null) assert.strictEqual(typeof routeDefinitions, 'object') done() }) }) it('should have the fullPath navigated to', done => { const {sources} = runApp('/some/really/deep/nested/path') sources.router.path('/some').path('really/').path('deep') .define({ '/nested': { '/path': 123, }, }).subscribe(({path, value, fullPath}) => { assert.strictEqual(path, '/nested/path') assert.strictEqual(value, 123) assert.strictEqual(fullPath, '/some/really/deep/nested/path') done() }) }) it('should match a root path', done => { const {sources} = runApp() sources.router.define({ '/': 123, '/path': 345, }).subscribe(({path, value}) => { assert.strictEqual(path, '/') assert.strictEqual(value, 123) done() }) }) it('should match a basic path', done => { const {sources} = runApp('/path') sources.router.define({ '/': 123, '/path': 345, }).subscribe(({path, value}) => { assert.strictEqual(path, '/path') assert.strictEqual(value, 345) done() }) }) it('should match a basic nested path', done => { const {sources} = runApp('/correct/path') sources.router.define({ '/': 123, '/path': 345, '/correct/path': 100, }).subscribe(({path, value}) => { assert.strictEqual(path, '/correct/path') assert.strictEqual(value, 100) done() }) }) it('should match a complex nested path', done => { const {sources} = runApp('/deep/nested/path') sources.router.define({ '/': 123, '/path': 345, '/deep': { '/nested': { '/path': 1000, }, }, }).subscribe(({path, value}) => { assert.strictEqual(path, '/deep/nested/path') assert.strictEqual(value, 1000) done() }) }) it('should match a path with a named parameter', done => { const {sources} = runApp('/user/123') sources.router.define({ '/': 'wrong!', '/user/:id': id => `${id}`, }).subscribe(({path, value}) => { assert.strictEqual(path, '/user/123') assert.strictEqual(value, '123') done() }) }) it('should allow .path().define()', done => { const {sources} = runApp('/some/path') sources.router.path('/some').define({ '/path': 123, }).subscribe(({path, value}) => { assert.strictEqual(path, '/path') assert.strictEqual(value, 123) done() }) }) it('should allow multiple .path()s and define', done => { const {sources} = runApp('/some/really/deep/nested/path') sources.router.path('/some').path('really/').path('deep') .define({ '/nested': { '/path': 123, }, }).subscribe(({path, value}) => { assert.strictEqual(path, '/nested/path') assert.strictEqual(value, 123) done() }) }) }) }) describe('State', () => { it('should allow saving state with rackt/history', done => { const {sources} = runApp({ pathname: '/path', state: {something: 'stateful'}, }) sources.router.observable.filter(filterPush).subscribe(({state}) => { assert.strictEqual(state.something, 'stateful') done() }) }) it('should allow for passing props with .path()', done => { function Component(router) { return router.define({ '/path': 'My favorite hex color: ', }).flatMap(({value, props$}) => { return props$.map((props) => { return `${value}${props.color}` }) }) } function app({router}) { const props$ = Rx.Observable.just({color: '#000000'}) const component$ = Component(router.path('/some', props$)) return { router: Rx.Observable.just('/some/path'), component$, } } const {sinks} = run(app, {router: makeRouterDriver()}) sinks.component$.subscribe((string) => { assert.strictEqual(string, 'My favorite hex color: #000000') done() }) }) it('should allow accessing set state via state$', done => { const {sources} = runApp({ pathname: '/path', state: {something: 'stateful'}, }) sources.router.history$.subscribe(({state}) => { console.log(state) assert.strictEqual(state.something, 'stateful') done() }) }) }) })