diff --git a/core/src/components/modal/test/dismiss-behavior/index.html b/core/src/components/modal/test/dismiss-behavior/index.html new file mode 100644 index 00000000000..448b84457d9 --- /dev/null +++ b/core/src/components/modal/test/dismiss-behavior/index.html @@ -0,0 +1,97 @@ + + + + + Modal - Dismiss Behavior + + + + + + + + + + +
+ + + Modal - Dismiss Behavior + + + + + + +
+
+ + + + diff --git a/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts b/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts new file mode 100644 index 00000000000..7969317c447 --- /dev/null +++ b/core/src/components/modal/test/dismiss-behavior/modal.e2e.ts @@ -0,0 +1,58 @@ +import { expect } from '@playwright/test'; +import { configs, test } from '@utils/test/playwright'; + +configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('modal: dismiss behavior'), () => { + test.describe(title('modal: default dismiss'), () => { + test('should dismiss the last presented modal when the default dismiss button is clicked', async ({ page }) => { + await page.goto('/src/components/modal/test/dismiss-behavior', config); + + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#present-first-modal'); + await ionModalDidPresent.next(); + const firstModal = page.locator('ion-modal[data-testid="modal-1"]'); + await expect(firstModal).toBeVisible(); + + await page.click('#present-next-modal'); + await ionModalDidPresent.next(); + const secondModal = page.locator('ion-modal[data-testid="modal-2"]'); + await expect(secondModal).toBeVisible(); + + await page.click('ion-modal[data-testid="modal-2"] ion-button.dismiss-default'); + await ionModalDidDismiss.next(); + await secondModal.waitFor({ state: 'detached' }); + + await expect(firstModal).toBeVisible(); + await expect(secondModal).toBeHidden(); + }); + }); + + test.describe(title('modal: dismiss by id'), () => { + test('should dismiss the last presented modal when the dismiss by id button is clicked', async ({ page }) => { + await page.goto('/src/components/modal/test/dismiss-behavior', config); + + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + + await page.click('#present-first-modal'); + await ionModalDidPresent.next(); + const firstModal = page.locator('ion-modal[data-testid="modal-1"]'); + await expect(firstModal).toBeVisible(); + + await page.click('#present-next-modal'); + await ionModalDidPresent.next(); + const secondModal = page.locator('ion-modal[data-testid="modal-2"]'); + await expect(secondModal).toBeVisible(); + + await page.click('ion-modal[data-testid="modal-2"] ion-button.dismiss-by-id'); + await ionModalDidDismiss.next(); + await secondModal.waitFor({ state: 'detached' }); + + await expect(firstModal).toBeVisible(); + await expect(secondModal).toBeHidden(); + }); + }); + }); +}); diff --git a/core/src/components/modal/test/modal-id.spec.tsx b/core/src/components/modal/test/modal-id.spec.tsx index 43f1a9eaa16..93b6d34fa91 100644 --- a/core/src/components/modal/test/modal-id.spec.tsx +++ b/core/src/components/modal/test/modal-id.spec.tsx @@ -1,7 +1,7 @@ +import { h } from '@stencil/core'; import { newSpecPage } from '@stencil/core/testing'; import { Modal } from '../modal'; -import { h } from '@stencil/core'; describe('modal: id', () => { it('modal should be assigned an incrementing id', async () => { @@ -52,4 +52,21 @@ describe('modal: id', () => { const alert = page.body.querySelector('ion-modal')!; expect(alert.id).toBe(id); }); + + it('should allow multiple modals with the same id', async () => { + const sharedId = 'shared-modal-id'; + + const page = await newSpecPage({ + components: [Modal], + template: () => [ + , + , + ], + }); + + const modals = page.body.querySelectorAll('ion-modal'); + expect(modals.length).toBe(2); + expect(modals[0].id).toBe(sharedId); + expect(modals[1].id).toBe(sharedId); + }); }); diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index 472a57559d3..59b341a7d52 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -473,7 +473,9 @@ export const getPresentedOverlay = ( id?: string ): HTMLIonOverlayElement | undefined => { const overlays = getPresentedOverlays(doc, overlayTag); - return id === undefined ? overlays[overlays.length - 1] : overlays.find((o) => o.id === id); + // If no id is provided, return the last presented overlay + // Otherwise, return the last overlay with the given id + return (id === undefined ? overlays : overlays.filter((o: HTMLIonOverlayElement) => o.id === id)).slice(-1)[0]; }; /**