// 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 {PageManagerImpl} from './page_manager'; import {CORE_PLUGIN_ID} from './plugin_manager'; import {Router} from './router'; const mockComponent = { view() {}, }; describe('Router#resolve', () => { beforeEach(() => { window.location.hash = ''; }); const pluginId = CORE_PLUGIN_ID; const traceless = true; test('Resolves empty route to default component', () => { const pages = new PageManagerImpl(); pages.registerPage({route: '/', page: mockComponent, traceless, pluginId}); window.location.hash = ''; expect(pages.renderPageForCurrentRoute(undefined).tag).toBe(mockComponent); }); test('Resolves subpage route to component of main page', () => { const nonDefaultComponent = {view() {}}; const pages = new PageManagerImpl(); pages.registerPage({route: '/', page: mockComponent, traceless, pluginId}); pages.registerPage({ route: '/a', page: nonDefaultComponent, traceless, pluginId, }); window.location.hash = '#!/a/subpage'; expect(pages.renderPageForCurrentRoute(undefined).tag).toBe( nonDefaultComponent, ); expect(pages.renderPageForCurrentRoute(undefined).attrs.subpage).toBe( '/subpage', ); }); test('Pass empty subpage if not found in URL', () => { const nonDefaultComponent = {view() {}}; const pages = new PageManagerImpl(); pages.registerPage({route: '/', page: mockComponent, traceless, pluginId}); pages.registerPage({ route: '/a', page: nonDefaultComponent, traceless, pluginId, }); window.location.hash = '#!/a'; expect(pages.renderPageForCurrentRoute(undefined).tag).toBe( nonDefaultComponent, ); expect(pages.renderPageForCurrentRoute(undefined).attrs.subpage).toBe(''); }); }); describe('Router.parseUrl', () => { // Can parse arguments from the search string. test('Search parsing', () => { const url = 'http://localhost?p=123&s=42&url=a?b?c'; const route = Router.parseUrl(url); const args = route.args; expect(args.p).toBe('123'); expect(args.s).toBe('42'); expect(args.url).toBe('a?b?c'); expect(route.fragment).toBe(''); }); // Or from the fragment string. test('Fragment parsing', () => { const url = 'http://localhost/#!/foo?p=123&s=42&url=a?b?c'; const route = Router.parseUrl(url); const args = route.args; expect(args.p).toBe('123'); expect(args.s).toBe('42'); expect(args.url).toBe('a?b?c'); expect(route.fragment).toBe(''); }); // Or both in which case fragment overrides the search. test('Fragment parsing', () => { const url = 'http://localhost/?p=1&s=2&hideSidebar=true#!/foo?s=3&url=4&hideSidebar=false'; const route = Router.parseUrl(url); const args = route.args; expect(args.p).toBe('1'); expect(args.s).toBe('3'); expect(args.url).toBe('4'); expect(args.hideSidebar).toBe(false); expect(route.fragment).toBe(''); }); // + is also space test('plus is space query', () => { const url = 'http://localhost?query=(foo+%2B+bar),'; const route = Router.parseUrl(url); const args = route.args; expect(args.query).toBe('(foo + bar),'); }); // + is also space test('plus is space hash', () => { const url = 'http://localhost#!/foo?query=(foo+%2B+bar),'; const route = Router.parseUrl(url); const args = route.args; expect(args.query).toBe('(foo + bar),'); }); test('Nested fragment', () => { const url = 'http://localhost/?p=1&s=2&hideSidebar=true#!/foo?s=3&url=4&hideSidebar=false#myfragment'; const route = Router.parseUrl(url); expect(route.fragment).toBe('myfragment'); }); }); describe('Router.parseFragment', () => { test('empty route broken into empty components', () => { const {page, subpage, args} = Router.parseFragment(''); expect(page).toBe(''); expect(subpage).toBe(''); expect(args.mode).toBe(undefined); }); test('by default args are undefined', () => { // This prevents the url from becoming messy. const {args} = Router.parseFragment(''); expect(args).toEqual({}); }); test('invalid route broken into empty components', () => { const {page, subpage} = Router.parseFragment('/bla'); expect(page).toBe(''); expect(subpage).toBe(''); }); test('simple route has page defined', () => { const {page, subpage} = Router.parseFragment('#!/record'); expect(page).toBe('/record'); expect(subpage).toBe(''); }); test('simple route has both components defined', () => { const {page, subpage} = Router.parseFragment('#!/record/memory'); expect(page).toBe('/record'); expect(subpage).toBe('/memory'); }); test('route broken at first slash', () => { const {page, subpage} = Router.parseFragment('#!/record/memory/stuff'); expect(page).toBe('/record'); expect(subpage).toBe('/memory/stuff'); }); test('parameters separated from route', () => { const {page, subpage, args} = Router.parseFragment( '#!/record/memory?url=http://localhost:1234/aaaa', ); expect(page).toBe('/record'); expect(subpage).toBe('/memory'); expect(args.url).toEqual('http://localhost:1234/aaaa'); }); test('openFromAndroidBugTool can be false', () => { const {args} = Router.parseFragment('#!/?openFromAndroidBugTool=false'); expect(args.openFromAndroidBugTool).toEqual(false); }); test('openFromAndroidBugTool can be true', () => { const {args} = Router.parseFragment('#!/?openFromAndroidBugTool=true'); expect(args.openFromAndroidBugTool).toEqual(true); }); test('bad modes are coerced to default', () => { const {args} = Router.parseFragment('#!/?mode=1234'); expect(args.mode).toEqual(undefined); }); test('bad hideSidebar is coerced to default', () => { const {args} = Router.parseFragment('#!/?hideSidebar=helloworld!'); expect(args.hideSidebar).toEqual(undefined); }); });