diff --git a/packages/vue/test/base/src/router/index.ts b/packages/vue/test/base/src/router/index.ts index ce5e63de52e..8d094cc9b18 100644 --- a/packages/vue/test/base/src/router/index.ts +++ b/packages/vue/test/base/src/router/index.ts @@ -200,6 +200,10 @@ const routes: Array = [ path: '/tabs-basic', component: () => import('@/views/TabsBasic.vue') }, + { + path: '/tabs-standalone', + component: () => import('@/views/TabsStandalone.vue') + }, { path: '/tabs-search-params/', component: () => import('@/views/tabs-search-params/TabsSearchParams.vue'), diff --git a/packages/vue/test/base/src/views/Home.vue b/packages/vue/test/base/src/views/Home.vue index b8fbfdf04e7..505d5295bb0 100644 --- a/packages/vue/test/base/src/views/Home.vue +++ b/packages/vue/test/base/src/views/Home.vue @@ -53,6 +53,9 @@ Tabs with Basic Navigation + + Tab Bar without Tabs + Tabs with Similar Route Prefixes diff --git a/packages/vue/test/base/src/views/TabsStandalone.vue b/packages/vue/test/base/src/views/TabsStandalone.vue new file mode 100644 index 00000000000..0415ff555f0 --- /dev/null +++ b/packages/vue/test/base/src/views/TabsStandalone.vue @@ -0,0 +1,44 @@ + + + diff --git a/packages/vue/test/base/tests/e2e/playwright/tab-bar-standalone.spec.ts b/packages/vue/test/base/tests/e2e/playwright/tab-bar-standalone.spec.ts new file mode 100644 index 00000000000..c4076db86a8 --- /dev/null +++ b/packages/vue/test/base/tests/e2e/playwright/tab-bar-standalone.spec.ts @@ -0,0 +1,54 @@ +import { test, expect } from './utils/test-base'; +import { ionPageVisible, tabClick } from './utils/test-utils'; + +/** + * https://github.com/ionic-team/ionic-framework/issues/30361 + * ion-tab-bar used without ion-tabs or ion-router-outlet, with the app + * navigating by method from the tab buttons. + */ +test.describe('Tab Bar: standalone', () => { + test('should switch tabs on click without errors', async ({ page }) => { + const errors: string[] = []; + page.on('pageerror', (err) => errors.push(err.message)); + page.on('console', (msg) => { + if (msg.type() === 'error' || msg.type() === 'warning') { + errors.push(msg.text()); + } + }); + + await page.goto('/tabs-standalone'); + await ionPageVisible(page, 'tabs-standalone'); + + const tab1 = page.locator('ion-tab-button#tab-button-tab1'); + const tab2 = page.locator('ion-tab-button#tab-button-tab2'); + + await expect(tab1).toHaveClass(/tab-selected/); + await expect(page.locator('#active-tab')).toHaveText('tab1'); + + await tabClick(page, 'tab2'); + + await expect(tab2).toHaveClass(/tab-selected/); + await expect(tab1).not.toHaveClass(/tab-selected/); + await expect(page.locator('#active-tab')).toHaveText('tab2'); + // With no router outlet, a tab button must not change the URL itself. + await expect(page).toHaveURL(/\/tabs-standalone(\?|$)/); + + await tabClick(page, 'tab1'); + + await expect(tab1).toHaveClass(/tab-selected/); + await expect(tab2).not.toHaveClass(/tab-selected/); + await expect(page.locator('#active-tab')).toHaveText('tab1'); + + expect(errors).toEqual([]); + }); + + test('should navigate by method from a tab button', async ({ page }) => { + await page.goto('/tabs-standalone'); + await ionPageVisible(page, 'tabs-standalone'); + + await tabClick(page, 'routing'); + + await ionPageVisible(page, 'routing'); + await expect(page).toHaveURL(/\/routing(\?|$)/); + }); +});