// Copyright (C) 2018 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import {dingus} from 'dingusjs'; import {Actions, DeferredAction} from '../common/actions'; import {NullAnalytics} from './analytics'; import {Router} from './router'; const mockComponent = { view() {} }; const fakeDispatch = () => {}; const mockLogging = new NullAnalytics(); beforeEach(() => { window.onhashchange = null; window.location.hash = ''; }); test('Default route must be defined', () => { expect( () => new Router('/a', {'/b': mockComponent}, fakeDispatch, mockLogging)) .toThrow(); }); test('Resolves empty route to default component', () => { const router = new Router('/a', {'/a': mockComponent}, fakeDispatch, mockLogging); expect(router.resolve('')).toBe(mockComponent); expect(router.resolve(null)).toBe(mockComponent); }); test('Parse route from hash', () => { const router = new Router('/', {'/': mockComponent}, fakeDispatch, mockLogging); window.location.hash = '#!/foobar?s=42'; expect(router.getRouteFromHash()).toBe('/foobar'); window.location.hash = '/foobar'; // Invalid prefix. expect(router.getRouteFromHash()).toBe(''); }); test('Set valid route on hash', () => { const dispatch = dingus<(a: DeferredAction) => void>(); const router = new Router( '/', { '/': mockComponent, '/a': mockComponent, }, dispatch, mockLogging); const prevHistoryLength = window.history.length; router.setRouteOnHash('/a'); expect(window.location.hash).toBe('#!/a'); expect(window.history.length).toBe(prevHistoryLength + 1); // No navigation action should be dispatched. expect(dispatch.calls.length).toBe(0); }); test('Redirects to default for invalid route in setRouteOnHash ', () => { const dispatch = dingus<(a: DeferredAction) => void>(); // const dispatch = () => {console.log("action received")}; const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging); router.setRouteOnHash('foo'); expect(dispatch.calls.length).toBe(1); expect(dispatch.calls[0][1].length).toBeGreaterThanOrEqual(1); expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/'})); }); test('Navigate on hash change', done => { const mockDispatch = (a: DeferredAction) => { expect(a).toEqual(Actions.navigate({route: '/viewer'})); done(); }; new Router( '/', { '/': mockComponent, '/viewer': mockComponent, }, mockDispatch, mockLogging); window.location.hash = '#!/viewer'; }); test('Redirects to default when invalid route set in window location', done => { const mockDispatch = (a: DeferredAction) => { expect(a).toEqual(Actions.navigate({route: '/'})); done(); }; new Router( '/', { '/': mockComponent, '/viewer': mockComponent, }, mockDispatch, mockLogging); window.location.hash = '#invalid'; }); test('navigateToCurrentHash with valid current route', () => { const dispatch = dingus<(a: DeferredAction) => void>(); window.location.hash = '#!/b'; const router = new Router( '/', {'/': mockComponent, '/b': mockComponent}, dispatch, mockLogging); router.navigateToCurrentHash(); expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/b'})); }); test('navigateToCurrentHash with invalid current route', () => { const dispatch = dingus<(a: DeferredAction) => void>(); window.location.hash = '#!/invalid'; const router = new Router('/', {'/': mockComponent}, dispatch, mockLogging); router.navigateToCurrentHash(); expect(dispatch.calls[0][1][0]).toEqual(Actions.navigate({route: '/'})); }); test('Params parsing', () => { window.location.hash = '#!/foo?a=123&b=42&c=a?b?c'; expect(Router.param('a')).toBe('123'); expect(Router.param('b')).toBe('42'); expect(Router.param('c')).toBe('a?b?c'); });