|  | // 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'); | 
|  | }); |