Skip to content

Commit 3c08630

Browse files
committed
test(modal): adding test for sheet modals that should help us prevent this regression in the future
1 parent 4c77460 commit 3c08630

File tree

8 files changed

+267
-1
lines changed

8 files changed

+267
-1
lines changed

core/src/components/modal/test/sheet/index.html

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,53 @@
151151
>
152152
Backdrop is inactive
153153
</button>
154+
<button id="present-inline-sheet-modal">Present Inline Sheet Modal</button>
155+
156+
<div id="inline-sheet-modal-container">
157+
<ion-modal id="inline-sheet-modal" mode="md">
158+
<ion-content>
159+
<ion-searchbar id="inline-sheet-searchbar" placeholder="Search"></ion-searchbar>
160+
<ion-list>
161+
<ion-item>
162+
<ion-avatar slot="start">
163+
<ion-img src="https://i.pravatar.cc/300?u=b"></ion-img>
164+
</ion-avatar>
165+
<ion-label>
166+
<h2>Connor Smith</h2>
167+
<p>Sales Rep</p>
168+
</ion-label>
169+
</ion-item>
170+
<ion-item>
171+
<ion-avatar slot="start">
172+
<ion-img src="https://i.pravatar.cc/300?u=a"></ion-img>
173+
</ion-avatar>
174+
<ion-label>
175+
<h2>Daniel Smith</h2>
176+
<p>Product Designer</p>
177+
</ion-label>
178+
</ion-item>
179+
<ion-item>
180+
<ion-avatar slot="start">
181+
<ion-img src="https://i.pravatar.cc/300?u=d"></ion-img>
182+
</ion-avatar>
183+
<ion-label>
184+
<h2>Greg Smith</h2>
185+
<p>Director of Operations</p>
186+
</ion-label>
187+
</ion-item>
188+
<ion-item>
189+
<ion-avatar slot="start">
190+
<ion-img src="https://i.pravatar.cc/300?u=e"></ion-img>
191+
</ion-avatar>
192+
<ion-label>
193+
<h2>Zoey Smith</h2>
194+
<p>CEO</p>
195+
</ion-label>
196+
</ion-item>
197+
</ion-list>
198+
</ion-content>
199+
</ion-modal>
200+
</div>
154201

155202
<div class="grid">
156203
<div class="grid-item red"></div>
@@ -173,6 +220,36 @@
173220
console.log('WillDismiss', e);
174221
});
175222

223+
const inlineSheetModal = document.querySelector('#inline-sheet-modal');
224+
const inlineSheetTrigger = document.querySelector('#present-inline-sheet-modal');
225+
const inlineSheetSearchbar = document.querySelector('#inline-sheet-searchbar');
226+
227+
if (inlineSheetModal) {
228+
inlineSheetModal.initialBreakpoint = 0.2;
229+
inlineSheetModal.breakpoints = [0, 0.2, 0.75, 1];
230+
inlineSheetModal.backdropDismiss = false;
231+
inlineSheetModal.backdropBreakpoint = 0.5;
232+
inlineSheetModal.focusTrap = false;
233+
inlineSheetModal.handleBehavior = 'cycle';
234+
inlineSheetModal.presentingElement = document.querySelector('.ion-page');
235+
236+
inlineSheetModal.addEventListener('ionModalDidDismiss', () => {
237+
inlineSheetModal.isOpen = false;
238+
});
239+
240+
if (inlineSheetTrigger) {
241+
inlineSheetTrigger.addEventListener('click', () => {
242+
inlineSheetModal.isOpen = true;
243+
});
244+
}
245+
246+
if (inlineSheetSearchbar) {
247+
inlineSheetSearchbar.addEventListener('click', () => {
248+
inlineSheetModal.setCurrentBreakpoint(0.75);
249+
});
250+
}
251+
}
252+
176253
function createModal(options) {
177254
let items = '';
178255

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test.describe('Modals: Inline Sheet', () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto('/lazy/modal-sheet-inline');
6+
});
7+
8+
test('should open inline sheet modal', async ({ page }) => {
9+
await page.locator('#present-inline-sheet-modal').click();
10+
11+
await expect(page.locator('ion-modal')).toBeVisible();
12+
await expect(page.locator('#current-breakpoint')).toHaveText('0.2');
13+
await expect(page.locator('ion-modal ion-item')).toHaveCount(4);
14+
});
15+
16+
test('should expand to 0.75 breakpoint when searchbar is clicked', async ({ page }) => {
17+
await page.locator('#present-inline-sheet-modal').click();
18+
await expect(page.locator('#current-breakpoint')).toHaveText('0.2');
19+
20+
await page.locator('ion-modal ion-searchbar').click();
21+
22+
await expect(page.locator('#current-breakpoint')).toHaveText('0.75');
23+
});
24+
25+
test('should allow interacting with background content while sheet is open', async ({ page }) => {
26+
await page.locator('#present-inline-sheet-modal').click();
27+
28+
await expect(page.locator('ion-modal')).toBeVisible();
29+
30+
await page.locator('#background-action').click();
31+
32+
await expect(page.locator('#background-action-count')).toHaveText('1');
33+
});
34+
});

