mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
fix(vue): pages now render in correct outlet when using multiple nested outlets (#22301)
resolves #22286
This commit is contained in:
@ -6,14 +6,6 @@ import { RouteInfo,
|
||||
|
||||
export const createViewStacks = () => {
|
||||
let viewStacks: ViewStacks = {};
|
||||
const tabsPrefixes = new Set();
|
||||
|
||||
const addTabsPrefix = (prefix: string) => tabsPrefixes.add(prefix);
|
||||
const hasTabsPrefix = (path: string) => {
|
||||
const values = Array.from(tabsPrefixes.values());
|
||||
const hasPrefix = values.find((v: string) => path.includes(v));
|
||||
return hasPrefix !== undefined;
|
||||
}
|
||||
|
||||
const getViewStack = (outletId: number) => {
|
||||
return viewStacks[outletId];
|
||||
@ -31,6 +23,19 @@ export const createViewStacks = () => {
|
||||
return findViewItemByPath(routeInfo.lastPathname, outletId);
|
||||
}
|
||||
|
||||
const findViewItemByMatchedRoute = (matchedRoute: any, outletId: number): ViewItem | undefined => {
|
||||
const stack = viewStacks[outletId];
|
||||
if (!stack) return undefined;
|
||||
|
||||
return stack.find((viewItem: ViewItem) => {
|
||||
if (viewItem.matchedRoute.path === matchedRoute.path) {
|
||||
return viewItem;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
const findViewItemInStack = (path: string, stack: ViewItem[]): ViewItem | undefined => {
|
||||
return stack.find((viewItem: ViewItem) => {
|
||||
if (viewItem.pathname === path) {
|
||||
@ -100,9 +105,8 @@ export const createViewStacks = () => {
|
||||
}
|
||||
|
||||
return {
|
||||
addTabsPrefix,
|
||||
hasTabsPrefix,
|
||||
findViewItemByRouteInfo,
|
||||
findViewItemByMatchedRoute,
|
||||
findLeavingViewItemByRouteInfo,
|
||||
createViewItem,
|
||||
getChildrenToRender,
|
||||
|
@ -19,17 +19,9 @@ export const IonRouterOutlet = defineComponent({
|
||||
setup(_, { attrs }) {
|
||||
const route = useRoute();
|
||||
const depth = inject(viewDepthKey, 0);
|
||||
|
||||
// TODO types
|
||||
let tabsPrefix: string | undefined;
|
||||
const matchedRouteRef: any = computed(() => {
|
||||
const matchedRoute = route.matched[depth];
|
||||
|
||||
if (attrs.tabs && !tabsPrefix) {
|
||||
tabsPrefix = route.matched[0].path;
|
||||
viewStacks.addTabsPrefix(tabsPrefix);
|
||||
}
|
||||
|
||||
if (matchedRoute && attrs.tabs && route.matched[depth + 1]) {
|
||||
return route.matched[route.matched.length - 1];
|
||||
}
|
||||
@ -50,9 +42,10 @@ export const IonRouterOutlet = defineComponent({
|
||||
|
||||
let skipTransition = false;
|
||||
|
||||
watch(matchedRouteRef, () => {
|
||||
setupViewItem(matchedRouteRef);
|
||||
});
|
||||
// The base url for this router outlet
|
||||
let parentOutletPath: string;
|
||||
|
||||
watch(matchedRouteRef, () => setupViewItem(matchedRouteRef));
|
||||
|
||||
const canStart = () => {
|
||||
const stack = viewStacks.getViewStack(id);
|
||||
@ -252,20 +245,46 @@ export const IonRouterOutlet = defineComponent({
|
||||
components.value = viewStacks.getChildrenToRender(id);
|
||||
}
|
||||
|
||||
// TODO types
|
||||
const setupViewItem = (matchedRouteRef: any) => {
|
||||
if (!matchedRouteRef.value) {
|
||||
const firstMatchedRoute = route.matched[0];
|
||||
if (!parentOutletPath) {
|
||||
parentOutletPath = firstMatchedRoute.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no matched route, do not do anything in this outlet.
|
||||
* If there is a match, but it the first matched path
|
||||
* is not the root path for this outlet, then this view
|
||||
* change needs to be rendered in a different outlet.
|
||||
* We also add an exception for when the matchedRouteRef is
|
||||
* equal to the first matched route (i.e. the base router outlet).
|
||||
* This logic is mainly to help nested outlets/multi-tab
|
||||
* setups work better.
|
||||
*/
|
||||
if (
|
||||
!matchedRouteRef.value ||
|
||||
(matchedRouteRef.value !== firstMatchedRoute && firstMatchedRoute.path !== parentOutletPath)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentRoute = ionRouter.getCurrentRouteInfo();
|
||||
const hasTabsPrefix = viewStacks.hasTabsPrefix(currentRoute.pathname)
|
||||
const isLastPathTabs = viewStacks.hasTabsPrefix(currentRoute.lastPathname);
|
||||
if (hasTabsPrefix && isLastPathTabs && !attrs.tabs) { return; }
|
||||
|
||||
let enteringViewItem = viewStacks.findViewItemByRouteInfo(currentRoute, id);
|
||||
|
||||
if (!enteringViewItem) {
|
||||
/**
|
||||
* If we have no existing entering item, we need
|
||||
* make sure that there is no existing view according to the
|
||||
* matched route rather than what is in the url bar.
|
||||
* This is mainly for tabs when outlet 1 renders ion-tabs
|
||||
* and outlet 2 renders the individual tab view. We don't
|
||||
* want outlet 1 creating a new ion-tabs instance every time
|
||||
* we switch tabs.
|
||||
*/
|
||||
if (viewStacks.findViewItemByMatchedRoute(matchedRouteRef.value, id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
enteringViewItem = viewStacks.createViewItem(id, matchedRouteRef.value.components.default, matchedRouteRef.value, currentRoute);
|
||||
viewStacks.add(enteringViewItem);
|
||||
}
|
||||
|
32
packages/vue/test-app/package-lock.json
generated
32
packages/vue/test-app/package-lock.json
generated
@ -1306,27 +1306,27 @@
|
||||
}
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.4.0-dev.202010081857.bfc0b25.tgz",
|
||||
"integrity": "sha512-yCH1GTlTTTS3dt9kYk/y5K82UdKOLidRqziGTsFeOoqTJI2w87SgRx0V0Il92dcB1XaWPB/SNnaM7Tt+GD7+Lg==",
|
||||
"version": "5.4.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.4.0-rc.1.tgz",
|
||||
"integrity": "sha512-8/Mcz86GZEA8Q9x86MOpWU+v4PQBmMfjja1LNVlGN+OIh2oIVBbY6EL6+dw9o6lcHoMY4bUHHpgyPvpYDNXfJw==",
|
||||
"requires": {
|
||||
"ionicons": "^5.1.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@ionic/vue": {
|
||||
"version": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-5.4.0-dev.202010081857.bfc0b25.tgz",
|
||||
"integrity": "sha512-A2s0skOjoytlwC2xJVo+jmv6ZcYKV+HAaGitqKs08bPHATFDh+yzpJLXRkS0poZ3N2Bk4ossXsd5gn4eXC7cKw==",
|
||||
"version": "5.4.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-5.4.0-rc.1.tgz",
|
||||
"integrity": "sha512-DqlZIE61Awm3D1jNX6ADbGcfQWKhRZty1EZVjnJ9xPnPLm4h/yKUU2jRUwfN5ia7pYIvKoz+FAqwBgGxO4G8UQ==",
|
||||
"requires": {
|
||||
"@ionic/core": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"@ionic/core": "5.4.0-rc.1",
|
||||
"ionicons": "^5.1.2"
|
||||
}
|
||||
},
|
||||
"@ionic/vue-router": {
|
||||
"version": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue-router/-/vue-router-5.4.0-dev.202010081857.bfc0b25.tgz",
|
||||
"integrity": "sha512-qlFRY32CuttCZHqFFTZoDOERFFLDursJvMeb75KjE5lO/gD+dbelb7Cn0dOyaKyrM06X/lwb8eXgjCwSsGbHxg=="
|
||||
"version": "5.4.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue-router/-/vue-router-5.4.0-rc.1.tgz",
|
||||
"integrity": "sha512-Yq+yPJdaCdHZTEefes7ry9fEUyMkxPvxPjzc/e4vgDz1a3/UISM3SGfxP4qRv2RtRs5nbPv0tb1DZuPbMOYT9g=="
|
||||
},
|
||||
"@jest/console": {
|
||||
"version": "24.9.0",
|
||||
@ -7691,6 +7691,12 @@
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
@ -12295,12 +12301,6 @@
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||
|
@ -12,8 +12,8 @@
|
||||
"sync": "sh ./scripts/sync.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/vue": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"@ionic/vue-router": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"@ionic/vue": "^5.4.0-rc.1",
|
||||
"@ionic/vue-router": "^5.4.0-rc.1",
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0-0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
|
@ -4,6 +4,11 @@ cp -a ../dist node_modules/@ionic/vue/dist
|
||||
cp -a ../css node_modules/@ionic/vue/css
|
||||
cp -a ../package.json node_modules/@ionic/vue/package.json
|
||||
|
||||
# Copy ionic vue router dist
|
||||
rm -rf node_modules/@ionic/vue-router/dist
|
||||
cp -a ../../vue-router/dist node_modules/@ionic/vue-router/dist
|
||||
cp -a ../../vue-router/package.json node_modules/@ionic/vue-router/package.json
|
||||
|
||||
# Copy core dist
|
||||
rm -rf node_modules/@ionic/core/dist node_modules/@ionic/core/loader
|
||||
cp -a ../../../core/dist node_modules/@ionic/core/dist
|
||||
|
@ -85,6 +85,28 @@ const routes: Array<RouteRecordRaw> = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/tabs-secondary/',
|
||||
component: () => import('@/views/TabsSecondary.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirect: '/tabs-secondary/tab1'
|
||||
},
|
||||
{
|
||||
path: 'tab1',
|
||||
component: () => import('@/views/Tab1Secondary.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab2',
|
||||
component: () => import('@/views/Tab2Secondary.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab3',
|
||||
component: () => import('@/views/Tab3Secondary.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
@ -38,6 +38,9 @@
|
||||
<ion-item router-link="/tabs" id="tabs">
|
||||
<ion-label>Tabs</ion-label>
|
||||
</ion-item>
|
||||
<ion-item router-link="/tabs-secondary" id="tab-secondary">
|
||||
<ion-label>Tabs Secondary</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
</ion-content>
|
||||
|
@ -17,6 +17,7 @@
|
||||
</ion-header>
|
||||
|
||||
<div class="ion-padding">
|
||||
<ion-button router-link="/tabs/tab1" id="nested-tabs">Tab 1</ion-button>
|
||||
<ion-button router-link="/nested/two" id="nested-child-two">Nested Child Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-page data-pageid="routeroutlet">
|
||||
<ion-content>
|
||||
<ion-router-outlet></ion-router-outlet>
|
||||
</ion-content>
|
||||
|
@ -20,6 +20,17 @@
|
||||
<ion-item router-link="tab1/child-one" id="child-one">
|
||||
<ion-label>Go to Tab 1 Child 1</ion-label>
|
||||
</ion-item>
|
||||
<ion-item router-link="/nested" id="nested">
|
||||
<ion-label>Go to Nested Outlet</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item router-link="/tabs-secondary" id="tabs-secondary">
|
||||
<ion-label>Go to Secondary Tabs</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item router-link="/tabs" id="tabs-primary">
|
||||
<ion-label>Go to Primary Tabs</ion-label>
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
34
packages/vue/test-app/src/views/Tab1Secondary.vue
Normal file
34
packages/vue/test-app/src/views/Tab1Secondary.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<ion-page data-pageid="tab1-secondary">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-back-button default-href="/"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Tab 1 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content :fullscreen="true">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Tab 1 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ExploreContainer name="Tab 1 page" />
|
||||
|
||||
<ion-item router-link="/tabs" id="tabs-primary">
|
||||
<ion-label>Go to Primary Tabs</ion-label>
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonButtons, IonBackButton, IonPage, IonHeader, IonItem, IonLabel, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
|
||||
import ExploreContainer from '@/components/ExploreContainer.vue';
|
||||
|
||||
export default {
|
||||
components: { IonButtons, IonBackButton, ExploreContainer, IonHeader, IonItem, IonLabel, IonToolbar, IonTitle, IonContent, IonPage }
|
||||
}
|
||||
</script>
|
27
packages/vue/test-app/src/views/Tab2Secondary.vue
Normal file
27
packages/vue/test-app/src/views/Tab2Secondary.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<ion-page data-pageid="tab2-secondary">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab 2 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content :fullscreen="true">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Tab 2 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ExploreContainer name="Tab 2 page" />
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
|
||||
import ExploreContainer from '@/components/ExploreContainer.vue';
|
||||
|
||||
export default {
|
||||
components: { ExploreContainer, IonHeader, IonToolbar, IonTitle, IonContent, IonPage }
|
||||
}
|
||||
</script>
|
27
packages/vue/test-app/src/views/Tab3Secondary.vue
Normal file
27
packages/vue/test-app/src/views/Tab3Secondary.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab 3 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content :fullscreen="true">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Tab 3 - Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ExploreContainer name="Tab 3 page" />
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
|
||||
import ExploreContainer from '@/components/ExploreContainer.vue';
|
||||
|
||||
export default {
|
||||
components: { ExploreContainer, IonHeader, IonToolbar, IonTitle, IonContent, IonPage }
|
||||
}
|
||||
</script>
|
41
packages/vue/test-app/src/views/TabsSecondary.vue
Normal file
41
packages/vue/test-app/src/views/TabsSecondary.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<ion-page data-pageid="tabs-secondary">
|
||||
<ion-content>
|
||||
<ion-tabs id="tabs">
|
||||
<ion-tab-bar slot="bottom">
|
||||
<ion-tab-button tab="tab1" href="/tabs-secondary/tab1">
|
||||
<ion-icon :icon="triangle" />
|
||||
<ion-label>Tab 1</ion-label>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="tab2" href="/tabs-secondary/tab2">
|
||||
<ion-icon :icon="ellipse" />
|
||||
<ion-label>Tab 2</ion-label>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="tab3" href="/tabs-secondary/tab3">
|
||||
<ion-icon :icon="square" />
|
||||
<ion-label>Tab 3</ion-label>
|
||||
</ion-tab-button>
|
||||
</ion-tab-bar>
|
||||
</ion-tabs>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { IonTabBar, IonTabButton, IonTabs, IonContent, IonLabel, IonIcon, IonPage } from '@ionic/vue';
|
||||
import { ellipse, square, triangle } from 'ionicons/icons';
|
||||
|
||||
export default {
|
||||
name: 'Tabs',
|
||||
components: { IonContent, IonLabel, IonTabs, IonTabBar, IonTabButton, IonIcon, IonPage },
|
||||
setup() {
|
||||
return {
|
||||
ellipse,
|
||||
square,
|
||||
triangle,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -7,15 +7,29 @@ describe('Nested', () => {
|
||||
cy.ionPageVisible('nestedchild');
|
||||
});
|
||||
|
||||
it.skip('should go to second page', () => {
|
||||
it('should go to second page', () => {
|
||||
cy.get('#nested-child-two').click();
|
||||
cy.ionPageVisible('nestedchildtwo');
|
||||
cy.ionPageInvisible('nestedchild');
|
||||
cy.ionPageHidden('nestedchild');
|
||||
});
|
||||
|
||||
it.skip('should go back to first page', () => {
|
||||
it('should go back to first page', () => {
|
||||
cy.get('#nested-child-two').click();
|
||||
cy.ionBackClick('nestedchildtwo');
|
||||
cy.ionPageVisible('nestedchild');
|
||||
});
|
||||
|
||||
it('should go navigate across nested outlet contexts', () => {
|
||||
cy.ionPageVisible('nestedchild');
|
||||
|
||||
cy.get('#nested-tabs').click();
|
||||
|
||||
cy.ionPageHidden('routeroutlet');
|
||||
cy.ionPageVisible('tab1');
|
||||
|
||||
cy.ionBackClick('tab1');
|
||||
|
||||
cy.ionPageDoesNotExist('tab1');
|
||||
cy.ionPageVisible('routeroutlet');
|
||||
});
|
||||
})
|
||||
|
@ -36,6 +36,21 @@ describe('Tabs', () => {
|
||||
cy.get('ion-tab-button#tab-button-tab1').click();
|
||||
});
|
||||
|
||||
it('should go to correct tab when going back via browser', () => {
|
||||
cy.visit('http://localhost:8080/tabs')
|
||||
|
||||
cy.get('#child-one').click();
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab2').click();
|
||||
cy.ionPageVisible('tab2');
|
||||
cy.ionPageHidden('tab1childone');
|
||||
|
||||
cy.go('back');
|
||||
|
||||
cy.ionPageVisible('tab1childone');
|
||||
cy.ionPageHidden('tab1');
|
||||
});
|
||||
|
||||
// TODO this does not work
|
||||
it.skip('should return to tab root when clicking tab button', () => {
|
||||
cy.visit('http://localhost:8080/tabs')
|
||||
@ -134,3 +149,30 @@ describe('Tabs - Swipe to Go Back', () => {
|
||||
cy.ionPageVisible('home');
|
||||
});
|
||||
})
|
||||
|
||||
describe('Multi Tabs', () => {
|
||||
it('should navigate to multiple tabs instances', () => {
|
||||
cy.visit('http://localhost:8080/tabs')
|
||||
|
||||
cy.get('#tabs-secondary').click();
|
||||
cy.ionPageHidden('tabs');
|
||||
cy.ionPageVisible('tabs-secondary');
|
||||
|
||||
cy.get('[data-pageid="tab1-secondary"] #tabs-primary').click();
|
||||
cy.ionPageHidden('tabs-secondary');
|
||||
cy.ionPageVisible('tabs');
|
||||
|
||||
cy.ionBackClick('tab1');
|
||||
cy.ionPageVisible('tabs-secondary');
|
||||
cy.ionPageDoesNotExist('tabs');
|
||||
|
||||
cy.ionBackClick('tab1-secondary');
|
||||
cy.ionPageVisible('tabs');
|
||||
cy.ionPageDoesNotExist('tabs-secondary');
|
||||
|
||||
cy.ionBackClick('tab1');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('tabs');
|
||||
});
|
||||
})
|
||||
|
Reference in New Issue
Block a user