Skip to content

Commit

Permalink
fix(popover): dismissing nested popover via backdrop now works (#24957)
Browse files Browse the repository at this point in the history
resolves #24954
  • Loading branch information
liamdebeasi authored Mar 21, 2022
1 parent 63842a2 commit 9e84ef7
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 198 deletions.
19 changes: 19 additions & 0 deletions core/src/components/popover/popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@
z-index: $z-index-overlay;
}

/**
* With nested popovers, only the popover that
* was first presented has a popover. This is the
* parent popover and allows us to easily
* track all nested popovers from a single backdrop.
* As a result, nested popovers do not have backdrops
* and their container should not be clickable.
* This ensures that users can click the parent backdrop
* while still interacting with the nested popover inner
* content.
*/
:host(.popover-nested) {
pointer-events: none;
}

:host(.popover-nested) .popover-wrapper {
pointer-events: auto;
}

:host(.overlay-hidden) {
display: none;
}
Expand Down
180 changes: 180 additions & 0 deletions core/src/components/popover/test/nested/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import type { E2EPage } from '@stencil/core/testing';
import { newE2EPage } from '@stencil/core/testing';

describe('nested popovers', () => {
let page: E2EPage;

beforeEach(async () => {
page = await newE2EPage({ url: '/src/components/popover/test/nested?ionic:_testing=true' });
});

test('nested popover should render correctly', async () => {
const screenshotCompares = [];

const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');

await page.click('#first-trigger');

await ionPopoverDidPresent.next();

const parentPopover = await page.find('.parent-popover');
expect(parentPopover).not.toHaveClass('overlay-hidden');

await page.click('#open-with-popover');

await ionPopoverDidPresent.next();

const nestedPopover = await page.find('.child-popover-one');
expect(nestedPopover).not.toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});

test('nested popover should dismiss when clicking backdrop', async () => {
const screenshotCompares = [];

const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');

await page.click('#first-trigger');

await ionPopoverDidPresent.next();

const parentPopover = await page.find('.parent-popover');
expect(parentPopover).not.toHaveClass('overlay-hidden');

await page.click('#open-with-popover');

await ionPopoverDidPresent.next();

const nestedPopover = await page.find('.child-popover-one');
expect(nestedPopover).not.toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

const backdrop = await page.find('.parent-popover >>> ion-backdrop');
await backdrop.click();

await ionPopoverDidDismiss.next();

const nestedPopoverAgain = await page.find('.child-popover-one');
expect(nestedPopoverAgain).toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});

test('nested popover should be interactive', async () => {
const screenshotCompares = [];

const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');

await page.click('#first-trigger');

await ionPopoverDidPresent.next();

await page.click('#share-popover');

await ionPopoverDidPresent.next();

await page.click('#share-other-popover');

await ionPopoverDidPresent.next();

const nestedPopover = await page.find('.child-popover-three');
expect(nestedPopover).not.toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});

test('clicking backdrop should dismiss multiple levels of popover', async () => {
const screenshotCompares = [];

const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');

await page.click('#first-trigger');

await ionPopoverDidPresent.next();

await page.click('#share-popover');

await ionPopoverDidPresent.next();

await page.click('#share-other-popover');

await ionPopoverDidPresent.next();

const backdrop = await page.find('.parent-popover >>> ion-backdrop');
await backdrop.click();

await ionPopoverDidDismiss.next();

const nestedPopoverOne = await page.find('.child-popover-one');
expect(nestedPopoverOne).toHaveClass('overlay-hidden');

const nestedPopoverTwo = await page.find('.child-popover-three');
expect(nestedPopoverTwo).toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});

test('should dismiss sibling nested popover when another sibling popover is opened', async () => {
const screenshotCompares = [];

const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');

await page.click('#first-trigger');

await ionPopoverDidPresent.next();

await page.click('#open-with-popover');

await ionPopoverDidPresent.next();

const openWithPopover = await page.find('.child-popover-one');
expect(openWithPopover).not.toHaveClass('overlay-hidden');

await page.click('#share-popover');

await ionPopoverDidPresent.next();
await ionPopoverDidDismiss.next();

const openWithPopoverAgain = await page.find('.child-popover-one');
const sharePopover = await page.find('.child-popover-two');
expect(openWithPopoverAgain).toHaveClass('overlay-hidden');
expect(sharePopover).not.toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

const backdrop = await page.find('.parent-popover >>> ion-backdrop');
await backdrop.click();

await ionPopoverDidDismiss.next();

const nestedPopoverAgain = await page.find('.child-popover-one');
expect(nestedPopoverAgain).toHaveClass('overlay-hidden');

screenshotCompares.push(await page.compareScreenshot());

for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
})
});
Loading

0 comments on commit 9e84ef7

Please sign in to comment.