mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(vue): modal, popover, and nav are now created within application context (#22282)
resolves #22079
This commit is contained in:
@@ -83,6 +83,7 @@ export const config: Config = {
|
||||
'ion-popover',
|
||||
'ion-toast',
|
||||
|
||||
'ion-app',
|
||||
'ion-icon'
|
||||
],
|
||||
routerLinkComponents: [
|
||||
|
||||
38
packages/vue/src/components/IonApp.ts
Normal file
38
packages/vue/src/components/IonApp.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { h, defineComponent, shallowRef, VNode } from 'vue';
|
||||
|
||||
const userComponents = shallowRef([]);
|
||||
export const IonApp = defineComponent({
|
||||
name: 'IonApp',
|
||||
setup(_, { attrs, slots }) {
|
||||
return () => {
|
||||
return h(
|
||||
'ion-app',
|
||||
{
|
||||
...attrs
|
||||
},
|
||||
[slots.default && slots.default(), ...userComponents.value]
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* When rendering user components inside of
|
||||
* ion-modal, ion-popover, or ion-nav, the component
|
||||
* needs to be created inside of the current application
|
||||
* context otherwise libraries such as vue-i18n or vuex
|
||||
* will not work properly.
|
||||
*
|
||||
* `userComponents` renders teleported components as children
|
||||
* of `ion-app` within the current application context.
|
||||
*/
|
||||
export const addTeleportedUserComponent = (component: VNode) => {
|
||||
userComponents.value = [
|
||||
...userComponents.value,
|
||||
component
|
||||
]
|
||||
}
|
||||
|
||||
export const removeTeleportedUserComponent = (component: VNode) => {
|
||||
userComponents.value = userComponents.value.filter(cmp => cmp !== component);
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createVNode, render } from 'vue';
|
||||
|
||||
import { h, Teleport, VNode } from 'vue';
|
||||
import { addTeleportedUserComponent, removeTeleportedUserComponent } from './components/IonApp';
|
||||
export const VueDelegate = () => {
|
||||
const attachViewToDom = (parentElement: HTMLElement, component: any, componentProps: any, classes?: string[]) => {
|
||||
let Component: VNode | undefined;
|
||||
const attachViewToDom = (parentElement: HTMLElement, component: any, componentProps: any = {}, classes?: string[]) => {
|
||||
/**
|
||||
* Ionic Framework passes in modal and popover element
|
||||
* refs as props, but if these are not defined
|
||||
@@ -10,20 +11,24 @@ export const VueDelegate = () => {
|
||||
*/
|
||||
delete componentProps['modal'];
|
||||
delete componentProps['popover'];
|
||||
const vueInstance = createVNode(component, componentProps);
|
||||
|
||||
const div = document.createElement('div');
|
||||
classes && div.classList.add(...classes);
|
||||
|
||||
parentElement.appendChild(div);
|
||||
|
||||
render(vueInstance, div);
|
||||
Component = h(
|
||||
Teleport,
|
||||
{ to: div },
|
||||
h(component, { ...componentProps })
|
||||
);
|
||||
|
||||
addTeleportedUserComponent(Component);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
const removeViewFromDom = (_: HTMLElement, childElement: any) => {
|
||||
render(null, childElement);
|
||||
const removeViewFromDom = () => {
|
||||
Component && removeTeleportedUserComponent(Component);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ export { IonTabs } from './components/IonTabs';
|
||||
export { IonTabBar } from './components/IonTabBar';
|
||||
export { IonNav } from './components/IonNav';
|
||||
export { IonIcon } from './components/IonIcon';
|
||||
export { IonApp } from './components/IonApp';
|
||||
|
||||
export * from './components/Overlays';
|
||||
|
||||
export { IonKeyboardRef, IonRouter, useBackButton, useIonRouter, useKeyboard } from './hooks';
|
||||
|
||||
@@ -8,9 +8,6 @@ import { JSX } from '@ionic/core';
|
||||
|
||||
|
||||
|
||||
export const IonApp = /*@__PURE__*/ defineContainer<JSX.IonApp>('ion-app');
|
||||
|
||||
|
||||
export const IonAvatar = /*@__PURE__*/ defineContainer<JSX.IonAvatar>('ion-avatar');
|
||||
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
|
||||
|
||||
const Container = defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
||||
const overlay = ref();
|
||||
const content = ref();
|
||||
|
||||
const onVnodeMounted = async () => {
|
||||
const isOpen = props.isOpen;
|
||||
isOpen && (await present(props))
|
||||
@@ -39,7 +37,7 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
|
||||
}
|
||||
|
||||
const present = async (props: Readonly<Props>) => {
|
||||
const component = (slots) ? h('div', { ref: content }, slots) : undefined;
|
||||
const component = slots.default && slots.default()[0];
|
||||
overlay.value = await controller.create({
|
||||
...props,
|
||||
component
|
||||
|
||||
20
packages/vue/test-app/package-lock.json
generated
20
packages/vue/test-app/package-lock.json
generated
@@ -1306,27 +1306,27 @@
|
||||
}
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.4.0-dev.202010091911.bfc0b25.tgz",
|
||||
"integrity": "sha512-gDWwMcgV+kPeTfBToZ8oLoSI7FygkRYEgi/DEAIHye3W8T/Z/NmqrxaNqXrXU0J0RKvfzrIlrw6uB67Xz1xRcw==",
|
||||
"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==",
|
||||
"requires": {
|
||||
"ionicons": "^5.1.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@ionic/vue": {
|
||||
"version": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-5.4.0-dev.202010091911.bfc0b25.tgz",
|
||||
"integrity": "sha512-zrF/u3sMq4k3mLMtlA/VcS+RFeWEXrhOnzJAo8uPuDGT4ZcttJv0sVIFJMqZF7zM+6+xxep5B5mMoB1cigwG3A==",
|
||||
"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==",
|
||||
"requires": {
|
||||
"@ionic/core": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"@ionic/core": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"ionicons": "^5.1.2"
|
||||
}
|
||||
},
|
||||
"@ionic/vue-router": {
|
||||
"version": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue-router/-/vue-router-5.4.0-dev.202010091911.bfc0b25.tgz",
|
||||
"integrity": "sha512-moa388WPxJjHBcIVILoijS+xrTcS7jaK4T/rP3U9Lri1bSYrDpYNWmd/0sktGt80m3gaa8VXS5E995zDiyLAfQ=="
|
||||
"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=="
|
||||
},
|
||||
"@jest/console": {
|
||||
"version": "24.9.0",
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"sync": "sh ./scripts/sync.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/vue": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"@ionic/vue-router": "5.4.0-dev.202010091911.bfc0b25",
|
||||
"@ionic/vue": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"@ionic/vue-router": "5.4.0-dev.202010081857.bfc0b25",
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0-0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
|
||||
16
packages/vue/test-app/src/components/Nav.vue
Normal file
16
packages/vue/test-app/src/components/Nav.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<ion-nav :root="NavRoot"></ion-nav>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { IonNav } from '@ionic/vue';
|
||||
import NavRoot from '@/components/NavRoot.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonNav },
|
||||
setup() {
|
||||
return { NavRoot }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
39
packages/vue/test-app/src/components/NavChild.vue
Normal file
39
packages/vue/test-app/src/components/NavChild.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Nav - Child</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding" id="nav-child-content">
|
||||
{{ title }}
|
||||
</ion-content>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
} from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
title: { type: String, default: 'Default Title' }
|
||||
},
|
||||
components: {
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
}
|
||||
})
|
||||
</script>
|
||||
47
packages/vue/test-app/src/components/NavRoot.vue
Normal file
47
packages/vue/test-app/src/components/NavRoot.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-button @click="dismiss">Dismiss</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Nav - Root</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<ion-button expand="block" @click="pushPage" id="push-nav-child">Go to Nav Child</ion-button>
|
||||
</ion-content>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
IonButtons,
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
modalController
|
||||
} from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import NavChild from '@/components/NavChild.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
IonButtons,
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
},
|
||||
methods: {
|
||||
pushPage: function() {
|
||||
const ionNav = document.querySelector('ion-nav') as any;
|
||||
ionNav.push(NavChild, { title: 'Custom Title' });
|
||||
},
|
||||
dismiss: async function() {
|
||||
await modalController.dismiss();
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -27,13 +27,16 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/DefaultHref.vue')
|
||||
},
|
||||
{
|
||||
path: '/navigation',
|
||||
name: 'Navigation',
|
||||
component: () => import('@/views/Navigation.vue')
|
||||
path: '/routing',
|
||||
component: () => import('@/views/Routing.vue')
|
||||
},
|
||||
{
|
||||
path: '/navigation/child',
|
||||
component: () => import('@/views/NavigationChild.vue')
|
||||
path: '/routing/child',
|
||||
component: () => import('@/views/RoutingChild.vue')
|
||||
},
|
||||
{
|
||||
path: '/navigation',
|
||||
component: () => import('@/views/Navigation.vue')
|
||||
},
|
||||
{
|
||||
path: '/nested',
|
||||
@@ -81,7 +84,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/Tab3.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
<ion-item router-link="/navigation" id="navigation">
|
||||
<ion-label>Navigation</ion-label>
|
||||
</ion-item>
|
||||
<ion-item router-link="/routing" id="routing">
|
||||
<ion-label>Routing</ion-label>
|
||||
</ion-item>
|
||||
<ion-item router-link="/default-href" id="default-href">
|
||||
<ion-label>Default Href</ion-label>
|
||||
</ion-item>
|
||||
|
||||
@@ -16,56 +16,47 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-item button @click="setRouteParams" id="route-params">
|
||||
<ion-label>Set Route Parameters</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button router-link="/navigation/child" id="child">
|
||||
<ion-label>Go to Child Page</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding">
|
||||
<ion-button expand="block" @click="openModal" id="open-nav-modal">Open Modal</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
IonButton,
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
IonToolbar,
|
||||
modalController
|
||||
} from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import Nav from '@/components/Nav.vue';
|
||||
export default defineComponent({
|
||||
name: 'Navigation',
|
||||
components: {
|
||||
IonButton,
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const setRouteParams = () => {
|
||||
router.push({
|
||||
query: {
|
||||
search: 'liamwashere'
|
||||
}
|
||||
const openModal = async () => {
|
||||
const modal = await modalController.create({
|
||||
component: Nav
|
||||
});
|
||||
}
|
||||
|
||||
return { setRouteParams }
|
||||
await modal.present();
|
||||
}
|
||||
return { openModal }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
|
||||
<ion-modal
|
||||
:is-open="isModalOpen"
|
||||
:componentProps="overlayProps"
|
||||
@onDidDismiss="setModalRef(false)"
|
||||
>
|
||||
<ModalContent></ModalContent>
|
||||
@@ -97,6 +98,7 @@
|
||||
|
||||
<ion-popover
|
||||
:is-open="isPopoverOpen"
|
||||
:componentProps="overlayProps"
|
||||
:event="popoverEvent"
|
||||
@onDidDismiss="setPopoverRef(false)"
|
||||
>
|
||||
@@ -231,6 +233,10 @@ export default defineComponent({
|
||||
}
|
||||
]
|
||||
|
||||
const overlayProps = {
|
||||
title: 'Custom Title'
|
||||
}
|
||||
|
||||
const openActionSheet = async () => {
|
||||
const actionSheet = await actionSheetController.create({ buttons: actionSheetButtons });
|
||||
await actionSheet.present();
|
||||
@@ -252,12 +258,12 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const openModal = async () => {
|
||||
const modal = await modalController.create({ component: ModalContent });
|
||||
const modal = await modalController.create({ component: ModalContent, componentProps: overlayProps });
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
const openPopover = async (event: Event) => {
|
||||
const popover = await popoverController.create({ component: PopoverContent, event });
|
||||
const popover = await popoverController.create({ component: PopoverContent, event, componentProps: overlayProps });
|
||||
await popover.present();
|
||||
}
|
||||
|
||||
@@ -309,6 +315,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return {
|
||||
overlayProps,
|
||||
present,
|
||||
componentType,
|
||||
presentationType,
|
||||
|
||||
70
packages/vue/test-app/src/views/Routing.vue
Normal file
70
packages/vue/test-app/src/views/Routing.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<ion-page data-pageid="routing">
|
||||
<ion-header :translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Routing</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content :fullscreen="true">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Routing</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-item button @click="setRouteParams" id="route-params">
|
||||
<ion-label>Set Route Parameters</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button router-link="/routing/child" id="child">
|
||||
<ion-label>Go to Child Page</ion-label>
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
} from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const setRouteParams = () => {
|
||||
router.push({
|
||||
query: {
|
||||
search: 'liamwashere'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { setRouteParams }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<ion-page data-pageid="navigationchild">
|
||||
<ion-page data-pageid="routingchild">
|
||||
<ion-header :translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Navigation Child</ion-title>
|
||||
<ion-title>Routing Child</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content :fullscreen="true">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar>
|
||||
<ion-title size="large">Navigation Child</ion-title>
|
||||
<ion-title size="large">Routing Child</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<div class="ion-padding">
|
||||
Navigation Child Page
|
||||
Routing Child Page
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
@@ -37,7 +37,6 @@ import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NavigationChild',
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
@@ -1,74 +1,13 @@
|
||||
describe('Navigation', () => {
|
||||
it('should go to sibling page', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
cy.get('ion-item#navigation').click();
|
||||
|
||||
cy.wait(500)
|
||||
|
||||
cy.ionPageVisible('navigation')
|
||||
cy.ionPageHidden('home')
|
||||
});
|
||||
|
||||
it('should set query params and keep view in stack', () => {
|
||||
cy.visit('http://localhost:8080/navigation');
|
||||
cy.get('#route-params').click();
|
||||
cy.ionPageVisible('navigation');
|
||||
});
|
||||
|
||||
it('should go back home', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
cy.get('ion-item#navigation').click();
|
||||
|
||||
cy.ionBackClick('navigation');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('navigation');
|
||||
});
|
||||
|
||||
it('should go back home with default href', () => {
|
||||
cy.visit('http://localhost:8080/default-href');
|
||||
|
||||
cy.ionBackClick('defaulthref');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('defaulthref');
|
||||
});
|
||||
|
||||
it('should show back button', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
|
||||
cy.get('#navigation').click();
|
||||
cy.get('#child').click();
|
||||
|
||||
cy.ionBackClick('navigationchild');
|
||||
cy.ionBackClick('navigation');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('navigation');
|
||||
cy.ionPageDoesNotExist('navigationchild')
|
||||
})
|
||||
});
|
||||
|
||||
describe('Navigation - Swipe to Go Back', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(320, 568);
|
||||
cy.visit('http://localhost:8080?ionic:mode=ios');
|
||||
cy.get('#navigation').click();
|
||||
cy.ionPageHidden('home');
|
||||
cy.ionPageVisible('navigation')
|
||||
cy.visit('http://localhost:8080/navigation');
|
||||
});
|
||||
|
||||
it('should swipe and abort', () => {
|
||||
cy.ionSwipeToGoBack();
|
||||
cy.ionPageHidden('home');
|
||||
cy.ionPageVisible('navigation');
|
||||
});
|
||||
it('should push a page with props', () => {
|
||||
cy.get('#open-nav-modal').click();
|
||||
|
||||
it('should swipe and complete', () => {
|
||||
cy.ionSwipeToGoBack(true);
|
||||
cy.ionPageVisible('home');
|
||||
cy.get('#push-nav-child').click();
|
||||
|
||||
// TODO: Vue router does not go back in cypress with router.back()
|
||||
//cy.ionPageDoesNotExist('navigation');
|
||||
cy.get('#nav-child-content').should('have.text', 'Custom Title');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
@@ -48,14 +48,54 @@ describe('Overlays', () => {
|
||||
}
|
||||
|
||||
it(`should open and close ion-toast via component`, () => {
|
||||
cy.get(`ion-radio#ion-toast`).click();
|
||||
cy.get('ion-radio#component').click();
|
||||
cy.get(`ion-radio#ion-toast`).click();
|
||||
cy.get('ion-radio#component').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-toast').should('exist');
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-toast').should('exist');
|
||||
|
||||
cy.get('ion-toast').find('button').click();
|
||||
cy.get('ion-toast').find('button').click();
|
||||
|
||||
cy.get('ion-toast').should('not.exist');
|
||||
});
|
||||
cy.get('ion-toast').should('not.exist');
|
||||
});
|
||||
|
||||
it('it should pass props to modal via controller', () => {
|
||||
cy.get('ion-radio#ion-modal').click();
|
||||
cy.get('ion-radio#controller').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-modal').should('exist');
|
||||
|
||||
cy.get('ion-modal ion-content').should('have.text', 'Custom Title');
|
||||
});
|
||||
|
||||
it('it should pass props to modal via component', () => {
|
||||
cy.get('ion-radio#ion-modal').click();
|
||||
cy.get('ion-radio#component').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-modal').should('exist');
|
||||
|
||||
cy.get('ion-modal ion-content').should('have.text', 'Custom Title');
|
||||
});
|
||||
|
||||
it('it should pass props to popover via controller', () => {
|
||||
cy.get('ion-radio#ion-popover').click();
|
||||
cy.get('ion-radio#controller').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-popover').should('exist');
|
||||
|
||||
cy.get('ion-popover ion-content').should('have.text', 'Custom Title');
|
||||
});
|
||||
|
||||
it('it should pass props to popover via component', () => {
|
||||
cy.get('ion-radio#ion-popover').click();
|
||||
cy.get('ion-radio#component').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-popover').should('exist');
|
||||
|
||||
cy.get('ion-popover ion-content').should('have.text', 'Custom Title');
|
||||
});
|
||||
})
|
||||
|
||||
74
packages/vue/test-app/tests/e2e/specs/routing.js
Normal file
74
packages/vue/test-app/tests/e2e/specs/routing.js
Normal file
@@ -0,0 +1,74 @@
|
||||
describe('Routing', () => {
|
||||
it('should go to sibling page', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
cy.get('ion-item#routing').click();
|
||||
|
||||
cy.wait(500)
|
||||
|
||||
cy.ionPageVisible('routing')
|
||||
cy.ionPageHidden('home')
|
||||
});
|
||||
|
||||
it('should set query params and keep view in stack', () => {
|
||||
cy.visit('http://localhost:8080/routing');
|
||||
cy.get('#route-params').click();
|
||||
cy.ionPageVisible('routing');
|
||||
});
|
||||
|
||||
it('should go back home', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
cy.get('ion-item#routing').click();
|
||||
|
||||
cy.ionBackClick('routing');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('routing');
|
||||
});
|
||||
|
||||
it('should go back home with default href', () => {
|
||||
cy.visit('http://localhost:8080/default-href');
|
||||
|
||||
cy.ionBackClick('defaulthref');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('defaulthref');
|
||||
});
|
||||
|
||||
it('should show back button', () => {
|
||||
cy.visit('http://localhost:8080');
|
||||
|
||||
cy.get('#routing').click();
|
||||
cy.get('#child').click();
|
||||
|
||||
cy.ionBackClick('routingchild');
|
||||
cy.ionBackClick('routing');
|
||||
|
||||
cy.ionPageVisible('home');
|
||||
cy.ionPageDoesNotExist('routing');
|
||||
cy.ionPageDoesNotExist('routingchild')
|
||||
})
|
||||
});
|
||||
|
||||
describe('Routing - Swipe to Go Back', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(320, 568);
|
||||
cy.visit('http://localhost:8080?ionic:mode=ios');
|
||||
cy.get('#routing').click();
|
||||
cy.ionPageHidden('home');
|
||||
cy.ionPageVisible('routing')
|
||||
});
|
||||
|
||||
it('should swipe and abort', () => {
|
||||
cy.ionSwipeToGoBack();
|
||||
cy.ionPageHidden('home');
|
||||
cy.ionPageVisible('routing');
|
||||
});
|
||||
|
||||
it('should swipe and complete', () => {
|
||||
cy.ionSwipeToGoBack(true);
|
||||
cy.ionPageVisible('home');
|
||||
|
||||
// TODO: Vue router does not go back in cypress with router.back()
|
||||
//cy.ionPageDoesNotExist('navigation');
|
||||
});
|
||||
})
|
||||
Reference in New Issue
Block a user