import { mount } from '@vue/test-utils'; import { createRouter, createWebHistory } from '@ionic/vue-router'; import { IonicVue, IonApp, IonRouterOutlet, IonPage, IonTabs, IonTabBar, IonTabButton, IonLabel } from '@ionic/vue'; import { onBeforeRouteLeave } from 'vue-router'; import { waitForRouter } from './utils'; const App = { components: { IonApp, IonRouterOutlet }, template: '', } const BasePage = { template: '', components: { IonPage }, } describe('Routing', () => { beforeAll(() => { (HTMLElement.prototype as HTMLIonRouterOutletElement).commit = jest.fn(); }); it('should pass no props', async () => { const Page1 = { ...BasePage, props: { title: { type: String, default: 'Default Title' } } }; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/', component: Page1 } ] }); router.push('/'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); const cmp = wrapper.findComponent(Page1); expect(cmp.props()).toEqual({ title: 'Default Title' }); }); it('should pass route props as an object', async () => { const Page1 = { ...BasePage, props: { title: { type: String, default: 'Default Title' } } }; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/', component: Page1, props: { title: 'Page 1 Title' } } ] }); router.push('/'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); const cmp = wrapper.findComponent(Page1); expect(cmp.props()).toEqual({ title: 'Page 1 Title' }); }); it('should pass route props as a function', async () => { const Page1 = { ...BasePage, props: { title: { type: String, default: 'Default Title' } } }; const propsFn = jest.fn((route) => { return { title: `${route.params.id} Title` } }); const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/myPath/:id', component: Page1, props: propsFn }, { path: '/otherPage', component: Page1 } ] }); router.push('/myPath/123'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); const cmp = wrapper.findComponent(Page1); expect(cmp.props()).toEqual({ title: '123 Title' }); router.push('/otherPage'); await waitForRouter(); expect(propsFn.mock.calls.length).toBe(1); router.back(); await waitForRouter(); expect(propsFn.mock.calls.length).toBe(1); expect(cmp.props()).toEqual({ title: '123 Title' }); }); it('should pass route params as props', async () => { const Page1 = { ...BasePage, props: { title: { type: String, default: 'Default Title' } } }; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/:title', component: Page1, props: true } ] }); router.push('/myPath'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); const cmp = wrapper.findComponent(Page1); expect(cmp.props()).toEqual({ title: 'myPath' }); }); it('should call vue router hooks properly', async () => { const leaveHook = jest.fn(); const Page1 = { ...BasePage, setup() { onBeforeRouteLeave(leaveHook); } }; const Page2 = { ...BasePage }; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/', component: Page1 }, { path: '/page2', component: Page2 } ] }); router.push('/'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); // Navigate to 2nd page router.push('/page2'); await waitForRouter(); expect(leaveHook).toBeCalled(); }); // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22492 it('should show correct view when replacing', async () => { const Tabs = { components: { IonPage, IonTabs, IonTabBar, IonTabButton, IonLabel }, template: ` Tab 1 Tab 2 `, } const Tab1 = { components: { IonPage }, template: `Tab 1` } const Tab2 = { components: { IonPage }, template: `Tab 2` } const Parent = { ...BasePage, template: `Parent Page` } const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes: [ { path: '/', redirect: '/tabs/tab1' }, { path: '/parent', component: Parent }, { path: '/tabs/', component: Tabs, children: [ { path: '/', redirect: 'tab1' }, { path: 'tab1', component: Tab1 }, { path: 'tab2', component: Tab2 } ]} ] }); router.push('/'); await router.isReady(); const wrapper = mount(App, { global: { plugins: [router, IonicVue] } }); // Go to Tab 2 const tabButtons = wrapper.findAllComponents(IonTabButton); tabButtons[1].trigger('click'); await waitForRouter(); expect(wrapper.findComponent(Tab2).exists()).toBe(true); expect(wrapper.findComponent(Parent).exists()).toBe(false); router.replace('/parent') await waitForRouter(); expect(wrapper.findComponent(Parent).exists()).toBe(true); expect(wrapper.findComponent(Tabs).exists()).toBe(false); router.replace('/tabs/tab1'); await waitForRouter(); expect(wrapper.findComponent(Parent).exists()).toBe(false); expect(wrapper.findComponent(Tab1).exists()).toBe(true); expect(wrapper.findComponent(Tab2).exists()).toBe(false); }); });