diff --git a/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts index c236fc8d2b0..cca426a6fab 100644 --- a/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts +++ b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts @@ -17,6 +17,7 @@ test.describe('datetime-button: switching to correct view', () => { expect(datetime).toHaveJSProperty('presentation', 'date-time'); await page.locator('#date-button').click(); + await page.waitForChanges(); expect(datetime).toHaveJSProperty('presentation', 'date'); }); @@ -25,6 +26,7 @@ test.describe('datetime-button: switching to correct view', () => { expect(datetime).toHaveJSProperty('presentation', 'date-time'); await page.locator('#time-button').click(); + await page.waitForChanges(); expect(datetime).toHaveJSProperty('presentation', 'time'); }); diff --git a/core/src/components/modal/test/inline/modal.e2e.ts b/core/src/components/modal/test/inline/modal.e2e.ts index c215da0a4be..75f0546f0f9 100644 --- a/core/src/components/modal/test/inline/modal.e2e.ts +++ b/core/src/components/modal/test/inline/modal.e2e.ts @@ -21,4 +21,44 @@ test.describe('modal: inline', () => { expect(await page.screenshot()).toMatchSnapshot(`modal-inline-dismiss-${page.getSnapshotSettings()}.png`); }); + + test('presenting should create a single root element with the ion-page class', async ({ page, skip }, testInfo) => { + skip.mode('md'); + skip.rtl(); + + testInfo.annotations.push({ + type: 'issue', + description: 'https://github.com/ionic-team/ionic-framework/issues/26117', + }); + + await page.setContent(` + + + + + + `); + + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss'); + const modal = page.locator('ion-modal'); + + await page.locator('#date-button').click(); + await ionModalDidPresent.next(); + + // Verifies that the host element exists with the .ion-page class + expect(await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.className)).toContain('ion-page'); + + await modal.evaluate((el: HTMLIonModalElement) => el.dismiss()); + await ionModalDidDismiss.next(); + + await page.locator('#date-button').click(); + await ionModalDidPresent.next(); + + // Verifies that presenting the overlay again does not create a new host element + expect(await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.className)).toContain('ion-page'); + expect( + await modal.evaluate((el: HTMLIonModalElement) => el.firstElementChild!.firstElementChild!.className) + ).not.toContain('ion-page'); + }); }); diff --git a/core/src/utils/framework-delegate.ts b/core/src/utils/framework-delegate.ts index d3b6ff382c7..af4f24a2be7 100644 --- a/core/src/utils/framework-delegate.ts +++ b/core/src/utils/framework-delegate.ts @@ -87,14 +87,22 @@ export const CoreDelegate = () => { await new Promise((resolve) => componentOnReady(el, resolve)); } else if (BaseComponent.children.length > 0) { - // If there is no component, then we need to create a new parent - // element to apply the css classes to. - const el = BaseComponent.ownerDocument?.createElement('div'); - cssClasses.forEach((c) => el.classList.add(c)); - // Move each child from the original template to the new parent element. - el.append(...BaseComponent.children); - // Append the new parent element to the original parent element. - BaseComponent.appendChild(el); + const root = BaseComponent.children[0] as HTMLElement; + if (!root.classList.contains('ion-delegate-host')) { + /** + * If the root element is not a delegate host, it means + * that the overlay has not been presented yet and we need + * to create the containing element with the specified classes. + */ + const el = BaseComponent.ownerDocument?.createElement('div'); + // Add a class to track if the root element was created by the delegate. + el.classList.add('ion-delegate-host'); + cssClasses.forEach((c) => el.classList.add(c)); + // Move each child from the original template to the new parent element. + el.append(...BaseComponent.children); + // Append the new parent element to the original parent element. + BaseComponent.appendChild(el); + } } /**