@ionic/core 7.5.6-dev.11700169088.140f3e6a → 7.5.6-dev.11700492285.1581ed02

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.
Files changed (68) hide show
  1. package/dist/collection/collection-manifest.json +4 -4
  2. package/dist/collection/components/accordion/test/accordion.spec.js +195 -0
  3. package/dist/collection/components/action-sheet/test/action-sheet-id.spec.js +32 -0
  4. package/dist/collection/components/action-sheet/test/basic/action-sheet.spec.js +18 -0
  5. package/dist/collection/components/alert/test/alert-id.spec.js +32 -0
  6. package/dist/collection/components/alert/test/alert.spec.js +37 -0
  7. package/dist/collection/components/back-button/test/back-button.spec.js +86 -0
  8. package/dist/collection/components/breadcrumb/test/aria.spec.js +22 -0
  9. package/dist/collection/components/breadcrumbs/test/breadcrumbs.spec.js +58 -0
  10. package/dist/collection/components/button/test/form-reference/button.spec.js +26 -0
  11. package/dist/collection/components/card/test/aria.spec.js +16 -0
  12. package/dist/collection/components/checkbox/test/checkbox.spec.js +20 -0
  13. package/dist/collection/components/datetime/test/a11y/datetime.spec.js +43 -0
  14. package/dist/collection/components/datetime/test/comparison.spec.js +43 -0
  15. package/dist/collection/components/datetime/test/data.spec.js +456 -0
  16. package/dist/collection/components/datetime/test/format.spec.js +124 -0
  17. package/dist/collection/components/datetime/test/helpers.spec.js +72 -0
  18. package/dist/collection/components/datetime/test/manipulation.spec.js +433 -0
  19. package/dist/collection/components/datetime/test/parse.spec.js +222 -0
  20. package/dist/collection/components/datetime/test/state.spec.js +114 -0
  21. package/dist/collection/components/infinite-scroll-content/test/infinite-scroll-content.spec.js +37 -0
  22. package/dist/collection/components/input/test/input.spec.js +85 -0
  23. package/dist/collection/components/input/test/item/input.spec.js +24 -0
  24. package/dist/collection/components/item/test/a11y/item.spec.js +48 -0
  25. package/dist/collection/components/loading/test/basic/loading.spec.js +16 -0
  26. package/dist/collection/components/loading/test/loading-id.spec.js +32 -0
  27. package/dist/collection/components/loading/test/loading.spec.js +37 -0
  28. package/dist/collection/components/modal/test/a11y/modal.spec.js +22 -0
  29. package/dist/collection/components/modal/test/basic/modal.spec.js +16 -0
  30. package/dist/collection/components/modal/test/can-dismiss/modal.spec.js +191 -0
  31. package/dist/collection/components/modal/test/modal-id.spec.js +32 -0
  32. package/dist/collection/components/nav/test/nav-controller.spec.js +749 -0
  33. package/dist/collection/components/picker/test/picker-id.spec.js +32 -0
  34. package/dist/collection/components/picker-column/test/picker-column-aria.spec.js +35 -0
  35. package/dist/collection/components/picker-column/test/picker-column-dynamic.spec.js +29 -0
  36. package/dist/collection/components/picker-column/test/picker-column.spec.js +17 -0
  37. package/dist/collection/components/popover/test/basic/popover.spec.js +16 -0
  38. package/dist/collection/components/popover/test/popover-id.spec.js +32 -0
  39. package/dist/collection/components/popover/test/util.spec.js +53 -0
  40. package/dist/collection/components/radio/test/radio.spec.js +46 -0
  41. package/dist/collection/components/range/test/label/range.spec.js +23 -0
  42. package/dist/collection/components/range/test/range.spec.js +205 -0
  43. package/dist/collection/components/refresher-content/test/refresher-content.spec.js +46 -0
  44. package/dist/collection/components/router/test/matching.spec.js +250 -0
  45. package/dist/collection/components/router/test/parser.spec.js +133 -0
  46. package/dist/collection/components/router/test/path.spec.js +218 -0
  47. package/dist/collection/components/router/test/router.spec.js +55 -0
  48. package/dist/collection/components/searchbar/test/searchbar.spec.js +15 -0
  49. package/dist/collection/components/segment/test/segment.spec.js +37 -0
  50. package/dist/collection/components/select/test/select.spec.js +59 -0
  51. package/dist/collection/components/textarea/test/textarea.spec.js +59 -0
  52. package/dist/collection/components/toast/test/toast-id.spec.js +32 -0
  53. package/dist/collection/components/toast/test/toast.spec.js +120 -0
  54. package/dist/collection/components/toggle/test/toggle.spec.js +55 -0
  55. package/dist/collection/global/test/config-controller.spec.js +77 -0
  56. package/dist/collection/utils/animation/test/animation.spec.js +431 -0
  57. package/dist/collection/utils/keyboard/test/keyboard-controller.spec.js +21 -0
  58. package/dist/collection/utils/keyboard/test/keyboard.spec.js +214 -0
  59. package/dist/collection/utils/sanitization/test/sanitization.spec.js +43 -0
  60. package/dist/collection/utils/test/aria.spec.js +79 -0
  61. package/dist/collection/utils/test/attributes.spec.js +53 -0
  62. package/dist/collection/utils/test/hardware-back-button.spec.js +53 -0
  63. package/dist/collection/utils/test/overlays/overlays.spec.js +102 -0
  64. package/dist/collection/utils/test/platform.spec.js +132 -0
  65. package/dist/collection/utils/test/ready.spec.js +39 -0
  66. package/dist/collection/utils/test/theme.spec.js +56 -0
  67. package/dist/docs.json +21 -21
  68. package/package.json +2 -1
