mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 09:34:19 +08:00
feat(vue): extend useIonRouter hook for programmatic navigation with animation control (#23499)
resolves #23450
This commit is contained in:
@ -32,6 +32,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
|
||||
* [Tabs Config](#tabs-config)
|
||||
* [Tabs Router Outlet](#tabs-router-outlet)
|
||||
* [Overlay Events](#overlay-events)
|
||||
* [Utility Function Types](#utility-function-types)
|
||||
- [Browser and Platform Support](#browser-and-platform-support)
|
||||
|
||||
|
||||
@ -309,6 +310,12 @@ This applies to the following components: `ion-action-sheet`, `ion-alert`, `ion-
|
||||
</ion-modal>
|
||||
```
|
||||
|
||||
#### Utility Function Types
|
||||
|
||||
- The `IonRouter` type for `useIonRouter` has been renamed to `UseIonRouterResult`.
|
||||
|
||||
- The `IonKeyboardRef` type for `useKeyboard` has been renamed to `UseKeyboardResult`.
|
||||
|
||||
|
||||
### Browser and Platform Support
|
||||
|
||||
|
@ -2,7 +2,8 @@ import {
|
||||
parseQuery,
|
||||
Router,
|
||||
RouteLocationNormalized,
|
||||
NavigationFailure
|
||||
NavigationFailure,
|
||||
RouteLocationRaw
|
||||
} from 'vue-router';
|
||||
import { createLocationHistory } from './locationHistory';
|
||||
import { generateId } from './utils';
|
||||
@ -115,13 +116,8 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
}
|
||||
}
|
||||
|
||||
const handleNavigate = (path: string, routerAction?: RouteAction, routerDirection?: RouteDirection, routerAnimation?: AnimationBuilder, tab?: string) => {
|
||||
incomingRouteParams = {
|
||||
routerAction,
|
||||
routerDirection,
|
||||
routerAnimation,
|
||||
tab
|
||||
}
|
||||
const handleNavigate = (path: RouteLocationRaw, routerAction?: RouteAction, routerDirection?: RouteDirection, routerAnimation?: AnimationBuilder, tab?: string) => {
|
||||
setIncomingRouteParams(routerAction, routerDirection, routerAnimation, tab);
|
||||
|
||||
if (routerAction === 'push') {
|
||||
router.push(path);
|
||||
@ -247,11 +243,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
const navigate = (navigationOptions: ExternalNavigationOptions) => {
|
||||
const { routerAnimation, routerDirection, routerLink } = navigationOptions;
|
||||
|
||||
incomingRouteParams = {
|
||||
routerAnimation,
|
||||
routerDirection: routerDirection || 'forward',
|
||||
routerAction: 'push'
|
||||
}
|
||||
setIncomingRouteParams('push', routerDirection, routerAnimation);
|
||||
|
||||
router.push(routerLink);
|
||||
}
|
||||
@ -313,7 +305,26 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
historyChangeListeners.push(cb);
|
||||
}
|
||||
|
||||
const setIncomingRouteParams = (routerAction: RouteAction = 'push', routerDirection: RouteDirection = 'forward', routerAnimation?: AnimationBuilder, tab?: string) => {
|
||||
incomingRouteParams = {
|
||||
routerAction,
|
||||
routerDirection,
|
||||
routerAnimation,
|
||||
tab
|
||||
};
|
||||
}
|
||||
|
||||
const goBack = (routerAnimation?: AnimationBuilder) => {
|
||||
setIncomingRouteParams('pop', 'back', routerAnimation);
|
||||
router.back()
|
||||
};
|
||||
const goForward = (routerAnimation?: AnimationBuilder) => {
|
||||
setIncomingRouteParams('push', 'forward', routerAnimation);
|
||||
router.forward();
|
||||
}
|
||||
|
||||
return {
|
||||
handleNavigate,
|
||||
handleNavigateBack,
|
||||
handleSetCurrentTab,
|
||||
getCurrentRouteInfo,
|
||||
@ -321,6 +332,8 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
navigate,
|
||||
resetTab,
|
||||
changeTab,
|
||||
registerHistoryChangeListener
|
||||
registerHistoryChangeListener,
|
||||
goBack,
|
||||
goForward
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ export interface ExternalNavigationOptions {
|
||||
routerLink: string;
|
||||
routerDirection?: RouteDirection;
|
||||
routerAnimation?: AnimationBuilder;
|
||||
routerAction?: RouteAction;
|
||||
}
|
||||
|
||||
export interface NavigationInformation {
|
||||
|
@ -1,106 +0,0 @@
|
||||
import { BackButtonEvent } from '@ionic/core/components';
|
||||
import {
|
||||
inject,
|
||||
ref,
|
||||
Ref,
|
||||
ComponentInternalInstance,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import { LifecycleHooks } from './utils';
|
||||
|
||||
type Handler = (processNextHandler: () => void) => Promise<any> | void | null;
|
||||
|
||||
export interface IonRouter {
|
||||
canGoBack: (deep?: number) => boolean;
|
||||
}
|
||||
|
||||
export interface IonKeyboardRef {
|
||||
isOpen: Ref<boolean>;
|
||||
keyboardHeight: Ref<number>;
|
||||
unregister: () => void
|
||||
}
|
||||
|
||||
export const useBackButton = (priority: number, handler: Handler) => {
|
||||
const callback = (ev: BackButtonEvent) => ev.detail.register(priority, handler);
|
||||
const unregister = () => document.removeEventListener('ionBackButton', callback);
|
||||
|
||||
document.addEventListener('ionBackButton', callback);
|
||||
|
||||
return { unregister };
|
||||
}
|
||||
|
||||
export const useIonRouter = (): IonRouter => {
|
||||
const { canGoBack } = inject('navManager') as any;
|
||||
|
||||
return {
|
||||
canGoBack
|
||||
} as IonRouter
|
||||
}
|
||||
|
||||
export const useKeyboard = (): IonKeyboardRef => {
|
||||
let isOpen = ref(false);
|
||||
let keyboardHeight = ref(0);
|
||||
|
||||
const showCallback = (ev: CustomEvent) => {
|
||||
isOpen.value = true;
|
||||
keyboardHeight.value = ev.detail.keyboardHeight;
|
||||
}
|
||||
|
||||
const hideCallback = () => {
|
||||
isOpen.value = false;
|
||||
keyboardHeight.value = 0;
|
||||
}
|
||||
|
||||
const unregister = () => {
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
window.removeEventListener('ionKeyboardDidShow', showCallback);
|
||||
window.removeEventListener('ionKeyboardDidHide', hideCallback);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
window.addEventListener('ionKeyboardDidShow', showCallback);
|
||||
window.addEventListener('ionKeyboardDidHide', hideCallback);
|
||||
}
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
keyboardHeight,
|
||||
unregister
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an returns a function that
|
||||
* can be used to provide a lifecycle hook.
|
||||
*/
|
||||
const injectHook = (lifecycleType: LifecycleHooks, hook: Function, component: ComponentInternalInstance | null): Function | undefined => {
|
||||
if (component) {
|
||||
|
||||
// Add to public instance so it is accessible to IonRouterOutlet
|
||||
const target = component as any;
|
||||
const hooks = target.proxy[lifecycleType] || (target.proxy[lifecycleType] = []);
|
||||
const wrappedHook = (...args: unknown[]) => {
|
||||
if (target.isUnmounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
return args ? hook(...args) : hook();
|
||||
};
|
||||
|
||||
hooks.push(wrappedHook);
|
||||
|
||||
return wrappedHook;
|
||||
} else {
|
||||
console.warn('[@ionic/vue]: Ionic Lifecycle Hooks can only be used during execution of setup().');
|
||||
}
|
||||
}
|
||||
|
||||
const createHook = <T extends Function = () => any>(lifecycle: LifecycleHooks) => {
|
||||
return (hook: T, target: ComponentInternalInstance | null = getCurrentInstance()) => injectHook(lifecycle, hook, target);
|
||||
}
|
||||
|
||||
export const onIonViewWillEnter = createHook(LifecycleHooks.WillEnter);
|
||||
export const onIonViewDidEnter = createHook(LifecycleHooks.DidEnter);
|
||||
export const onIonViewWillLeave = createHook(LifecycleHooks.WillLeave);
|
||||
export const onIonViewDidLeave = createHook(LifecycleHooks.DidLeave);
|
15
packages/vue/src/hooks/back-button.ts
Normal file
15
packages/vue/src/hooks/back-button.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { BackButtonEvent } from '@ionic/core/components';
|
||||
|
||||
type Handler = (processNextHandler: () => void) => Promise<any> | void | null;
|
||||
export interface UseBackButtonResult {
|
||||
unregister: () => void;
|
||||
}
|
||||
|
||||
export const useBackButton = (priority: number, handler: Handler): UseBackButtonResult => {
|
||||
const callback = (ev: BackButtonEvent) => ev.detail.register(priority, handler);
|
||||
const unregister = () => document.removeEventListener('ionBackButton', callback);
|
||||
|
||||
document.addEventListener('ionBackButton', callback);
|
||||
|
||||
return { unregister };
|
||||
}
|
40
packages/vue/src/hooks/keyboard.ts
Normal file
40
packages/vue/src/hooks/keyboard.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { ref, Ref } from 'vue';
|
||||
|
||||
export interface UseKeyboardResult {
|
||||
isOpen: Ref<boolean>;
|
||||
keyboardHeight: Ref<number>;
|
||||
unregister: () => void
|
||||
}
|
||||
|
||||
export const useKeyboard = (): UseKeyboardResult => {
|
||||
let isOpen = ref(false);
|
||||
let keyboardHeight = ref(0);
|
||||
|
||||
const showCallback = (ev: CustomEvent) => {
|
||||
isOpen.value = true;
|
||||
keyboardHeight.value = ev.detail.keyboardHeight;
|
||||
}
|
||||
|
||||
const hideCallback = () => {
|
||||
isOpen.value = false;
|
||||
keyboardHeight.value = 0;
|
||||
}
|
||||
|
||||
const unregister = () => {
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
window.removeEventListener('ionKeyboardDidShow', showCallback);
|
||||
window.removeEventListener('ionKeyboardDidHide', hideCallback);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
window.addEventListener('ionKeyboardDidShow', showCallback);
|
||||
window.addEventListener('ionKeyboardDidHide', hideCallback);
|
||||
}
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
keyboardHeight,
|
||||
unregister
|
||||
}
|
||||
}
|
37
packages/vue/src/hooks/lifecycle.ts
Normal file
37
packages/vue/src/hooks/lifecycle.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { LifecycleHooks } from '../utils';
|
||||
import { ComponentInternalInstance, getCurrentInstance } from 'vue';
|
||||
|
||||
/**
|
||||
* Creates an returns a function that
|
||||
* can be used to provide a lifecycle hook.
|
||||
*/
|
||||
const injectHook = (lifecycleType: LifecycleHooks, hook: Function, component: ComponentInternalInstance | null): Function | undefined => {
|
||||
if (component) {
|
||||
|
||||
// Add to public instance so it is accessible to IonRouterOutlet
|
||||
const target = component as any;
|
||||
const hooks = target.proxy[lifecycleType] || (target.proxy[lifecycleType] = []);
|
||||
const wrappedHook = (...args: unknown[]) => {
|
||||
if (target.isUnmounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
return args ? hook(...args) : hook();
|
||||
};
|
||||
|
||||
hooks.push(wrappedHook);
|
||||
|
||||
return wrappedHook;
|
||||
} else {
|
||||
console.warn('[@ionic/vue]: Ionic Lifecycle Hooks can only be used during execution of setup().');
|
||||
}
|
||||
}
|
||||
|
||||
const createHook = <T extends Function = () => any>(lifecycle: LifecycleHooks) => {
|
||||
return (hook: T, target: ComponentInternalInstance | null = getCurrentInstance()) => injectHook(lifecycle, hook, target);
|
||||
}
|
||||
|
||||
export const onIonViewWillEnter = createHook(LifecycleHooks.WillEnter);
|
||||
export const onIonViewDidEnter = createHook(LifecycleHooks.DidEnter);
|
||||
export const onIonViewWillLeave = createHook(LifecycleHooks.WillLeave);
|
||||
export const onIonViewDidLeave = createHook(LifecycleHooks.DidLeave);
|
69
packages/vue/src/hooks/router.ts
Normal file
69
packages/vue/src/hooks/router.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { inject } from 'vue';
|
||||
import { AnimationBuilder } from '../';
|
||||
|
||||
export type RouteAction = 'push' | 'pop' | 'replace';
|
||||
export type RouteDirection = 'forward' | 'back' | 'root' | 'none';
|
||||
|
||||
export interface UseIonRouterResult {
|
||||
|
||||
/**
|
||||
* The location parameter is really of type 'RouteLocationRaw'
|
||||
* imported from vue-router, but the @ionic/vue package should
|
||||
* not have a hard dependency on vue-router, so we just use 'any'.
|
||||
*/
|
||||
canGoBack: (deep?: number) => boolean;
|
||||
push: (location: any, routerAnimation?: AnimationBuilder) => void;
|
||||
replace: (location: any, routerAnimation?: AnimationBuilder) => void;
|
||||
back: (routerAnimation?: AnimationBuilder) => void;
|
||||
forward: (routerAnimation?: AnimationBuilder) => void;
|
||||
navigate: (
|
||||
location: any,
|
||||
routerDirection?: RouteDirection,
|
||||
routerAction?: RouteAction,
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to navigate within Vue Router
|
||||
* while controlling the animation.
|
||||
*/
|
||||
export const useIonRouter = (): UseIonRouterResult => {
|
||||
const { canGoBack, goBack, goForward, handleNavigate } = inject('navManager') as any;
|
||||
|
||||
const navigate = (
|
||||
location: any,
|
||||
routerDirection?: RouteDirection,
|
||||
routerAction?: RouteAction,
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => handleNavigate(location, routerAction, routerDirection, routerAnimation);
|
||||
|
||||
const push = (
|
||||
location: any,
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => navigate(location, 'forward', 'push', routerAnimation);
|
||||
|
||||
const replace = (
|
||||
location: any,
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => navigate(location, 'root', 'replace', routerAnimation);
|
||||
|
||||
const back = (
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => goBack(routerAnimation);
|
||||
|
||||
const forward = (
|
||||
routerAnimation?: AnimationBuilder
|
||||
) => goForward(routerAnimation);
|
||||
|
||||
return {
|
||||
canGoBack,
|
||||
push,
|
||||
replace,
|
||||
back,
|
||||
forward,
|
||||
navigate
|
||||
} as UseIonRouterResult
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,12 @@ import { addIcons } from 'ionicons';
|
||||
import { arrowBackSharp, caretBackSharp, chevronBack, chevronDown, chevronForward, close, closeCircle, closeSharp, menuOutline, menuSharp, reorderThreeOutline, reorderTwoSharp, searchOutline, searchSharp } from 'ionicons/icons';
|
||||
|
||||
export * from './proxies';
|
||||
|
||||
export { UseBackButtonResult, useBackButton } from './hooks/back-button';
|
||||
export { UseKeyboardResult, useKeyboard } from './hooks/keyboard';
|
||||
export { onIonViewWillEnter, onIonViewDidEnter, onIonViewWillLeave, onIonViewDidLeave } from './hooks/lifecycle';
|
||||
export { UseIonRouterResult, useIonRouter } from './hooks/router';
|
||||
|
||||
export { IonicVue } from './ionic-vue';
|
||||
|
||||
export { IonBackButton } from './components/IonBackButton';
|
||||
@ -18,18 +24,6 @@ export { IonModal } from './components/IonModal';
|
||||
|
||||
export * from './components/Overlays';
|
||||
|
||||
export {
|
||||
IonKeyboardRef,
|
||||
IonRouter,
|
||||
useBackButton,
|
||||
useIonRouter,
|
||||
useKeyboard,
|
||||
onIonViewWillEnter,
|
||||
onIonViewDidEnter,
|
||||
onIonViewWillLeave,
|
||||
onIonViewDidLeave
|
||||
} from './hooks';
|
||||
|
||||
export {
|
||||
modalController,
|
||||
popoverController,
|
||||
|
254
packages/vue/test-app/tests/unit/hooks.spec.ts
Normal file
254
packages/vue/test-app/tests/unit/hooks.spec.ts
Normal file
@ -0,0 +1,254 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { createRouter, createWebHistory } from '@ionic/vue-router';
|
||||
import { IonicVue, IonApp, IonRouterOutlet, IonPage, useIonRouter, createAnimation } from '@ionic/vue';
|
||||
import { waitForRouter } from './utils';
|
||||
|
||||
const App = {
|
||||
components: { IonApp, IonRouterOutlet },
|
||||
template: '<ion-app><ion-router-outlet /></ion-app>',
|
||||
}
|
||||
|
||||
const BasePage = {
|
||||
template: '<ion-page></ion-page>',
|
||||
components: { IonPage },
|
||||
}
|
||||
|
||||
describe('useIonRouter', () => {
|
||||
beforeAll(() => {
|
||||
(HTMLElement.prototype as HTMLIonRouterOutletElement).commit = jest.fn((entering, leaving, opts) => {
|
||||
if (opts && opts.animationBuilder) {
|
||||
opts.animationBuilder(entering, leaving);
|
||||
}
|
||||
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
});
|
||||
it('should correctly navigate back', async () => {
|
||||
const Page1 = {
|
||||
...BasePage
|
||||
};
|
||||
|
||||
const Page2 = {
|
||||
...BasePage,
|
||||
name: 'Page2',
|
||||
setup() {
|
||||
const ionRouter = useIonRouter();
|
||||
|
||||
return { ionRouter };
|
||||
}
|
||||
};
|
||||
|
||||
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]
|
||||
}
|
||||
});
|
||||
|
||||
router.push('/page2');
|
||||
await waitForRouter();
|
||||
|
||||
const cmp = wrapper.findComponent(Page2);
|
||||
const vm = cmp.vm as any;
|
||||
const animFn = jest.fn();
|
||||
|
||||
vm.ionRouter.back(animFn);
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/');
|
||||
expect(animFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should correctly navigate forward', async () => {
|
||||
const Page1 = {
|
||||
...BasePage
|
||||
};
|
||||
|
||||
const Page2 = {
|
||||
...BasePage,
|
||||
name: 'Page2',
|
||||
setup() {
|
||||
const ionRouter = useIonRouter();
|
||||
|
||||
return { ionRouter };
|
||||
}
|
||||
};
|
||||
|
||||
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]
|
||||
}
|
||||
});
|
||||
|
||||
router.push('/page2');
|
||||
await waitForRouter();
|
||||
|
||||
const cmp = wrapper.findComponent(Page2);
|
||||
const vm = cmp.vm as any;
|
||||
const animFn = jest.fn();
|
||||
|
||||
vm.ionRouter.back();
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/');
|
||||
|
||||
vm.ionRouter.forward(animFn);
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/page2');
|
||||
expect(animFn).toHaveBeenCalled();
|
||||
})
|
||||
|
||||
it('should correctly push a page', async () => {
|
||||
const Page1 = {
|
||||
...BasePage,
|
||||
name: 'Page1',
|
||||
setup() {
|
||||
const ionRouter = useIonRouter();
|
||||
|
||||
return { ionRouter };
|
||||
}
|
||||
};
|
||||
|
||||
const Page2 = {
|
||||
...BasePage,
|
||||
name: 'Page2',
|
||||
|
||||
};
|
||||
|
||||
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]
|
||||
}
|
||||
});
|
||||
|
||||
const cmp = wrapper.findComponent(Page1);
|
||||
const vm = cmp.vm as any;
|
||||
const animFn = jest.fn();
|
||||
|
||||
vm.ionRouter.push('/page2', animFn);
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/page2');
|
||||
expect(animFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should correctly replace a page', async () => {
|
||||
const Page1 = {
|
||||
...BasePage,
|
||||
name: 'Page1',
|
||||
setup() {
|
||||
const ionRouter = useIonRouter();
|
||||
|
||||
return { ionRouter };
|
||||
}
|
||||
};
|
||||
|
||||
const Page2 = {
|
||||
...BasePage,
|
||||
name: 'Page2',
|
||||
|
||||
};
|
||||
|
||||
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]
|
||||
}
|
||||
});
|
||||
|
||||
const cmp = wrapper.findComponent(Page1);
|
||||
const vm = cmp.vm as any;
|
||||
const animFn = jest.fn();
|
||||
|
||||
vm.ionRouter.replace('/page2', animFn);
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/page2');
|
||||
expect(animFn).toHaveBeenCalled();
|
||||
|
||||
expect(vm.ionRouter.canGoBack()).toEqual(false);
|
||||
})
|
||||
|
||||
it('should correctly navigate', async () => {
|
||||
const Page1 = {
|
||||
...BasePage,
|
||||
name: 'Page1',
|
||||
setup() {
|
||||
const ionRouter = useIonRouter();
|
||||
|
||||
return { ionRouter };
|
||||
}
|
||||
};
|
||||
|
||||
const Page2 = {
|
||||
...BasePage,
|
||||
name: 'Page2',
|
||||
|
||||
};
|
||||
|
||||
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]
|
||||
}
|
||||
});
|
||||
|
||||
const cmp = wrapper.findComponent(Page1);
|
||||
const vm = cmp.vm as any;
|
||||
const animFn = jest.fn();
|
||||
|
||||
vm.ionRouter.navigate('/page2', 'forward', 'push', animFn);
|
||||
await waitForRouter();
|
||||
|
||||
expect(router.currentRoute.value.path).toEqual('/page2');
|
||||
expect(animFn).toHaveBeenCalled();
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user