@justeattakeaway/pie-modal 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +33 -0
- package/README.md +12 -8
- package/dist/index.js +238 -155
- package/dist/react.js +127 -125
- package/dist/types/packages/components/pie-modal/src/defs.d.ts +37 -1
- package/dist/types/packages/components/pie-modal/src/defs.d.ts.map +1 -1
- package/dist/types/packages/components/pie-modal/src/index.d.ts +38 -11
- package/dist/types/packages/components/pie-modal/src/index.d.ts.map +1 -1
- package/dist/types/packages/components/pie-modal/src/react.d.ts +3 -2
- package/dist/types/packages/components/pie-modal/src/react.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/defs.ts +48 -1
- package/src/index.ts +144 -41
- package/src/modal.scss +230 -20
- package/test/component/pie-modal.spec.ts +335 -57
- package/test/helpers/index.ts +2 -0
- package/test/visual/pie-modal.spec.ts +227 -60
|
@@ -1,63 +1,18 @@
|
|
|
1
1
|
import { test } from '@sand4rt/experimental-ct-web';
|
|
2
2
|
import percySnapshot from '@percy/playwright';
|
|
3
|
-
import {
|
|
4
|
-
WebComponentTestWrapper,
|
|
5
|
-
} from '@justeattakeaway/pie-webc-testing/src/helpers/components/web-component-test-wrapper/WebComponentTestWrapper.ts';
|
|
6
3
|
import { PieIconButton } from '@justeattakeaway/pie-icon-button';
|
|
4
|
+
import { PieButton } from '@justeattakeaway/pie-button';
|
|
5
|
+
import { positions } from '@/defs.ts';
|
|
7
6
|
import { PieModal } from '@/index';
|
|
8
7
|
import { ModalProps, sizes } from '@/defs';
|
|
9
|
-
import { createScrollablePageHTML, renderTestPieModal } from '../helpers/index.ts';
|
|
10
8
|
|
|
11
|
-
// Mount any components that are used inside
|
|
9
|
+
// Mount any components that are used inside pie-modal so that
|
|
12
10
|
// they have been registered with the browser before the tests run.
|
|
13
11
|
// There is likely a nicer way to do this but this will temporarily
|
|
14
12
|
// unblock tests.
|
|
15
|
-
test.beforeEach(async ({
|
|
16
|
-
await mount(
|
|
17
|
-
|
|
18
|
-
{},
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// Removing the element so it's not present in the tests (but is still registered in the DOM)
|
|
22
|
-
await page.evaluate(() => {
|
|
23
|
-
const element : Element | null = document.querySelector('pie-icon-button');
|
|
24
|
-
element?.remove();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('Should not be able to scroll when modal is open', async ({ page, mount }) => {
|
|
29
|
-
const modalComponent = renderTestPieModal();
|
|
30
|
-
|
|
31
|
-
await mount(
|
|
32
|
-
WebComponentTestWrapper,
|
|
33
|
-
{
|
|
34
|
-
props: {
|
|
35
|
-
pageMode: true,
|
|
36
|
-
},
|
|
37
|
-
slots: {
|
|
38
|
-
component: modalComponent,
|
|
39
|
-
pageMarkup: createScrollablePageHTML(),
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Scroll 800 pixels down the page
|
|
45
|
-
await page.mouse.wheel(0, 800);
|
|
46
|
-
|
|
47
|
-
await page.waitForTimeout(3000); // The mouse.wheel function causes scrolling, but doesn't wait for the scroll to finish before returning.
|
|
48
|
-
|
|
49
|
-
await percySnapshot(page, 'Modal - scroll locking');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('should not render when isOpen = false', async ({ page, mount }) => {
|
|
53
|
-
await mount(PieModal, {
|
|
54
|
-
props: {
|
|
55
|
-
heading: 'This is a modal heading',
|
|
56
|
-
isOpen: false,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
await percySnapshot(page, 'Modal - isOpen = false');
|
|
13
|
+
test.beforeEach(async ({ mount }) => {
|
|
14
|
+
await (await mount(PieButton)).unmount();
|
|
15
|
+
await (await mount(PieIconButton)).unmount();
|
|
61
16
|
});
|
|
62
17
|
|
|
63
18
|
sizes.forEach((size) => {
|
|
@@ -67,14 +22,19 @@ sizes.forEach((size) => {
|
|
|
67
22
|
heading: 'This is a modal heading',
|
|
68
23
|
isOpen: true,
|
|
69
24
|
size,
|
|
70
|
-
|
|
25
|
+
leadingAction: {
|
|
26
|
+
text: 'Confirm',
|
|
27
|
+
variant: 'primary',
|
|
28
|
+
ariaLabel: 'Confirmation text',
|
|
29
|
+
},
|
|
30
|
+
} as ModalProps,
|
|
71
31
|
});
|
|
72
32
|
|
|
73
33
|
await percySnapshot(page, `Modal - size = ${size}`);
|
|
74
34
|
});
|
|
75
35
|
});
|
|
76
36
|
|
|
77
|
-
test.describe('`isFullWidthBelowMid`', () => {
|
|
37
|
+
test.describe('Prop: `isFullWidthBelowMid`', () => {
|
|
78
38
|
test.describe('when true', () => {
|
|
79
39
|
test('should be full width for a modal with size = medium', async ({ page, mount }) => {
|
|
80
40
|
await mount(PieModal, {
|
|
@@ -83,7 +43,12 @@ test.describe('`isFullWidthBelowMid`', () => {
|
|
|
83
43
|
isFullWidthBelowMid: true,
|
|
84
44
|
isOpen: true,
|
|
85
45
|
size: 'medium',
|
|
86
|
-
|
|
46
|
+
leadingAction: {
|
|
47
|
+
text: 'Confirm',
|
|
48
|
+
variant: 'primary',
|
|
49
|
+
ariaLabel: 'Confirmation text',
|
|
50
|
+
},
|
|
51
|
+
} as ModalProps,
|
|
87
52
|
});
|
|
88
53
|
|
|
89
54
|
await percySnapshot(page, 'Modal - isFullWidthBelowMid = true, size = medium');
|
|
@@ -96,7 +61,12 @@ test.describe('`isFullWidthBelowMid`', () => {
|
|
|
96
61
|
isFullWidthBelowMid: true,
|
|
97
62
|
isOpen: true,
|
|
98
63
|
size: 'small',
|
|
99
|
-
|
|
64
|
+
leadingAction: {
|
|
65
|
+
text: 'Confirm',
|
|
66
|
+
variant: 'primary',
|
|
67
|
+
ariaLabel: 'Confirmation text',
|
|
68
|
+
},
|
|
69
|
+
} as ModalProps,
|
|
100
70
|
});
|
|
101
71
|
|
|
102
72
|
await percySnapshot(page, 'Modal - isFullWidthBelowMid = true, size = small');
|
|
@@ -113,7 +83,12 @@ test.describe('`isFullWidthBelowMid`', () => {
|
|
|
113
83
|
isFullWidthBelowMid: false,
|
|
114
84
|
isOpen: true,
|
|
115
85
|
size,
|
|
116
|
-
|
|
86
|
+
leadingAction: {
|
|
87
|
+
text: 'Confirm',
|
|
88
|
+
variant: 'primary',
|
|
89
|
+
ariaLabel: 'Confirmation text',
|
|
90
|
+
},
|
|
91
|
+
} as ModalProps,
|
|
117
92
|
});
|
|
118
93
|
|
|
119
94
|
await percySnapshot(page, `Modal - isFullWidthBelowMid = false, size = ${size}`);
|
|
@@ -122,7 +97,7 @@ test.describe('`isFullWidthBelowMid`', () => {
|
|
|
122
97
|
});
|
|
123
98
|
});
|
|
124
99
|
|
|
125
|
-
test.describe('`isDismissible`', () => {
|
|
100
|
+
test.describe('Prop: `isDismissible`', () => {
|
|
126
101
|
test.describe('when true', () => {
|
|
127
102
|
test('should display a close button within the modal', async ({ mount, page }) => {
|
|
128
103
|
await mount(PieModal, {
|
|
@@ -130,7 +105,12 @@ test.describe('`isDismissible`', () => {
|
|
|
130
105
|
heading: 'This is a modal heading',
|
|
131
106
|
isDismissible: true,
|
|
132
107
|
isOpen: true,
|
|
133
|
-
|
|
108
|
+
leadingAction: {
|
|
109
|
+
text: 'Confirm',
|
|
110
|
+
variant: 'primary',
|
|
111
|
+
ariaLabel: 'Confirmation text',
|
|
112
|
+
},
|
|
113
|
+
} as ModalProps,
|
|
134
114
|
});
|
|
135
115
|
|
|
136
116
|
await percySnapshot(page, 'Modal with close button displayed - isDismissible: `true`');
|
|
@@ -138,16 +118,203 @@ test.describe('`isDismissible`', () => {
|
|
|
138
118
|
});
|
|
139
119
|
|
|
140
120
|
test.describe('when false', () => {
|
|
141
|
-
test('should
|
|
121
|
+
test('should not display a close button', async ({ mount, page }) => {
|
|
142
122
|
await mount(PieModal, {
|
|
143
123
|
props: {
|
|
144
124
|
heading: 'This is a modal heading',
|
|
145
125
|
isDismissible: false,
|
|
146
126
|
isOpen: true,
|
|
147
|
-
|
|
127
|
+
leadingAction: {
|
|
128
|
+
text: 'Confirm',
|
|
129
|
+
variant: 'primary',
|
|
130
|
+
ariaLabel: 'Confirmation text',
|
|
131
|
+
},
|
|
132
|
+
} as ModalProps,
|
|
148
133
|
});
|
|
149
134
|
|
|
150
135
|
await percySnapshot(page, 'Modal without close button - isDismissible: `false`');
|
|
151
136
|
});
|
|
152
137
|
});
|
|
153
138
|
});
|
|
139
|
+
|
|
140
|
+
const directions = ['ltr', 'rtl', 'auto'] as const;
|
|
141
|
+
|
|
142
|
+
test.describe('Prop: `hasBackButton`', () => {
|
|
143
|
+
directions.forEach((dir) => {
|
|
144
|
+
test.describe('when true', () => {
|
|
145
|
+
test(`should display a back button within the modal and dir is ${dir}`, async ({ mount, page }) => {
|
|
146
|
+
await mount(PieModal, {
|
|
147
|
+
props: {
|
|
148
|
+
heading: 'This is a modal heading',
|
|
149
|
+
hasBackButton: true,
|
|
150
|
+
isOpen: true,
|
|
151
|
+
dir,
|
|
152
|
+
leadingAction: {
|
|
153
|
+
text: 'Confirm',
|
|
154
|
+
variant: 'primary',
|
|
155
|
+
ariaLabel: 'Confirmation text',
|
|
156
|
+
},
|
|
157
|
+
} as ModalProps,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await percySnapshot(page, `Modal with back button displayed - hasBackButton: ${true} - dir: ${dir}`);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test.describe('when false', () => {
|
|
165
|
+
test(`should not display a back button and dir is ${dir}`, async ({ mount, page }) => {
|
|
166
|
+
await mount(PieModal, {
|
|
167
|
+
props: {
|
|
168
|
+
heading: 'This is a modal heading',
|
|
169
|
+
hasBackButton: false,
|
|
170
|
+
isOpen: true,
|
|
171
|
+
dir,
|
|
172
|
+
leadingAction: {
|
|
173
|
+
text: 'Confirm',
|
|
174
|
+
variant: 'primary',
|
|
175
|
+
ariaLabel: 'Confirmation text',
|
|
176
|
+
},
|
|
177
|
+
} as ModalProps,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
await percySnapshot(page, `Modal without back button - hasBackButton: ${false} - dir: ${dir}`);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test.describe('Prop: `heading`', () => {
|
|
187
|
+
test('should display & render long headings correctly', async ({ page, mount }) => {
|
|
188
|
+
await mount(PieModal, {
|
|
189
|
+
props: {
|
|
190
|
+
heading: 'This is a modal heading but super long and should span multiple lines, hopefully this should never happen on production!',
|
|
191
|
+
isOpen: true,
|
|
192
|
+
size: 'medium',
|
|
193
|
+
hasBackButton: true,
|
|
194
|
+
isDismissible: true,
|
|
195
|
+
leadingAction: {
|
|
196
|
+
text: 'Confirm',
|
|
197
|
+
variant: 'primary',
|
|
198
|
+
ariaLabel: 'Confirmation text',
|
|
199
|
+
},
|
|
200
|
+
} as ModalProps,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await percySnapshot(page, 'Modal - Long heading');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test.describe('Prop: `isLoading`', () => {
|
|
208
|
+
test('should display loading spinner when `isLoading` is true', async ({ mount, page }) => {
|
|
209
|
+
await mount(PieModal, {
|
|
210
|
+
props: {
|
|
211
|
+
heading: 'This is a modal heading',
|
|
212
|
+
hasBackButton: true,
|
|
213
|
+
isDismissible: true,
|
|
214
|
+
isOpen: true,
|
|
215
|
+
isLoading: true,
|
|
216
|
+
leadingAction: {
|
|
217
|
+
text: 'Confirm',
|
|
218
|
+
variant: 'primary',
|
|
219
|
+
ariaLabel: 'Confirmation text',
|
|
220
|
+
},
|
|
221
|
+
} as ModalProps,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await percySnapshot(page, `Modal displays loading spinner - isLoading: ${true}`);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test.describe('Prop: `leadingAction`', () => {
|
|
229
|
+
test.describe('when prop is passed into component', () => {
|
|
230
|
+
test('should display `leadingAction` when props are passed correctly', async ({ mount, page }) => {
|
|
231
|
+
await mount(PieModal, {
|
|
232
|
+
props: {
|
|
233
|
+
heading: 'This is a modal heading',
|
|
234
|
+
hasBackButton: true,
|
|
235
|
+
isDismissible: true,
|
|
236
|
+
isOpen: true,
|
|
237
|
+
leadingAction: {
|
|
238
|
+
text: 'Confirm',
|
|
239
|
+
variant: 'primary',
|
|
240
|
+
ariaLabel: 'Confirmation text',
|
|
241
|
+
},
|
|
242
|
+
} as ModalProps,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
await percySnapshot(page, 'Modal displays leadingAction');
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test.describe('when prop is provided but the optional child properties of `leadingAction` are not provided', () => {
|
|
250
|
+
test('should falls back to defaults', async ({ mount, page }) => {
|
|
251
|
+
await mount(PieModal, {
|
|
252
|
+
props: {
|
|
253
|
+
heading: 'This is a modal heading',
|
|
254
|
+
hasBackButton: true,
|
|
255
|
+
isDismissible: true,
|
|
256
|
+
isOpen: true,
|
|
257
|
+
leadingAction: {
|
|
258
|
+
text: 'Confirm',
|
|
259
|
+
},
|
|
260
|
+
} as ModalProps,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
await percySnapshot(page, 'Modal falls back to default property `primary`');
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test.describe('when prop is provided but the `text` child property of `leadingAction` is empty', () => {
|
|
268
|
+
test('should not render leadingAction markup', async ({ mount, page }) => {
|
|
269
|
+
await mount(PieModal, {
|
|
270
|
+
props: {
|
|
271
|
+
heading: 'This is a modal heading',
|
|
272
|
+
hasBackButton: true,
|
|
273
|
+
isDismissible: true,
|
|
274
|
+
isOpen: true,
|
|
275
|
+
leadingAction: {
|
|
276
|
+
text: '',
|
|
277
|
+
},
|
|
278
|
+
} as ModalProps,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
await percySnapshot(page, 'Modal will not render `leadingAction` button when `text` is empty');
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test.describe('when prop is not passed into component', () => {
|
|
286
|
+
test('should not display `leadingAction`', async ({ mount, page }) => {
|
|
287
|
+
await mount(PieModal, {
|
|
288
|
+
props: {
|
|
289
|
+
heading: 'This is a modal heading',
|
|
290
|
+
hasBackButton: true,
|
|
291
|
+
isDismissible: true,
|
|
292
|
+
isOpen: true,
|
|
293
|
+
} as ModalProps,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await percySnapshot(page, 'Modal does not display leadingAction');
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test.describe('`position`', () => {
|
|
302
|
+
positions.forEach((position) => {
|
|
303
|
+
test(`should be positioned in the correct part of the page when position is: ${position}`, async ({ mount, page }) => {
|
|
304
|
+
await mount(PieModal, {
|
|
305
|
+
props: {
|
|
306
|
+
heading: 'This is a modal heading',
|
|
307
|
+
isOpen: true,
|
|
308
|
+
position,
|
|
309
|
+
leadingAction: {
|
|
310
|
+
text: 'Confirm',
|
|
311
|
+
variant: 'primary',
|
|
312
|
+
ariaLabel: 'Confirmation text',
|
|
313
|
+
},
|
|
314
|
+
} as ModalProps,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await percySnapshot(page, `Modal position: ${position}`);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
});
|