@@ -0,0 +1,431 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { createAnimation } from "../animation";
5
+ import { processKeyframes } from "../animation-utils";
6
+ import { getTimeGivenProgression } from "../cubic-bezier";
7
+ describe('Animation Class', () => {
8
+ describe('play()', () => {
9
+ it('should resolve when the animation is cancelled', async () => {
10
+ // Tell Jest to expect 1 assertion for async code
11
+ expect.assertions(1);
12
+ const el = document.createElement('div');
13
+ const animation = createAnimation()
14
+ .addElement(el)
15
+ .fromTo('transform', 'translateX(0px)', 'translateX(100px)')
16
+ .duration(100000);
17
+ const animationPromise = animation.play();
18
+ animation.stop();
19
+ // Expect that the promise resolves and returns undefined
20
+ expect(animationPromise).resolves.toEqual(undefined);
21
+ });
22
+ });
23
+ describe('isRunning()', () => {
24
+ let animation;
25
+ beforeEach(() => {
26
+ animation = createAnimation();
27
+ });
28
+ it('should not be running initially', () => {
29
+ expect(animation.isRunning()).toEqual(false);
30
+ });
31
+ it('should not be running due to not having keyframes', () => {
32
+ animation.play();
33
+ expect(animation.isRunning()).toEqual(false);
34
+ });
35
+ it('should be running', () => {
36
+ const el = document.createElement('div');
37
+ animation.addElement(el);
38
+ animation.keyframes([
39
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
40
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
41
+ ]);
42
+ animation.duration(250);
43
+ animation.play();
44
+ expect(animation.isRunning()).toEqual(true);
45
+ });
46
+ it('should not be running after finishing the animation', async () => {
47
+ const el = document.createElement('div');
48
+ animation.addElement(el);
49
+ animation.keyframes([
50
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
51
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
52
+ ]);
53
+ animation.duration(250);
54
+ await animation.play();
55
+ expect(animation.isRunning()).toEqual(false);
56
+ });
57
+ it('should not be running after calling pause', () => {
58
+ const el = document.createElement('div');
59
+ animation.addElement(el);
60
+ animation.keyframes([
61
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
62
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
63
+ ]);
64
+ animation.duration(250);
65
+ animation.play();
66
+ expect(animation.isRunning()).toEqual(true);
67
+ animation.pause();
68
+ expect(animation.isRunning()).toEqual(false);
69
+ });
70
+ it('should not be running when doing progress steps', () => {
71
+ const el = document.createElement('div');
72
+ animation.addElement(el);
73
+ animation.keyframes([
74
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
75
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
76
+ ]);
77
+ animation.duration(250);
78
+ animation.play();
79
+ animation.progressStart();
80
+ expect(animation.isRunning()).toEqual(false);
81
+ });
82
+ it('should be running after calling progressEnd', () => {
83
+ const el = document.createElement('div');
84
+ animation.addElement(el);
85
+ animation.keyframes([
86
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
87
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
88
+ ]);
89
+ animation.duration(250);
90
+ animation.play();
91
+ animation.progressStart();
92
+ animation.progressEnd(1, 0);
93
+ expect(animation.isRunning()).toEqual(true);
94
+ });
95
+ it('should not be running after playing to beginning', async () => {
96
+ const el = document.createElement('div');
97
+ animation.addElement(el);
98
+ animation.keyframes([
99
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
100
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
101
+ ]);
102
+ animation.duration(250);
103
+ await animation.play();
104
+ animation.progressStart();
105
+ animation.progressEnd(0, 0);
106
+ await new Promise((resolve) => {
107
+ animation.onFinish(() => {
108
+ expect(animation.isRunning()).toEqual(false);
109
+ resolve();
110
+ });
111
+ });
112
+ });
113
+ });
114
+ describe('addElement()', () => {
115
+ let animation;
116
+ beforeEach(() => {
117
+ animation = createAnimation();
118
+ });
119
+ it('should add 1 element', () => {
120
+ const el = document.createElement('p');
121
+ animation.addElement(el);
122
+ expect(animation.elements.length).toEqual(1);
123
+ });
124
+ it('should add multiple elements', () => {
125
+ const els = [document.createElement('p'), document.createElement('p'), document.createElement('p')];
126
+ animation.addElement(els);
127
+ expect(animation.elements.length).toEqual(els.length);
128
+ });
129
+ it('should not error when trying to add null or undefined', () => {
130
+ const el = document.createElement('p');
131
+ animation.addElement(el);
132
+ animation.addElement(null);
133
+ animation.addElement(undefined);
134
+ expect(animation.elements.length).toEqual(1);
135
+ });
136
+ });
137
+ describe('addAnimation()', () => {
138
+ let animation;
139
+ beforeEach(() => {
140
+ animation = createAnimation();
141
+ });
142
+ it('should add 1 animation', () => {
143
+ const newAnimation = createAnimation();
144
+ animation.addAnimation(newAnimation);
145
+ expect(animation.childAnimations.length).toEqual(1);
146
+ });
147
+ it('should add multiple animations', () => {
148
+ animation.addAnimation([createAnimation(), createAnimation(), createAnimation()]);
149
+ expect(animation.childAnimations.length).toEqual(3);
150
+ });
151
+ it('should not error when trying to add null or undefined', () => {
152
+ animation.addAnimation(null);
153
+ animation.addAnimation(undefined);
154
+ expect(animation.childAnimations.length).toEqual(0);
155
+ });
156
+ });
157
+ describe('Animation Keyframes', () => {
158
+ let animation;
159
+ beforeEach(() => {
160
+ animation = createAnimation();
161
+ });
162
+ it('should generate a keyframe', () => {
163
+ animation.keyframes([
164
+ { transform: 'scale(1)', opacity: 1, offset: 0 },
165
+ { transform: 'scale(0.5)', opacity: 0.5, offset: 0.5 },
166
+ { transform: 'scale(0)', opacity: 0, offset: 1 },
167
+ ]);
168
+ expect(animation.getKeyframes().length).toEqual(3);
169
+ });
170
+ it('should convert properties for CSS Animations', () => {
171
+ const processedKeyframes = processKeyframes([
172
+ { borderRadius: '0px', easing: 'ease-in', offset: 0 },
173
+ { borderRadius: '4px', easing: 'ease-out', offset: 1 },
174
+ ]);
175
+ expect(processedKeyframes).toEqual([
176
+ { 'border-radius': '0px', 'animation-timing-function': 'ease-in', offset: 0 },
177
+ { 'border-radius': '4px', 'animation-timing-function': 'ease-out', offset: 1 },
178
+ ]);
179
+ });
180
+ it('should set the from keyframe properly', () => {
181
+ animation.from('opacity', 0).from('background', 'red').from('color', 'purple');
182
+ const keyframes = animation.getKeyframes();
183
+ expect(keyframes.length).toEqual(1);
184
+ expect(keyframes[0]).toEqual({
185
+ opacity: 0,
186
+ color: 'purple',
187
+ background: 'red',
188
+ offset: 0,
189
+ });
190
+ });
191
+ it('should set the to keyframe properly', () => {
192
+ animation.to('opacity', 0).to('background', 'red').to('color', 'purple');
193
+ const keyframes = animation.getKeyframes();
194
+ expect(keyframes.length).toEqual(1);
195
+ expect(keyframes[0]).toEqual({
196
+ opacity: 0,
197
+ color: 'purple',
198
+ background: 'red',
199
+ offset: 1,
200
+ });
201
+ });
202
+ it('should mix keyframes and fromTo properly', () => {
203
+ animation
204
+ .keyframes([
205
+ { offset: 0, background: 'red' },
206
+ { offset: 0.99, background: 'blue' },
207
+ { offset: 1, background: 'green' },
208
+ ])
209
+ .fromTo('opacity', 0, 1);
210
+ const keyframes = animation.getKeyframes();
211
+ expect(keyframes.length).toEqual(3);
212
+ expect(keyframes[0]).toEqual({
213
+ opacity: 0,
214
+ background: 'red',
215
+ offset: 0,
216
+ });
217
+ expect(keyframes[1]).toEqual({
218
+ background: 'blue',
219
+ offset: 0.99,
220
+ });
221
+ expect(keyframes[2]).toEqual({
222
+ opacity: 1,
223
+ background: 'green',
224
+ offset: 1,
225
+ });
226
+ });
227
+ });
228
+ describe('Animation Config Methods', () => {
229
+ let animation;
230
+ beforeEach(() => {
231
+ animation = createAnimation();
232
+ });
233
+ it('should get "linear" when easing not set', () => {
234
+ expect(animation.getEasing()).toEqual('linear');
235
+ });
236
+ it('should get parent easing when child easing is not set', () => {
237
+ const childAnimation = createAnimation();
238
+ animation.addAnimation(childAnimation).easing('ease-in-out');
239
+ expect(childAnimation.getEasing()).toEqual('ease-in-out');
240
+ });
241
+ it('should get prefer child easing over parent easing', () => {
242
+ const childAnimation = createAnimation();
243
+ childAnimation.easing('linear');
244
+ animation.addAnimation(childAnimation).easing('ease-in-out');
245
+ expect(childAnimation.getEasing()).toEqual('linear');
246
+ });
247
+ it('should get linear easing when forceLinear is set', () => {
248
+ animation.easing('ease-in-out');
249
+ animation.progressStart(true);
250
+ expect(animation.getEasing()).toEqual('linear');
251
+ animation.progressEnd(0, 0);
252
+ expect(animation.getEasing()).toEqual('ease-in-out');
253
+ });
254
+ it('should get 0 when duration not set', () => {
255
+ expect(animation.getDuration()).toEqual(0);
256
+ });
257
+ it('should get parent duration when child duration is not set', () => {
258
+ const childAnimation = createAnimation();
259
+ animation.addAnimation(childAnimation).duration(500);
260
+ expect(childAnimation.getDuration()).toEqual(500);
261
+ });
262
+ it('should get prefer child duration over parent duration', () => {
263
+ const childAnimation = createAnimation();
264
+ childAnimation.duration(500);
265
+ animation.addAnimation(childAnimation).duration(1000);
266
+ expect(childAnimation.getDuration()).toEqual(500);
267
+ });
268
+ it('should get 0 when delay not set', () => {
269
+ expect(animation.getDelay()).toEqual(0);
270
+ });
271
+ it('should get parent delay when child delay is not set', () => {
272
+ const childAnimation = createAnimation();
273
+ animation.addAnimation(childAnimation).delay(500);
274
+ expect(childAnimation.getDelay()).toEqual(500);
275
+ });
276
+ it('should get prefer child delay over parent delay', () => {
277
+ const childAnimation = createAnimation();
278
+ childAnimation.delay(500);
279
+ animation.addAnimation(childAnimation).delay(1000);
280
+ expect(childAnimation.getDelay()).toEqual(500);
281
+ });
282
+ it('should get 1 when iterations not set', () => {
283
+ expect(animation.getIterations()).toEqual(1);
284
+ });
285
+ it('should get parent iterations when child iterations is not set', () => {
286
+ const childAnimation = createAnimation();
287
+ animation.addAnimation(childAnimation).iterations(2);
288
+ expect(childAnimation.getIterations()).toEqual(2);
289
+ });
290
+ it('should get prefer child iterations over parent iterations', () => {
291
+ const childAnimation = createAnimation();
292
+ childAnimation.iterations(2);
293
+ animation.addAnimation(childAnimation).iterations(1);
294
+ expect(childAnimation.getIterations()).toEqual(2);
295
+ });
296
+ it('should get "both" when fill not set', () => {
297
+ expect(animation.getFill()).toEqual('both');
298
+ });
299
+ it('should get parent fill when child fill is not set', () => {
300
+ const childAnimation = createAnimation();
301
+ animation.addAnimation(childAnimation).fill('both');
302
+ expect(childAnimation.getFill()).toEqual('both');
303
+ });
304
+ it('should get prefer child fill over parent fill', () => {
305
+ const childAnimation = createAnimation();
306
+ childAnimation.fill('none');
307
+ animation.addAnimation(childAnimation).fill('forwards');
308
+ expect(childAnimation.getFill()).toEqual('none');
309
+ });
310
+ it('should get "normal" when direction not set', () => {
311
+ expect(animation.getDirection()).toEqual('normal');
312
+ });
313
+ it('should get parent direction when child direction is not set', () => {
314
+ const childAnimation = createAnimation();
315
+ animation.addAnimation(childAnimation).direction('alternate');
316
+ expect(childAnimation.getDirection()).toEqual('alternate');
317
+ });
318
+ it('should get prefer child direction over parent direction', () => {
319
+ const childAnimation = createAnimation();
320
+ childAnimation.direction('alternate-reverse');
321
+ animation.addAnimation(childAnimation).direction('normal');
322
+ expect(childAnimation.getDirection()).toEqual('alternate-reverse');
323
+ });
324
+ });
325
+ });
326
+ describe('cubic-bezier conversion', () => {
327
+ describe('should properly get a time value (x value) given a progression value (y value)', () => {
328
+ it('cubic-bezier(0.32, 0.72, 0, 1)', () => {
329
+ const equation = [
330
+ [0, 0],
331
+ [0.32, 0.72],
332
+ [0, 1],
333
+ [1, 1],
334
+ ];
335
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.5), [
336
+ 0.16,
337
+ ]);
338
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.97), [
339
+ 0.56,
340
+ ]);
341
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.33), [
342
+ 0.11,
343
+ ]);
344
+ });
345
+ it('cubic-bezier(1, 0, 0.68, 0.28)', () => {
346
+ const equation = [
347
+ [0, 0],
348
+ [1, 0],
349
+ [0.68, 0.28],
350
+ [1, 1],
351
+ ];
352
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.08), [
353
+ 0.6,
354
+ ]);
355
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.5), [
356
+ 0.84,
357
+ ]);
358
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.94), [
359
+ 0.98,
360
+ ]);
361
+ });
362
+ it('cubic-bezier(0.4, 0, 0.6, 1)', () => {
363
+ const equation = [
364
+ [0, 0],
365
+ [0.4, 0],
366
+ [0.6, 1],
367
+ [1, 1],
368
+ ];
369
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.39), [
370
+ 0.43,
371
+ ]);
372
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.03), [
373
+ 0.11,
374
+ ]);
375
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.89), [
376
+ 0.78,
377
+ ]);
378
+ });
379
+ it('cubic-bezier(0, 0, 0.2, 1)', () => {
380
+ const equation = [
381
+ [0, 0],
382
+ [0, 0],
383
+ [0.2, 1],
384
+ [1, 1],
385
+ ];
386
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.95), [
387
+ 0.71,
388
+ ]);
389
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.1), [
390
+ 0.03,
391
+ ]);
392
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.7), [
393
+ 0.35,
394
+ ]);
395
+ });
396
+ it('cubic-bezier(0.32, 0.72, 0, 1) (with out of bounds progression)', () => {
397
+ const equation = [
398
+ [0, 0],
399
+ [0.05, 0.2],
400
+ [0.14, 1.72],
401
+ [1, 1],
402
+ ];
403
+ expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.32)[0]).toBeUndefined();
404
+ expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], -0.32)[0]).toBeUndefined();
405
+ });
406
+ it('cubic-bezier(0.21, 1.71, 0.88, 0.9) (multiple solutions)', () => {
407
+ const equation = [
408
+ [0, 0],
409
+ [0.21, 1.71],
410
+ [0.88, 0.9],
411
+ [1, 1],
412
+ ];
413
+ shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.02), [0.35, 0.87]);
414
+ });
415
+ it('cubic-bezier(0.32, 0.72, 0, 1) (with out of bounds progression)', () => {
416
+ const equation = [
417
+ [0, 0],
418
+ [0.05, 0.2],
419
+ [0.14, 1.72],
420
+ [1, 1],
421
+ ];
422
+ expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.32)).toEqual([]);
423
+ expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], -0.32)).toEqual([]);
424
+ });
425
+ });
426
+ });
427
+ const shouldApproximatelyEqual = (givenValues, expectedValues) => {
428
+ givenValues.forEach((givenValue, i) => {
429
+ expect(Math.abs(expectedValues[i] - givenValue)).toBeLessThanOrEqual(0.01);
430
+ });
431
+ };
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { createKeyboardController } from "../keyboard-controller";
5
+ describe('Keyboard Controller', () => {
6
+ it('should update isKeyboardVisible', async () => {
7
+ const keyboardCtrl = await createKeyboardController();
8
+ window.dispatchEvent(new Event('keyboardWillShow'));
9
+ expect(keyboardCtrl.isKeyboardVisible()).toBe(true);
10
+ window.dispatchEvent(new Event('keyboardWillHide'));
11
+ expect(keyboardCtrl.isKeyboardVisible()).toBe(false);
12
+ });
13
+ it('should run the callback', async () => {
14
+ const callbackMock = jest.fn();
15
+ await createKeyboardController(callbackMock);
16
+ window.dispatchEvent(new Event('keyboardWillShow'));
17
+ expect(callbackMock).toHaveBeenCalledWith(true, undefined);
18
+ window.dispatchEvent(new Event('keyboardWillHide'));
19
+ expect(callbackMock).toHaveBeenCalledWith(false, undefined);
20
+ });
21
+ });
@@ -0,0 +1,214 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { copyVisualViewport, setKeyboardClose, setKeyboardOpen, keyboardDidClose, keyboardDidOpen, keyboardDidResize, resetKeyboardAssist, startKeyboardAssist, trackViewportChanges, KEYBOARD_DID_OPEN, KEYBOARD_DID_CLOSE, } from "../keyboard";
5
+ const mockVisualViewport = (win, visualViewport = { width: 320, height: 568 }, layoutViewport = { innerWidth: 320, innerHeight: 568 }) => {
6
+ win.visualViewport = {
7
+ width: 320,
8
+ height: 568,
9
+ offsetTop: 0,
10
+ offsetLeft: 0,
11
+ pageTop: 0,
12
+ pageLeft: 0,
13
+ scale: 1,
14
+ onresize: undefined,
15
+ onscroll: undefined,
16
+ };
17
+ win.visualViewport = Object.assign(win.visualViewport, visualViewport);
18
+ win = Object.assign(win, layoutViewport);
19
+ const mockDispatchEvent = jest.fn();
20
+ win.dispatchEvent = mockDispatchEvent;
21
+ trackViewportChanges(win);
22
+ return {
23
+ win,
24
+ mockDispatchEvent,
25
+ };
26
+ };
27
+ const mockCapacitor = (win) => {
28
+ win.Capacitor = {
29
+ isPluginAvailable: () => false,
30
+ };
31
+ };
32
+ const resizeVisualViewport = (win, visualViewport = {}) => {
33
+ win.visualViewport = Object.assign(win.visualViewport, visualViewport);
34
+ if (win.visualViewport.onresize) {
35
+ win.visualViewport.onresize({});
36
+ }
37
+ else {
38
+ trackViewportChanges(win);
39
+ }
40
+ };
41
+ const resizeLayoutViewport = (win, layoutViewport = {}) => {
42
+ win = Object.assign(win, { innerWidth: layoutViewport.width, innerHeight: layoutViewport.height });
43
+ };
44
+ describe('Keyboard Assist Tests', () => {
45
+ describe('copyVisualViewport()', () => {
46
+ it('should properly copy the visual viewport', () => {
47
+ const visualViewport = {
48
+ width: 100,
49
+ height: 200,
50
+ offsetTop: 5,
51
+ offsetLeft: 10,
52
+ pageTop: 0,
53
+ pageLeft: 0,
54
+ scale: 2,
55
+ };
56
+ const copiedViewport = copyVisualViewport(visualViewport);
57
+ visualViewport.width = 400;
58
+ visualViewport.height = 800;
59
+ visualViewport.scale = 3;
60
+ visualViewport.offsetTop = 0;
61
+ expect(copiedViewport.width).toEqual(100);
62
+ expect(copiedViewport.height).toEqual(200);
63
+ expect(copiedViewport.scale).toEqual(2);
64
+ expect(copiedViewport.offsetTop).toEqual(5);
65
+ });
66
+ });
67
+ describe('setKeyboardOpen()', () => {
68
+ it('should dispatch the keyboard open event on the window', () => {
69
+ const mockDispatchEvent = jest.fn();
70
+ window.dispatchEvent = mockDispatchEvent;
71
+ setKeyboardOpen(window);
72
+ expect(mockDispatchEvent.mock.calls.length).toEqual(1);
73
+ expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
74
+ });
75
+ });
76
+ describe('setKeyboardClose()', () => {
77
+ it('should dispatch the keyboard close event on the window', () => {
78
+ const mockDispatchEvent = jest.fn();
79
+ window.dispatchEvent = mockDispatchEvent;
80
+ setKeyboardClose(window);
81
+ expect(mockDispatchEvent.mock.calls.length).toEqual(1);
82
+ expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_CLOSE);
83
+ });
84
+ });
85
+ describe('keyboardDidOpen()', () => {
86
+ beforeEach(() => {
87
+ resetKeyboardAssist();
88
+ mockVisualViewport(window);
89
+ });
90
+ it('should return true when visual viewport height < layout viewport height and meets or exceeds the keyboard threshold', () => {
91
+ resizeVisualViewport(window, { height: 200 });
92
+ expect(keyboardDidOpen()).toEqual(true);
93
+ });
94
+ it('should return true if the layout and visual viewports resize', () => {
95
+ resizeLayoutViewport(window, { width: 320, height: 300 });
96
+ resizeVisualViewport(window, { width: 320, height: 300 });
97
+ expect(keyboardDidOpen()).toEqual(true);
98
+ });
99
+ it('should return false when visual viewport height < layout viewport heigh but does not meet the keyboard threshold', () => {
100
+ resizeVisualViewport(window, { height: 500 });
101
+ expect(keyboardDidOpen()).toEqual(false);
102
+ });
103
+ it('should return false on orientation change', () => {
104
+ resizeVisualViewport(window, { width: 320, height: 250 });
105
+ resizeVisualViewport(window, { width: 250, height: 320 });
106
+ expect(keyboardDidOpen()).toEqual(false);
107
+ });
108
+ it('should return false when both the visual and layout viewports change', () => {
109
+ resizeVisualViewport(window, { width: 250, height: 320 });
110
+ expect(keyboardDidOpen()).toEqual(false);
111
+ });
112
+ it('should return true when the keyboard shows even if the user is zoomed in', () => {
113
+ // User zooms in
114
+ resizeVisualViewport(window, { width: 160, height: 284, scale: 2 });
115
+ // User taps input and keyboard appears
116
+ resizeVisualViewport(window, { width: 160, height: 184, scale: 2 });
117
+ expect(keyboardDidOpen()).toEqual(true);
118
+ });
119
+ });
120
+ describe('keyboardDidClose()', () => {
121
+ beforeEach(() => {
122
+ resetKeyboardAssist();
123
+ mockVisualViewport(window);
124
+ });
125
+ it('should return false when keyboard is not open', () => {
126
+ expect(keyboardDidClose(window)).toEqual(false);
127
+ });
128
+ it('should return false when keyboard is open but visual viewport !== layout viewport', () => {
129
+ resizeVisualViewport(window, { width: 320, height: 250 });
130
+ setKeyboardOpen(window);
131
+ expect(keyboardDidClose(window)).toEqual(false);
132
+ });
133
+ it('should return true when keyboard is open and viewport === layout viewport', () => {
134
+ resizeVisualViewport(window, { width: 320, height: 250 });
135
+ setKeyboardOpen(window);
136
+ resizeVisualViewport(window, { width: 320, height: 568 });
137
+ expect(keyboardDidClose(window)).toEqual(true);
138
+ });
139
+ it('should return false on orientation change', () => {
140
+ resizeVisualViewport(window, { width: 320, height: 250 });
141
+ setKeyboardOpen(window);
142
+ resizeVisualViewport(window, { width: 250, height: 320 });
143
+ expect(keyboardDidClose(window)).toEqual(false);
144
+ });
145
+ });
146
+ describe('keyboardDidResize()', () => {
147
+ it('should return true when the keyboard is open but did not close', () => {
148
+ mockVisualViewport(window, { width: 250, height: 320 });
149
+ setKeyboardOpen(window);
150
+ mockVisualViewport(window, { width: 250, height: 300 });
151
+ expect(keyboardDidResize(window)).toEqual(true);
152
+ });
153
+ it('should return false when the keyboard is not open', () => {
154
+ mockVisualViewport(window);
155
+ expect(keyboardDidResize(window)).toEqual(false);
156
+ });
157
+ it('should return false when the keyboard has closed', () => {
158
+ mockVisualViewport(window, { width: 320, height: 250 });
159
+ setKeyboardOpen(window);
160
+ setKeyboardClose(window);
161
+ expect(keyboardDidResize(window)).toEqual(false);
162
+ });
163
+ });
164
+ });
165
+ describe('Keyboard Assist Integration', () => {
166
+ let mockDispatchEvent;
167
+ beforeEach(() => {
168
+ resetKeyboardAssist();
169
+ mockDispatchEvent = mockVisualViewport(window).mockDispatchEvent;
170
+ startKeyboardAssist(window);
171
+ });
172
+ afterEach(() => {
173
+ mockDispatchEvent.mockReset();
174
+ });
175
+ it('should properly set the keyboard to be open', () => {
176
+ resizeVisualViewport(window, { width: 320, height: 350 });
177
+ expect(mockDispatchEvent.mock.calls.length).toEqual(1);
178
+ expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
179
+ });
180
+ it('should properly set the keyboard to be closed', () => {
181
+ resizeVisualViewport(window, { width: 320, height: 350 });
182
+ resizeVisualViewport(window, { width: 320, height: 568 });
183
+ expect(mockDispatchEvent.mock.calls.length).toEqual(2);
184
+ expect(mockDispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_CLOSE);
185
+ });
186
+ it('should properly set the keyboard to be resized', () => {
187
+ resizeVisualViewport(window, { width: 320, height: 350 });
188
+ resizeVisualViewport(window, { width: 320, height: 360 });
189
+ expect(mockDispatchEvent.mock.calls.length).toEqual(2);
190
+ expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
191
+ expect(mockDispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_OPEN);
192
+ });
193
+ it('should not set keyboard open on orientation change', () => {
194
+ resizeVisualViewport(window, { width: 568, height: 320 });
195
+ expect(mockDispatchEvent.mock.calls.length).toEqual(0);
196
+ });
197
+ });
198
+ describe('Keyboard Assist with Capacitor', () => {
199
+ let mockDispatchEvent;
200
+ beforeEach(() => {
201
+ resetKeyboardAssist();
202
+ mockCapacitor(window);
203
+ mockDispatchEvent = mockVisualViewport(window).mockDispatchEvent;
204
+ startKeyboardAssist(window);
205
+ });
206
+ afterEach(() => {
207
+ mockDispatchEvent.mockReset();
208
+ });
209
+ it('should attach visual viewport listeners when Capacitor is available but the Keyboard plugin is not', () => {
210
+ resizeVisualViewport(window, { width: 320, height: 350 });
211
+ expect(mockDispatchEvent.mock.calls.length).toEqual(1);
212
+ expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
213
+ });
214
+ });