UNPKG

@relax.dev/router

Version:
272 lines (239 loc) 8.92 kB
/** * @jest-environment jsdom */ import { Router } from './Router'; import { Page } from './Page'; import { Route } from './Route'; import { dangerousResetGlobalRouterUseForTestOnly } from '../methods'; import { HistoryUpdateType, RouterGenericBase } from './Types'; type PanelIdType = 'panel_main' | 'user' | 'info' | 'done' | 'main' | 'create'; type ViewIdType = 'main' | 'create'; type PageIdType = '/' | '/user' | '/info' | '/done' | '/create' | '/product'; interface RouterTypes extends RouterGenericBase { panelId: PanelIdType; viewId: ViewIdType; pageId: PageIdType; } function delay(time = 100) { return new Promise((resolve) => setTimeout(resolve, time)); } test('route basic usage', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>( { '/': new Page<RouterTypes>(), '/user': new Page<RouterTypes>('user'), '/info': new Page<RouterTypes>('info'), }, null ); const recordEvents: Array<{ newRoute: Route; oldRoute: Route | undefined; isNewRoute: boolean; type: HistoryUpdateType; }> = []; r.on('update', (newRoute, oldRoute, isNewRoute, type) => { recordEvents.push({ newRoute, oldRoute, isNewRoute, type }); }); r.start(); expect(r.history.getCurrentIndex()).toBe(0); r.pushPage('/user'); expect(r.history.getCurrentIndex()).toBe(1); await delay(10); r.pushPage('/info'); expect(r.history.getCurrentIndex()).toBe(2); await delay(10); r.popPage(); await delay(10); expect(r.history.getCurrentIndex()).toBe(1); r.replacePage('/info'); await delay(10); expect(r.history.getCurrentIndex()).toBe(1); setTimeout(() => { // одно событие update приходит после старта роутера expect(recordEvents.length).toBe(4 + 1); expect(recordEvents[0].isNewRoute).toBeTruthy(); expect(recordEvents[1].isNewRoute).toBeTruthy(); expect(recordEvents[2].isNewRoute).toBeTruthy(); expect(recordEvents[3].isNewRoute).toBeFalsy(); expect(recordEvents[4].isNewRoute).toBeTruthy(); done(); r.stop(); }, 10); }); test('route first page push', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>( { '/': new Page<RouterTypes>(), '/user': new Page<RouterTypes>('user'), '/info': new Page<RouterTypes>('info'), }, null ); r.start(); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(true); // После старта страница всегда first r.pushPage('/info'); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(false); // После push страница всегда не будет first r.popPage(); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(true); // Вернулись назад на первую страницу, она была и осталась first r.stop(); done(); }); test('route first page replace', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>( { '/': new Page<RouterTypes>(), '/user': new Page<RouterTypes>('user'), '/info': new Page<RouterTypes>('info'), }, null ); r.start(); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(true); // После старта страница всегда first r.replacePage('/info'); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(true); // Мы заменили first страницу на какую-то другу, она осталась first r.pushPage('/user'); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(false); // Был push страница уже не first r.popPage(); await delay(100); expect(r.getCurrentLocation().isFirstPage()).toBe(true); // Вернулись обратно на first страницу r.stop(); done(); }); test('check history', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>( { '/': new Page<RouterTypes>('main', 'main'), '/user': new Page<RouterTypes>('user', 'main'), '/info': new Page<RouterTypes>('info', 'main'), '/create': new Page<RouterTypes>('create', 'create'), '/done': new Page('done', 'create'), }, null ); r.start(); expect(r.getCurrentLocation().getViewHistory('main')).toEqual(['main']); expect(r.getCurrentLocation().getPanelId()).toBe('main'); expect(r.getCurrentLocation().getViewId()).toBe('main'); r.pushPage('/user'); expect(r.getCurrentLocation().getViewHistory('main')).toEqual(['main', 'user']); expect(r.getCurrentLocation().getPanelId()).toBe('user'); expect(r.getCurrentLocation().getViewId()).toBe('main'); r.pushPage('/info'); expect(r.getCurrentLocation().getViewHistory('main')).toEqual(['main', 'user', 'info']); expect(r.getCurrentLocation().getPanelId()).toBe('info'); expect(r.getCurrentLocation().getViewId()).toBe('main'); r.pushPage('/create'); expect(r.getCurrentLocation().getViewHistory('main')).toEqual(['info']); expect(r.getCurrentLocation().getViewHistory('create')).toEqual(['create']); expect(r.getCurrentLocation().getPanelId()).toBe('create'); expect(r.getCurrentLocation().getViewId()).toBe('create'); r.pushPage('/done'); expect(r.getCurrentLocation().getViewHistory('create')).toEqual(['create', 'done']); expect(r.getCurrentLocation().getViewHistory('main')).toEqual(['info']); expect(r.getCurrentLocation().getPanelId()).toBe('done'); expect(r.getCurrentLocation().getViewId()).toBe('create'); expect(r.getCurrentLocation().getLastPanelInView('main')).toBe('info'); r.popPage(); await delay(100); expect(r.getCurrentLocation().getViewHistory('create')).toEqual(['create']); expect(r.getCurrentLocation().getLastPanelInView('main')).toBe('info'); r.stop(); done(); }); test('route preventSameLocationChange', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>( { '/': new Page(), '/user': new Page('user'), '/info': new Page<RouterTypes>('info'), }, { preventSameLocationChange: true } ); r.start(); expect(r.history.getCurrentIndex()).toBe(0); r.pushPage('/user'); expect(r.history.getCurrentIndex()).toBe(1); await delay(10); // Пушим точно такую же страницу, ничего не должно произойти let wasUpdates = false; r.once('update', () => (wasUpdates = true)); r.pushPage('/user'); expect(r.history.getCurrentIndex()).toBe(1); expect(wasUpdates).toBe(false); done(); }); test('fixBrokenHistory', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router({ '/': new Page(), '/user': new Page('user'), '/product': new Page<RouterTypes>('panel_main'), }); r.start(); r.pushPage('/user'); r.pushPage('/product'); // Эмитируем открытие м закрытие левого приложения window.history.pushState(null, 'OTHER PAGE OPEN', '#PAGE OPEN'); r.fixBrokenHistory(); expect(r.getCurrentLocation().getPageId()).toBe('/product'); r.popPage(); await r.afterUpdate(); expect(r.getCurrentLocation().getPageId()).toBe('/user'); done(); }); test('popPageToAndReplace', async (done) => { dangerousResetGlobalRouterUseForTestOnly(); const r = new Router<RouterTypes>({ '/': new Page<RouterTypes>(), '/user': new Page('user'), '/product': new Page<RouterTypes>('user'), '/done': new Page<RouterTypes>('done'), }); r.start(); r.pushPage('/user'); r.pushPage('/product'); // r.popPageToAndReplace(-2, '/done', {}); // await r.afterUpdate(); // expect(r.history.getCurrentIndex()).toBe(0); await done(); }); test('it should use certain parameter as hash', () => { dangerousResetGlobalRouterUseForTestOnly(); window.history.pushState(null, '', `http://localhost?app_hash=${btoa('user')}&hash=done#product`); const r = new Router<RouterTypes>({ '/': new Page<RouterTypes>(), '/user': new Page('user'), '/product': new Page<RouterTypes>('user'), '/done': new Page<RouterTypes>('done'), }); r.start('app_hash'); expect(r.getCurrentLocation().getPageId()).toBe('/user'); }); test('it should use modal id from query parameter', () => { dangerousResetGlobalRouterUseForTestOnly(); window.history.pushState( null, '', `http://localhost?app_hash=${btoa('?m=modal_features_intro&feature_key=museum_intro')}&hash=done#product` ); const r = new Router<RouterTypes>({ '/': new Page<RouterTypes>(), '/user': new Page('user'), '/product': new Page<RouterTypes>('user'), '/done': new Page<RouterTypes>('done'), }); r.start('app_hash'); expect(r.getCurrentLocation().getModalId()).toBe('modal_features_intro'); });