From 31f9bc81d6d0fa81f9abe20172bb606651a2d75d Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 22 Oct 2020 11:03:58 -0400 Subject: [PATCH] fix(vue): improve compatibility with route guards (#22371) resolves #22344 --- packages/vue-router/src/router.ts | 16 +++++++++++----- packages/vue/test-app/src/guards/Delay.ts | 18 ++++++++++++++++++ packages/vue/test-app/src/router/index.ts | 13 +++++++++++-- packages/vue/test-app/src/views/Home.vue | 3 +++ .../vue/test-app/tests/e2e/specs/routing.js | 18 +++++++++++++++++- packages/vue/test-app/tests/e2e/specs/tabs.js | 9 +++++++++ 6 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 packages/vue/test-app/src/guards/Delay.ts diff --git a/packages/vue-router/src/router.ts b/packages/vue-router/src/router.ts index 603d35090e..b90160f515 100644 --- a/packages/vue-router/src/router.ts +++ b/packages/vue-router/src/router.ts @@ -1,7 +1,6 @@ import { Router, - RouteLocationNormalized, - NavigationGuardNext + RouteLocationNormalized } from 'vue-router'; import { createLocationHistory } from './locationHistory'; import { generateId } from './utils'; @@ -19,13 +18,20 @@ import { AnimationBuilder } from '@ionic/core'; export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) => { let currentNavigationInfo: NavigationInformation = { direction: undefined, action: undefined }; - router.beforeEach((to: RouteLocationNormalized, _: RouteLocationNormalized, next: NavigationGuardNext) => { + /** + * Ionic Vue should only react to navigation + * changes once they have been confirmed and should + * never affect the outcome of navigation (with the + * exception of going back or selecting a tab). + * As a result, we should do our work in afterEach + * which is fired once navigation is confirmed + * and any user guards have run. + */ + router.afterEach((to: RouteLocationNormalized, _: RouteLocationNormalized) => { const { direction, action } = currentNavigationInfo; handleHistoryChange(to, action, direction); currentNavigationInfo = { direction: undefined, action: undefined }; - - next(); }); const locationHistory = createLocationHistory(); diff --git a/packages/vue/test-app/src/guards/Delay.ts b/packages/vue/test-app/src/guards/Delay.ts new file mode 100644 index 0000000000..7183b14931 --- /dev/null +++ b/packages/vue/test-app/src/guards/Delay.ts @@ -0,0 +1,18 @@ +import { loadingController } from '@ionic/vue'; +import { + NavigationGuardNext, + RouteLocationNormalized +} from 'vue-router'; + +export const DelayGuard = async (_: RouteLocationNormalized, _x: RouteLocationNormalized, next: NavigationGuardNext) => { + const loading = await loadingController.create({ + message: 'Waiting 500ms...', + duration: 500 + }); + + await loading.present(); + + await loading.onDidDismiss(); + + next({ path: '/routing' }); +} diff --git a/packages/vue/test-app/src/router/index.ts b/packages/vue/test-app/src/router/index.ts index ed2e75556e..6035f8aff4 100644 --- a/packages/vue/test-app/src/router/index.ts +++ b/packages/vue/test-app/src/router/index.ts @@ -1,12 +1,18 @@ import { createRouter, createWebHistory } from '@ionic/vue-router'; import { RouteRecordRaw } from 'vue-router'; -import Home from '../views/Home.vue' +import Home from '@/views/Home.vue' +import { DelayGuard } from '@/guards/Delay'; const routes: Array = [ { path: '/', component: Home }, + { + path: '/delayed-redirect', + beforeEnter: DelayGuard, + component: Home + }, { path: '/lifecycle', component: () => import('@/views/Lifecycle.vue') @@ -89,6 +95,9 @@ const routes: Array = [ }, { path: 'tab3', + beforeEnter: (to, from, next) => { + next({ path: '/tabs/tab1' }); + }, component: () => import('@/views/Tab3.vue') } ] @@ -120,6 +129,6 @@ const routes: Array = [ const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes -}) +}); export default router diff --git a/packages/vue/test-app/src/views/Home.vue b/packages/vue/test-app/src/views/Home.vue index a84860b6fa..82db17ee0f 100644 --- a/packages/vue/test-app/src/views/Home.vue +++ b/packages/vue/test-app/src/views/Home.vue @@ -44,6 +44,9 @@ Lifecycle + + Delayed Redirect + diff --git a/packages/vue/test-app/tests/e2e/specs/routing.js b/packages/vue/test-app/tests/e2e/specs/routing.js index 194276ad32..b65e328133 100644 --- a/packages/vue/test-app/tests/e2e/specs/routing.js +++ b/packages/vue/test-app/tests/e2e/specs/routing.js @@ -62,7 +62,23 @@ describe('Routing', () => { cy.ionPageDoesNotExist('routingparameter'); cy.ionPageVisible('routing'); - }) + }); + + // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22359 + it('should work properly with async navigation guards', () => { + cy.visit('http://localhost:8080'); + cy.get('#delayed-redirect').click(); + + cy.get('ion-loading').should('exist'); + + cy.ionPageVisible('routing'); + cy.ionPageHidden('home'); + + cy.ionBackClick('routing'); + + cy.ionPageVisible('home'); + cy.ionPageDoesNotExist('routing'); + }); }); describe('Routing - Swipe to Go Back', () => { diff --git a/packages/vue/test-app/tests/e2e/specs/tabs.js b/packages/vue/test-app/tests/e2e/specs/tabs.js index d7f526b1fa..dec8cc5e98 100644 --- a/packages/vue/test-app/tests/e2e/specs/tabs.js +++ b/packages/vue/test-app/tests/e2e/specs/tabs.js @@ -113,6 +113,15 @@ describe('Tabs', () => { cy.get('ion-tab-button#tab-button-tab2').click(); cy.ionPageVisible('tab2'); }); + + // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22344 + it('should show tab 1 when redirecting from tab 3', () => { + cy.visit('http://localhost:8080/tabs/tab3'); + + cy.ionPageVisible('tab1'); + cy.ionPageDoesNotExist('tab3'); + cy.ionPageVisible('tabs'); + }); }) describe('Tabs - Swipe to Go Back', () => {