@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.
@@ -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 of pie-modal so that
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 ({ page, mount }) => {
16
- await mount(
17
- PieIconButton,
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 NOT display a close button', async ({ mount, page }) => {
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
+ });