Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Event() ionDragEnd!: EventEmitter<ModalDragEventDetail>;

@Watch('breakpoints')
breakpointsChanged(breakpoints: number[] | undefined) {
if (breakpoints !== undefined) {
this.sortedBreakpoints = breakpoints.sort((a, b) => a - b);
Expand Down
47 changes: 47 additions & 0 deletions core/src/components/modal/test/sheet/modal.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,51 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
expect(Object.keys(dragEndEvent.detail).length).toBe(5);
});
});

test.describe(title('sheet modal: late breakpoints binding'), () => {
test('should not crash when swiped after breakpoints are set after the modal loads', async ({ page }) => {
const pageErrors: string[] = [];
page.on('pageerror', (err) => pageErrors.push(err.message));

await page.setContent(
`
<ion-modal initial-breakpoint="1">
<ion-content>Modal Content</ion-content>
</ion-modal>
`,
config
);

const modal = page.locator('ion-modal');

/**
* Simulates a JS framework (e.g. Angular with zoneless change detection)
* applying the `breakpoints` binding after the web component has finished
* loading. `setContent` resolves after `componentDidLoad`, so this lands
* too late for the manual `breakpointsChanged()` call in `componentDidLoad`
* to pick it up
*/
await modal.evaluate((el: HTMLIonModalElement) => {
el.breakpoints = [0, 1];
});

const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');

await modal.evaluate((el: HTMLIonModalElement) => el.present());
await ionModalDidPresent.next();

// Swiping the sheet down should snap it to breakpoint 0 and dismiss it
// without throwing an error
const handle = page.locator('ion-modal .modal-handle');
await expect(handle).toBeVisible();
await dragElementBy(handle, page, 0, 600);

// Flush any pending errors from the gesture's end handler
await page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))));
expect(pageErrors).toEqual([]);

await ionModalDidDismiss.next();
});
});
});
Loading