packages/angular/test/base/src/app/lazy/app-lazy/app.routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const routes: Routes = [
3737
{ path: 'template-form', component: TemplateFormComponent },
3838
{ path: 'modals', component: ModalComponent },
3939
{ path: 'modal-inline', loadChildren: () => import('../modal-inline').then(m => m.ModalInlineModule) },
40+
{ path: 'modal-sheet-inline', loadChildren: () => import('../modal-sheet-inline').then(m => m.ModalSheetInlineModule) },
4041
{ path: 'view-child', component: ViewChildComponent },
4142
{ path: 'keep-contents-mounted', loadChildren: () => import('../keep-contents-mounted').then(m => m.OverlayAutoMountModule) },
4243
{ path: 'overlays-inline', loadChildren: () => import('../overlays-inline').then(m => m.OverlaysInlineModule) },
@@ -90,4 +91,3 @@ export const routes: Routes = [
9091
]
9192
},
9293
];
93-
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './modal-sheet-inline.component';
2+
export * from './modal-sheet-inline.module';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { NgModule } from "@angular/core";
2+
import { RouterModule } from "@angular/router";
3+
import { ModalSheetInlineComponent } from ".";
4+
5+
@NgModule({
6+
imports: [
7+
RouterModule.forChild([
8+
{
9+
path: '',
10+
component: ModalSheetInlineComponent
11+
}
12+
])
13+
],
14+
exports: [RouterModule]
15+
})
16+
export class ModalSheetInlineRoutingModule { }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<ion-button id="present-inline-sheet-modal" (click)="presentInlineSheetModal()">
2+
Present Inline Sheet Modal
3+
</ion-button>
4+
5+
<p>
6+
Current breakpoint: <span id="current-breakpoint">{{ currentBreakpoint }}</span>
7+
</p>
8+
9+
<ion-button id="background-action" (click)="onBackgroundActionClick()">
10+
Background Action
11+
</ion-button>
12+
13+
<p>
14+
Background action count: <span id="background-action-count">{{ backgroundActionCount }}</span>
15+
</p>
16+
17+
<ion-modal
18+
#inlineSheetModal
19+
mode="md"
20+
[isOpen]="isSheetOpen"
21+
[initialBreakpoint]="0.2"
22+
[breakpoints]="breakpoints"
23+
[backdropDismiss]="false"
24+
[backdropBreakpoint]="0.5"
25+
[focusTrap]="false"
26+
handleBehavior="cycle"
27+
(ionBreakpointDidChange)="onSheetBreakpointDidChange($event)"
28+
(didDismiss)="onSheetDidDismiss()"
29+
>
30+
<ng-template>
31+
<ion-content>
32+
<ion-searchbar placeholder="Search" (click)="expandInlineSheet()"></ion-searchbar>
33+
<ion-list>
34+
<ion-item *ngFor="let contact of contacts">
35+
<ion-avatar slot="start">
36+
<ion-img [src]="contact.avatar"></ion-img>
37+
</ion-avatar>
38+
<ion-label>
39+
<h2>{{ contact.name }}</h2>
40+
<p>{{ contact.title }}</p>
41+
</ion-label>
42+
</ion-item>
43+
</ion-list>
44+
</ion-content>
45+
</ng-template>
46+
</ion-modal>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { Component, ViewChild } from "@angular/core";
2+
import { IonModal } from "@ionic/angular";
3+
4+
interface Contact {
5+
name: string;
6+
title: string;
7+
avatar: string;
8+
}
9+
10+
@Component({
11+
selector: 'app-modal-sheet-inline',
12+
templateUrl: './modal-sheet-inline.component.html',
13+
standalone: false
14+
})
15+
export class ModalSheetInlineComponent {
16+
17+
@ViewChild('inlineSheetModal', { read: IonModal }) inlineSheetModal?: IonModal;
18+
19+
readonly breakpoints: number[] = [0, 0.2, 0.75, 1];
20+
21+
readonly contacts: Contact[] = [
22+
{
23+
name: 'Connor Smith',
24+
title: 'Sales Rep',
25+
avatar: 'https://i.pravatar.cc/300?u=b'
26+
},
27+
{
28+
name: 'Daniel Smith',
29+
title: 'Product Designer',
30+
avatar: 'https://i.pravatar.cc/300?u=a'
31+
},
32+
{
33+
name: 'Greg Smith',
34+
title: 'Director of Operations',
35+
avatar: 'https://i.pravatar.cc/300?u=d'
36+
},
37+
{
38+
name: 'Zoey Smith',
39+
title: 'CEO',
40+
avatar: 'https://i.pravatar.cc/300?u=e'
41+
}
42+
];
43+
44+
isSheetOpen = false;
45+
46+
currentBreakpoint = 'closed';
47+
48+
backgroundActionCount = 0;
49+
50+
presentInlineSheetModal() {
51+
this.isSheetOpen = true;
52+
this.currentBreakpoint = '0.2';
53+
}
54+
55+
async expandInlineSheet() {
56+
const modal = this.inlineSheetModal;
57+
58+
if (!modal) {
59+
return;
60+
}
61+
62+
await modal.setCurrentBreakpoint(0.75);
63+
this.currentBreakpoint = '0.75';
64+
}
65+
66+
onSheetDidDismiss() {
67+
this.isSheetOpen = false;
68+
this.currentBreakpoint = 'closed';
69+
}
70+
71+
onSheetBreakpointDidChange(event: CustomEvent<{ breakpoint: number }>) {
72+
this.currentBreakpoint = event.detail.breakpoint.toString();
73+
}
74+
75+
onBackgroundActionClick() {
76+
this.backgroundActionCount++;
77+
}
78+
79+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { CommonModule } from "@angular/common";
2+
import { NgModule } from "@angular/core";
3+
import { IonicModule } from "@ionic/angular";
4+
import { ModalSheetInlineRoutingModule } from "./modal-sheet-inline-routing.module";
5+
import { ModalSheetInlineComponent } from "./modal-sheet-inline.component";
6+
7+
@NgModule({
8+
imports: [CommonModule, IonicModule, ModalSheetInlineRoutingModule],
9+
declarations: [ModalSheetInlineComponent],
10+
exports: [ModalSheetInlineComponent]
11+
})
12+
export class ModalSheetInlineModule { }

0 commit comments

Comments
 (0)