diff --git a/.github/ionic-issue-bot.yml b/.github/ionic-issue-bot.yml
index fad26e0fce..c62a98b9e5 100644
--- a/.github/ionic-issue-bot.yml
+++ b/.github/ionic-issue-bot.yml
@@ -41,8 +41,7 @@ closeAndLock:
- label: "ionitron: support"
message: >
Thanks for the issue! This issue appears to be a support request. We use this issue tracker exclusively for
- bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) or our
- [slack channel](https://ionicworldwide.herokuapp.com/) for questions about the framework.
+ bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) for questions about the framework.
Thank you for using Ionic!
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4c98dcb722..f9c2304d99 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -42,7 +42,7 @@ jobs:
test-core-screenshot:
needs: [build-core]
runs-on: ubuntu-latest
- if: github.ref != 'refs/heads/main'
+ if: github.ref != 'refs/heads/main' && !github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-screenshot
diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml
new file mode 100644
index 0000000000..c9ed9dccc7
--- /dev/null
+++ b/.github/workflows/dev-build.yml
@@ -0,0 +1,75 @@
+name: 'Ionic Dev Build'
+
+on:
+ workflow_dispatch
+
+jobs:
+ dev-build:
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.devBuild.outputs.version }}
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: 15.x
+ registry-url: 'https://registry.npmjs.org'
+ - name: Install Dependencies
+ run: npm install
+ shell: bash
+ - name: Create Dev Build
+ run: npm run release.dev -- --skip-prompt
+ shell: bash
+ - name: Publish Core
+ run: npm publish --tag dev
+ working-directory: ./core
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish Docs
+ run: npm publish --tag dev
+ working-directory: ./docs
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish Angular
+ run: npm publish --tag dev
+ working-directory: ./angular
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish Angular Server
+ run: npm publish --tag dev
+ working-directory: ./packages/angular-server
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish React
+ run: npm publish --tag dev
+ working-directory: ./packages/react
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish React Router
+ run: npm publish --tag dev
+ working-directory: ./packages/react-router
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish Vue
+ run: npm publish --tag dev
+ working-directory: ./packages/vue
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Publish Vue Router
+ run: npm publish --tag dev
+ working-directory: ./packages/vue-router
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Wrap Up
+ id: devBuild
+ run: |
+ val=$(grep version package.json | sed 's/.*"version": "\(.*\)".*/\1/')
+ echo "::set-output name=version::$val"
+ working-directory: ./core
+ get-version:
+ name: Get your dev build!
+ runs-on: ubuntu-latest
+ needs: [dev-build]
+ steps:
+ - run: echo ${{ needs.dev-build.outputs.version }}
+
diff --git a/.scripts/common.js b/.scripts/common.js
index f43d416397..e8ddfad4b4 100644
--- a/.scripts/common.js
+++ b/.scripts/common.js
@@ -199,6 +199,16 @@ function preparePackage(tasks, package, version, install) {
});
}
+function installDevPackage(tasks, package) {
+ const projectRoot = projectPath(package);
+ const pkg = readPkg(package);
+
+ tasks.push({
+ title: `${pkg.name}: npm install`,
+ task: () => execa('npm', ['install', '--legacy-peer-deps'], { cwd: projectRoot })
+ });
+}
+
function prepareDevPackage(tasks, package, version) {
const projectRoot = projectPath(package);
const pkg = readPkg(package);
@@ -211,20 +221,20 @@ function prepareDevPackage(tasks, package, version) {
title: `${pkg.name}: npm link @ionic/core`,
task: () => execa('npm', ['link', '@ionic/core', '--legacy-peer-deps'], { cwd: projectRoot })
});
-
- if (package === 'packages/react-router') {
- projectTasks.push({
- title: `${pkg.name}: npm link @ionic/react`,
- task: () => execa('npm', ['link', '@ionic/react', '--legacy-peer-deps'], { cwd: projectRoot })
- });
- }
}
projectTasks.push({
title: `${pkg.name}: update ionic/core dep to ${version}`,
task: () => {
- updateDependency(pkg, '@ionic/core', version);
- writePkg(package, pkg);
+
+ /**
+ * At this point, the version for the package
+ * has been changed so we need to re-fetch the
+ * package contents so we do not overwrite it.
+ */
+ const updatedPackage = readPkg(package);
+ updateDependency(updatedPackage, '@ionic/core', version);
+ writePkg(package, updatedPackage);
}
});
@@ -233,7 +243,7 @@ function prepareDevPackage(tasks, package, version) {
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
});
- if (package === 'core' || package === 'packages/react') {
+ if (package === 'core') {
projectTasks.push({
title: `${pkg.name}: npm link`,
task: () => execa('npm', ['link'], { cwd: projectRoot })
@@ -278,17 +288,6 @@ function updatePackageVersions(tasks, packages, version) {
}
});
}
-
- if (package === 'packages/react-router') {
- tasks.push({
- title: `${package} update @ionic/react dependency, if present ${dim(`(${version})`)}`,
- task: async () => {
- const pkg = readPkg(package);
- updateDependency(pkg, '@ionic/react', version);
- writePkg(package, pkg);
- }
- });
- }
});
}
@@ -320,7 +319,7 @@ function copyPackageToDist(tasks, packages) {
}
function publishPackages(tasks, packages, version, npmTag = 'latest') {
- // first verify version
+ // verify version
packages.forEach(package => {
if (package === 'core') {
return;
@@ -337,22 +336,6 @@ function publishPackages(tasks, packages, version, npmTag = 'latest') {
}
});
});
-
- // Publish
- packages.forEach(package => {
- let projectRoot = projectPath(package);
-
- if (package === 'packages/angular-server' || package === 'angular') {
- projectRoot = path.join(projectRoot, 'dist')
- }
-
- tasks.push({
- title: `${package}: publish to ${npmTag} tag`,
- task: async () => {
- await execa('npm', ['publish', '--tag', npmTag], { cwd: projectRoot });
- }
- });
- });
}
function updateDependency(pkg, dependency, version) {
@@ -382,6 +365,7 @@ function copyCDNLoader(tasks, version) {
}
module.exports = {
+ installDevPackage,
checkTestDist,
checkGit,
askNpmTag,
diff --git a/.scripts/release-dev.js b/.scripts/release-dev.js
index a5812596ae..1bf90dccf7 100644
--- a/.scripts/release-dev.js
+++ b/.scripts/release-dev.js
@@ -33,7 +33,14 @@ async function main() {
const tasks = [];
- await setPackageVersionChanges(packages, devVersion);
+ packages.forEach(package => {
+ common.installDevPackage(tasks, package);
+ });
+
+ tasks.push({
+ title: 'Set package version changes',
+ task: async () => await setPackageVersionChanges(packages, devVersion)
+ })
packages.forEach(package => {
common.prepareDevPackage(tasks, package, devVersion);
@@ -50,13 +57,14 @@ async function main() {
console.log('\n', red(err), '\n');
process.exit(1);
}
-
- orgPkg.forEach(pkg => {
- fs.writeFileSync(pkg.filePath, pkg.packageContent);
- });
}
async function askDevVersion(devVersion) {
+ const skipPrompt = process.argv.find(arg => arg === '--skip-prompt');
+ if (skipPrompt) {
+ console.log(`\n--skip-prompt was passed. Skipping dev build prompt.`)
+ return true;
+ }
const prompts = [
{
@@ -78,9 +86,6 @@ async function setPackageVersionChanges(packages, version) {
if (package !== 'core') {
const pkg = common.readPkg(package);
common.updateDependency(pkg, '@ionic/core', version);
- if(package === 'packages/react-router') {
- common.updateDependency(pkg, '@ionic/react', version);
- }
common.writePkg(package, pkg);
}
const projectRoot = common.projectPath(package);
diff --git a/angular/src/index.ts b/angular/src/index.ts
index c95f811ff4..bbcce8c154 100644
--- a/angular/src/index.ts
+++ b/angular/src/index.ts
@@ -52,6 +52,7 @@ export {
mdTransitionAnimation,
setupConfig,
IonicSwiper,
+ IonicSlides,
getPlatforms,
isPlatform,
getTimeGivenProgression,
diff --git a/core/src/components/action-sheet/action-sheet.ios.scss b/core/src/components/action-sheet/action-sheet.ios.scss
index 4bd0540db8..d2c06d96bf 100644
--- a/core/src/components/action-sheet/action-sheet.ios.scss
+++ b/core/src/components/action-sheet/action-sheet.ios.scss
@@ -22,11 +22,6 @@
text-align: $action-sheet-ios-text-align;
}
-.action-sheet-wrapper {
- @include margin(var(--ion-safe-area-top, 0), auto, var(--ion-safe-area-bottom, 0), auto);
-}
-
-
// iOS Action Sheet Container
// ---------------------------------------------------
diff --git a/core/src/components/action-sheet/action-sheet.scss b/core/src/components/action-sheet/action-sheet.scss
index a19e11be19..bdc813571a 100644
--- a/core/src/components/action-sheet/action-sheet.scss
+++ b/core/src/components/action-sheet/action-sheet.scss
@@ -67,7 +67,7 @@
.action-sheet-wrapper {
@include position(null, 0, 0, 0);
- @include margin(auto);
+ @include margin(var(--ion-safe-area-top, 0), auto, var(--ion-safe-area-bottom, 0), auto);
@include transform(translate3d(0, 100%, 0));
display: block;
diff --git a/core/src/components/slides/IonicSlides.ts b/core/src/components/slides/IonicSlides.ts
new file mode 100644
index 0000000000..3184f0e2e4
--- /dev/null
+++ b/core/src/components/slides/IonicSlides.ts
@@ -0,0 +1,102 @@
+export const IonicSlides = (opts: any) => {
+ const { swiper, extendParams } = opts;
+ const slidesParams: any = {
+ effect: undefined,
+ direction: 'horizontal',
+ initialSlide: 0,
+ loop: false,
+ parallax: false,
+ slidesPerView: 1,
+ spaceBetween: 0,
+ speed: 300,
+ slidesPerColumn: 1,
+ slidesPerColumnFill: 'column',
+ slidesPerGroup: 1,
+ centeredSlides: false,
+ slidesOffsetBefore: 0,
+ slidesOffsetAfter: 0,
+ touchEventsTarget: 'container',
+ autoplay: false,
+ freeMode: false,
+ freeModeMomentum: true,
+ freeModeMomentumRatio: 1,
+ freeModeMomentumBounce: true,
+ freeModeMomentumBounceRatio: 1,
+ freeModeMomentumVelocityRatio: 1,
+ freeModeSticky: false,
+ freeModeMinimumVelocity: 0.02,
+ autoHeight: false,
+ setWrapperSize: false,
+ zoom: {
+ maxRatio: 3,
+ minRatio: 1,
+ toggle: false,
+ },
+ touchRatio: 1,
+ touchAngle: 45,
+ simulateTouch: true,
+ touchStartPreventDefault: false,
+ shortSwipes: true,
+ longSwipes: true,
+ longSwipesRatio: 0.5,
+ longSwipesMs: 300,
+ followFinger: true,
+ threshold: 0,
+ touchMoveStopPropagation: true,
+ touchReleaseOnEdges: false,
+ iOSEdgeSwipeDetection: false,
+ iOSEdgeSwipeThreshold: 20,
+ resistance: true,
+ resistanceRatio: 0.85,
+ watchSlidesProgress: false,
+ watchSlidesVisibility: false,
+ preventClicks: true,
+ preventClicksPropagation: true,
+ slideToClickedSlide: false,
+ loopAdditionalSlides: 0,
+ noSwiping: true,
+ runCallbacksOnInit: true,
+ coverflowEffect: {
+ rotate: 50,
+ stretch: 0,
+ depth: 100,
+ modifier: 1,
+ slideShadows: true
+ },
+ flipEffect: {
+ slideShadows: true,
+ limitRotation: true
+ },
+ cubeEffect: {
+ slideShadows: true,
+ shadow: true,
+ shadowOffset: 20,
+ shadowScale: 0.94
+ },
+ fadeEffect: {
+ crossFade: false
+ },
+ a11y: {
+ prevSlideMessage: 'Previous slide',
+ nextSlideMessage: 'Next slide',
+ firstSlideMessage: 'This is the first slide',
+ lastSlideMessage: 'This is the last slide'
+ }
+ }
+
+ if (swiper.pagination) {
+ slidesParams.pagination = {
+ type: 'bullets',
+ clickable: false,
+ hideOnClick: false,
+ }
+ }
+
+ if (swiper.scrollbar) {
+ slidesParams.scrollbar = {
+ hide: true
+ }
+ }
+
+ extendParams(slidesParams);
+}
diff --git a/core/src/components/slides/IonicSwiper.ts b/core/src/components/slides/IonicSwiper.ts
index da107b5af1..0c3b918110 100644
--- a/core/src/components/slides/IonicSwiper.ts
+++ b/core/src/components/slides/IonicSwiper.ts
@@ -120,6 +120,8 @@ export const IonicSwiper = {
name: 'ionic',
on: {
afterInit(swiper: any) {
+ console.warn('[Deprecation Warning]: The IonicSwiper module has been deprecated in favor of the IonSlides module. This change was made to better support the Swiper 7 release. The IonicSwiper module will be removed in Ionic 7.0. See https://ionicframework.com/docs/api/slides#migration for revised migration steps.');
+
setupSwiperInIonic(swiper);
}
}
diff --git a/core/src/components/virtual-scroll/readme.md b/core/src/components/virtual-scroll/readme.md
index 826ddf8a7f..b19d60d6b2 100644
--- a/core/src/components/virtual-scroll/readme.md
+++ b/core/src/components/virtual-scroll/readme.md
@@ -11,15 +11,15 @@ This guide will go over the recommended virtual scrolling packages for each fram
## Angular
-For virtual scrolling options in Ionic Angular, please see [Angular Virtual Scroll Guide](../angular/virtual-scroll).
+For virtual scrolling options in Ionic Angular, please see [Angular Virtual Scroll Guide](../../angular/virtual-scroll).
## React
-For virtual scrolling options in Ionic React, please see [React Virtual Scroll Guide](../react/virtual-scroll).
+For virtual scrolling options in Ionic React, please see [React Virtual Scroll Guide](../../react/virtual-scroll).
## Vue
-For virtual scrolling options in Ionic Vue, please see [Vue Virtual Scroll Guide](../vue/virtual-scroll).
+For virtual scrolling options in Ionic Vue, please see [Vue Virtual Scroll Guide](../../vue/virtual-scroll).
------
diff --git a/core/src/css/ionic-swiper.scss b/core/src/css/ionic-swiper.scss
index 8ebba40c5b..24e5eaaf4e 100644
--- a/core/src/css/ionic-swiper.scss
+++ b/core/src/css/ionic-swiper.scss
@@ -4,7 +4,7 @@
// Slides
// --------------------------------------------------
-.swiper-container {
+.swiper {
// These values are the same for iOS and MD
// We just do not add a .md or .ios class beforehand
@@ -33,11 +33,11 @@
// Pagination Bullets
// --------------------------------------------------
-.swiper-pagination-bullet {
+.swiper .swiper-pagination-bullet {
background: var(--bullet-background);
}
-.swiper-pagination-bullet-active {
+.swiper .swiper-pagination-bullet-active {
background: var(--bullet-background-active);
}
@@ -45,36 +45,29 @@
// Pagination Progress Bar
// --------------------------------------------------
-.swiper-pagination-progressbar {
+.swiper .swiper-pagination-progressbar {
background: var(--progress-bar-background);
}
-.swiper-pagination-progressbar .swiper-pagination-progressbar-fill {
+.swiper .swiper-pagination-progressbar .swiper-pagination-progressbar-fill {
background: var(--progress-bar-background-active);
}
// Scrollbar
// --------------------------------------------------
-.swiper-scrollbar {
+.swiper .swiper-scrollbar {
background: var(--scroll-bar-background);
}
-.swiper-scrollbar-drag {
+.swiper .swiper-scrollbar-drag {
background: var(--scroll-bar-background-active);
}
// Slide
// --------------------------------------------------
-ion-slide {
- display: block;
-
- width: 100%;
- height: 100%;
-}
-
-.slide-zoom {
+.swiper .slide-zoom {
display: block;
width: 100%;
@@ -82,7 +75,7 @@ ion-slide {
text-align: center;
}
-.swiper-slide {
+.swiper .swiper-slide {
// Center slide text vertically
display: flex;
@@ -101,7 +94,7 @@ ion-slide {
box-sizing: border-box;
}
-.swiper-slide img {
+.swiper .swiper-slide img {
width: auto;
max-width: 100%;
height: auto;
diff --git a/core/src/index.ts b/core/src/index.ts
index d6940bd4e9..a550c74161 100644
--- a/core/src/index.ts
+++ b/core/src/index.ts
@@ -14,3 +14,4 @@ export { LIFECYCLE_WILL_ENTER, LIFECYCLE_DID_ENTER, LIFECYCLE_WILL_LEAVE, LIFECY
export { menuController } from './utils/menu-controller';
export { alertController, actionSheetController, modalController, loadingController, pickerController, popoverController, toastController } from './utils/overlays';
export { IonicSwiper } from './components/slides/IonicSwiper';
+export { IonicSlides } from './components/slides/IonicSlides';
diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts
index fa7f705611..caf32399e8 100644
--- a/packages/react/src/components/index.ts
+++ b/packages/react/src/components/index.ts
@@ -25,6 +25,7 @@ export {
mdTransitionAnimation,
setupConfig,
IonicSwiper,
+ IonicSlides,
getTimeGivenProgression,
// TYPES
diff --git a/packages/vue-router/__tests__/locationHistory.spec.ts b/packages/vue-router/__tests__/locationHistory.spec.ts
index f451e0eb35..aacb8a31a9 100644
--- a/packages/vue-router/__tests__/locationHistory.spec.ts
+++ b/packages/vue-router/__tests__/locationHistory.spec.ts
@@ -84,7 +84,7 @@ describe('Location History', () => {
locationHistory.add({ pathname: '/home' });
locationHistory.add({ pathname: '/login' });
- expect(locationHistory.canGoBack(1)).toEqual(true);
- expect(locationHistory.canGoBack(2)).toEqual(false);
+ expect(locationHistory.canGoBack(1, 0, 1)).toEqual(true);
+ expect(locationHistory.canGoBack(2, 0, 1)).toEqual(false);
});
});
diff --git a/packages/vue-router/src/locationHistory.ts b/packages/vue-router/src/locationHistory.ts
index ac3d8ac6f6..879994eb02 100644
--- a/packages/vue-router/src/locationHistory.ts
+++ b/packages/vue-router/src/locationHistory.ts
@@ -133,7 +133,18 @@ export const createLocationHistory = () => {
}
const previous = () => locationHistory[locationHistory.length - 2] || last();
const last = () => locationHistory[locationHistory.length - 1];
- const canGoBack = (deep: number = 1) => locationHistory.length > deep;
+
+ /**
+ * With the introduction of router.go support, we no longer remove
+ * items from locationHistory as they may be needed again in the future.
+ * As a result, we need to look at the current position in location history
+ * to see if users can navigate back n pages. Previously we were checking
+ * the length of locationHistory, but that only worked since we were pruning
+ * the array.
+ */
+ const canGoBack = (deep: number = 1, initialHistory: number, currentHistory: number) => {
+ return currentHistory - deep >= initialHistory;
+ }
const getFirstRouteInfoForTab = (tab: string): RouteInfo | undefined => {
const tabHistory = getTabsHistory(tab);
diff --git a/packages/vue-router/src/router.ts b/packages/vue-router/src/router.ts
index f9c3a3b37d..415155bd2f 100644
--- a/packages/vue-router/src/router.ts
+++ b/packages/vue-router/src/router.ts
@@ -301,7 +301,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
const getCurrentRouteInfo = () => currentRouteInfo;
- const canGoBack = (deep: number = 1) => locationHistory.canGoBack(deep);
+ const canGoBack = (deep: number = 1) => locationHistory.canGoBack(deep, initialHistoryPosition, currentHistoryPosition);
const navigate = (navigationOptions: ExternalNavigationOptions) => {
const { routerAnimation, routerDirection, routerLink } = navigationOptions;
diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts
index 0ebfe7f089..f2cab23242 100644
--- a/packages/vue/src/index.ts
+++ b/packages/vue/src/index.ts
@@ -42,6 +42,7 @@ export {
mdTransitionAnimation,
setupConfig,
IonicSwiper,
+ IonicSlides,
getPlatforms,
isPlatform,
menuController,
diff --git a/packages/vue/test-app/src/App.vue b/packages/vue/test-app/src/App.vue
index 1e01091702..0f088ec216 100644
--- a/packages/vue/test-app/src/App.vue
+++ b/packages/vue/test-app/src/App.vue
@@ -15,4 +15,4 @@ export default defineComponent({
IonRouterOutlet
}
});
-
\ No newline at end of file
+
diff --git a/packages/vue/test-app/tests/unit/routing.spec.ts b/packages/vue/test-app/tests/unit/routing.spec.ts
index cbd42e4bc8..d793cd1bae 100644
--- a/packages/vue/test-app/tests/unit/routing.spec.ts
+++ b/packages/vue/test-app/tests/unit/routing.spec.ts
@@ -8,7 +8,8 @@ import {
IonTabs,
IonTabBar,
IonTabButton,
- IonLabel
+ IonLabel,
+ useIonRouter
} from '@ionic/vue';
import { onBeforeRouteLeave } from 'vue-router';
import { waitForRouter } from './utils';
@@ -548,4 +549,117 @@ describe('Routing', () => {
expect(wrapper.findComponent(Page2).exists()).toBe(false);
expect(wrapper.findComponent(Page3).exists()).toBe(false);
});
+
+ // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24109
+ it('canGoBack() should return the correct value', async () => {
+ const Page = {
+ components: { IonPage },
+ template: ``
+ }
+ const Page2 = {
+ components: { IonPage },
+ template: ``
+ }
+ const AppWithInject = {
+ components: { IonApp, IonRouterOutlet },
+ template: '',
+ setup() {
+ const ionRouter = useIonRouter();
+ return { ionRouter }
+ }
+ }
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/', component: Page }
+ { path: '/page2', component: Page2 }
+ ]
+ });
+
+ router.push('/');
+ await router.isReady();
+ const wrapper = mount(AppWithInject, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const ionRouter = wrapper.vm.ionRouter;
+ expect(ionRouter.canGoBack()).toEqual(false);
+
+ router.push('/page2');
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(true);
+
+ router.back();
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(false);
+ });
+
+ // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24109
+ it('canGoBack() should return the correct value when using router.go', async () => {
+ const Page = {
+ components: { IonPage },
+ template: ``
+ }
+ const Page2 = {
+ components: { IonPage },
+ template: ``
+ }
+ const Page3 = {
+ components: { IonPage },
+ template: ``
+ }
+ const AppWithInject = {
+ components: { IonApp, IonRouterOutlet },
+ template: '',
+ setup() {
+ const ionRouter = useIonRouter();
+ return { ionRouter }
+ }
+ }
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/', component: Page }
+ { path: '/page2', component: Page2 },
+ { path: '/page3', component: Page3 },
+ ]
+ });
+
+ router.push('/');
+ await router.isReady();
+ const wrapper = mount(AppWithInject, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const ionRouter = wrapper.vm.ionRouter;
+ expect(ionRouter.canGoBack()).toEqual(false);
+
+ router.push('/page2');
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(true);
+
+ router.push('/page3');
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(true);
+
+ router.go(-2);
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(false);
+
+ router.go(2);
+ await waitForRouter();
+
+ expect(ionRouter.canGoBack()).toEqual(true);
+ });
});