1
+/**
2
+ * Copyright (c) 2013-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails react-core
8
+ */
9
+
10
+'use strict';
11
+
12
+let React;
13
+let ReactDOM;
14
+
15
+describe('BeforeInputEventPlugin', () => {
16
+ let container;
17
+
18
+ function loadReactDOM(envSimulator) {
19
+ jest.resetModules();
20
+ if (envSimulator) {
21
+ envSimulator();
22
+ }
23
+ return require('react-dom');
24
+ }
25
+
26
+ function simulateIE11() {
27
+ document.documentMode = 11;
28
+ window.CompositionEvent = {};
29
+ }
30
+
31
+ function simulateWebkit() {
32
+ window.CompositionEvent = {};
33
+ window.TextEvent = {};
34
+ }
35
+
36
+ function simulateComposition() {
37
+ window.CompositionEvent = {};
38
+ }
39
+
40
+ function simulateNoComposition() {
41
+ // no composition event in Window - will use fallback
42
+ }
43
+
44
+ function simulateEvent(elem, type, data) {
45
+ const event = new Event(type, {bubbles: true});
46
+ Object.keys(data).forEach(key => {
47
+ event[key] = data[key];
48
+ });
49
+ elem.dispatchEvent(event);
50
+ }
51
+
52
+ function simulateKeyboardEvent(elem, type, data) {
53
+ const {char, value, ...rest} = data;
54
+ const event = new KeyboardEvent(type, {
55
+ bubbles: true,
56
+ ...rest,
57
+ });
58
+ if (char) {
59
+ event.char = char;
60
+ }
61
+ if (value) {
62
+ elem.value = value;
63
+ }
64
+ elem.dispatchEvent(event);
65
+ }
66
+
67
+ function simulatePaste(elem) {
68
+ const pasteEvent = new Event('paste', {
69
+ bubbles: true,
70
+ });
71
+ pasteEvent.clipboardData = {
72
+ dropEffect: null,
73
+ effectAllowed: null,
74
+ files: null,
75
+ items: null,
76
+ types: null,
77
+ };
78
+ elem.dispatchEvent(pasteEvent);
79
+ }
80
+
81
+ beforeEach(() => {
82
+ React = require('react');
83
+ container = document.createElement('div');
84
+ document.body.appendChild(container);
85
+ });
86
+
87
+ afterEach(() => {
88
+ delete document.documentMode;
89
+ delete window.CompositionEvent;
90
+ delete window.TextEvent;
91
+ delete window.opera;
92
+ document.body.removeChild(container);
93
+ container = null;
94
+ });
95
+
96
+ function keyCode(char) {
97
+ return char.charCodeAt(0);
98
+ }
99
+
100
+ const scenarios = [
101
+ {
102
+ eventSimulator: simulateEvent,
103
+ eventSimulatorArgs: [
104
+ 'compositionstart',
105
+ {detail: {data: 'test'}, data: 'test'},
106
+ ],
107
+ },
108
+ {
109
+ eventSimulator: simulateEvent,
110
+ eventSimulatorArgs: [
111
+ 'compositionupdate',
112
+ {detail: {data: 'test string'}, data: 'test string'},
113
+ ],
114
+ },
115
+ {
116
+ eventSimulator: simulateEvent,
117
+ eventSimulatorArgs: [
118
+ 'compositionend',
119
+ {detail: {data: 'test string 3'}, data: 'test string 3'},
120
+ ],
121
+ },
122
+ {
123
+ eventSimulator: simulateEvent,
124
+ eventSimulatorArgs: ['textInput', {data: 'abcß'}],
125
+ },
126
+ {
127
+ eventSimulator: simulateKeyboardEvent,
128
+ eventSimulatorArgs: ['keypress', {which: keyCode('a')}],
129
+ },
130
+ {
131
+ eventSimulator: simulateKeyboardEvent,
132
+ eventSimulatorArgs: ['keypress', {which: keyCode(' ')}, ' '],
133
+ },
134
+ {
135
+ eventSimulator: simulateEvent,
136
+ eventSimulatorArgs: ['textInput', {data: ' '}],
137
+ },
138
+ {
139
+ eventSimulator: simulateKeyboardEvent,
140
+ eventSimulatorArgs: ['keypress', {which: keyCode('a'), ctrlKey: true}],
141
+ },
142
+ {
143
+ eventSimulator: simulateKeyboardEvent,
144
+ eventSimulatorArgs: ['keypress', {which: keyCode('b'), altKey: true}],
145
+ },
146
+ {
147
+ eventSimulator: simulateKeyboardEvent,
148
+ eventSimulatorArgs: [
149
+ 'keypress',
150
+ {which: keyCode('c'), altKey: true, ctrlKey: true},
151
+ ],
152
+ },
153
+ {
154
+ eventSimulator: simulateKeyboardEvent,
155
+ eventSimulatorArgs: [
156
+ 'keypress',
157
+ {which: keyCode('X'), char: '\uD83D\uDE0A'},
158
+ ],
159
+ },
160
+ {
161
+ eventSimulator: simulateEvent,
162
+ eventSimulatorArgs: ['textInput', {data: '\uD83D\uDE0A'}],
163
+ },
164
+ {
165
+ eventSimulator: simulateKeyboardEvent,
166
+ eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foo'}],
167
+ },
168
+ {
169
+ eventSimulator: simulateKeyboardEvent,
170
+ eventSimulatorArgs: ['keydown', {keyCode: 9, value: 'foobar'}],
171
+ },
172
+ {
173
+ eventSimulator: simulateKeyboardEvent,
174
+ eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foofoo'}],
175
+ },
176
+ {
177
+ eventSimulator: simulateKeyboardEvent,
178
+ eventSimulatorArgs: ['keyup', {keyCode: 9, value: 'fooBARfoo'}],
179
+ },
180
+ {
181
+ eventSimulator: simulateKeyboardEvent,
182
+ eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foofoo'}],
183
+ },
184
+ {
185
+ eventSimulator: simulateKeyboardEvent,
186
+ eventSimulatorArgs: ['keypress', {keyCode: 60, value: 'Barfoofoo'}],
187
+ },
188
+ {
189
+ eventSimulator: simulatePaste,
190
+ eventSimulatorArgs: [],
191
+ },
192
+ ];
193
+
194
+ const environments = [
195
+ {
196
+ emulator: simulateWebkit,
197
+ assertions: [
198
+ {
199
+ run: ({
200
+ beforeInputEvent,
201
+ compositionStartEvent,
202
+ spyOnBeforeInput,
203
+ spyOnCompositionStart,
204
+ }) => {
205
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
206
+ expect(beforeInputEvent).toBeNull();
207
+ expect(spyOnCompositionStart.mock.calls.length).toBe(1);
208
+ expect(compositionStartEvent.type).toBe('compositionstart');
209
+ expect(compositionStartEvent.data).toBe('test');
210
+ },
211
+ },
212
+ {
213
+ run: ({
214
+ beforeInputEvent,
215
+ compositionUpdateEvent,
216
+ spyOnBeforeInput,
217
+ spyOnCompositionUpdate,
218
+ }) => {
219
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
220
+ expect(beforeInputEvent).toBeNull();
221
+ expect(spyOnCompositionUpdate.mock.calls.length).toBe(1);
222
+ expect(compositionUpdateEvent.type).toBe('compositionupdate');
223
+ expect(compositionUpdateEvent.data).toBe('test string');
224
+ },
225
+ },
226
+ {
227
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
228
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
229
+ expect(beforeInputEvent.type).toBe('compositionend');
230
+ expect(beforeInputEvent.data).toBe('test string 3');
231
+ },
232
+ },
233
+ {
234
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
235
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
236
+ expect(beforeInputEvent.type).toBe('textInput');
237
+ expect(beforeInputEvent.data).toBe('abcß');
238
+ },
239
+ },
240
+ {
241
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
242
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
243
+ expect(beforeInputEvent).toBeNull();
244
+ },
245
+ },
246
+ {
247
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
248
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
249
+ expect(beforeInputEvent.type).toBe('keypress');
250
+ expect(beforeInputEvent.data).toBe(' ');
251
+ },
252
+ },
253
+ {
254
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
255
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
256
+ expect(beforeInputEvent).toBeNull();
257
+ },
258
+ },
259
+ {
260
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
261
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
262
+ expect(beforeInputEvent).toBeNull();
263
+ },
264
+ },
265
+ {
266
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
267
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
268
+ expect(beforeInputEvent).toBeNull();
269
+ },
270
+ },
271
+ {
272
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
273
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
274
+ expect(beforeInputEvent).toBeNull();
275
+ },
276
+ },
277
+ {
278
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
279
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
280
+ expect(beforeInputEvent).toBeNull();
281
+ },
282
+ },
283
+ {
284
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
285
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
286
+ expect(beforeInputEvent.type).toBe('textInput');
287
+ expect(beforeInputEvent.data).toBe('\uD83D\uDE0A');
288
+ },
289
+ },
290
+ {
291
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
292
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
293
+ expect(beforeInputEvent).toBeNull();
294
+ },
295
+ },
296
+ {
297
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
298
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
299
+ expect(beforeInputEvent).toBeNull();
300
+ },
301
+ },
302
+ {
303
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
304
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
305
+ expect(beforeInputEvent).toBeNull();
306
+ },
307
+ },
308
+ {
309
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
310
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
311
+ expect(beforeInputEvent).toBeNull();
312
+ },
313
+ },
314
+ {
315
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
316
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
317
+ expect(beforeInputEvent).toBeNull();
318
+ },
319
+ },
320
+ {
321
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
322
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
323
+ expect(beforeInputEvent).toBeNull();
324
+ },
325
+ },
326
+ {
327
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
328
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
329
+ expect(beforeInputEvent).toBeNull();
330
+ },
331
+ },
332
+ ],
333
+ },
334
+ {
335
+ emulator: simulateIE11,
336
+ assertions: [
337
+ {
338
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
339
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
340
+ expect(beforeInputEvent).toBeNull();
341
+ },
342
+ },
343
+ {
344
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
345
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
346
+ expect(beforeInputEvent).toBeNull();
347
+ },
348
+ },
349
+ {
350
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
351
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
352
+ expect(beforeInputEvent).toBeNull();
353
+ },
354
+ },
355
+ {
356
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
357
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
358
+ expect(beforeInputEvent).toBeNull();
359
+ },
360
+ },
361
+ {
362
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
363
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
364
+ expect(beforeInputEvent.type).toBe('keypress');
365
+ expect(beforeInputEvent.data).toBe('a');
366
+ },
367
+ },
368
+ {
369
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
370
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
371
+ expect(beforeInputEvent.type).toBe('keypress');
372
+ expect(beforeInputEvent.data).toBe(' ');
373
+ },
374
+ },
375
+ {
376
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
377
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
378
+ expect(beforeInputEvent).toBeNull();
379
+ },
380
+ },
381
+ {
382
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
383
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
384
+ expect(beforeInputEvent).toBeNull();
385
+ },
386
+ },
387
+ {
388
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
389
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
390
+ expect(beforeInputEvent).toBeNull();
391
+ },
392
+ },
393
+ {
394
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
395
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
396
+ expect(beforeInputEvent.type).toBe('keypress');
397
+ expect(beforeInputEvent.data).toBe('c');
398
+ },
399
+ },
400
+ {
401
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
402
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
403
+ expect(beforeInputEvent.type).toBe('keypress');
404
+ expect(beforeInputEvent.data).toBe('\uD83D\uDE0A');
405
+ },
406
+ },
407
+ {
408
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
409
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
410
+ expect(beforeInputEvent).toBeNull();
411
+ },
412
+ },
413
+ {
414
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
415
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
416
+ expect(beforeInputEvent).toBeNull();
417
+ },
418
+ },
419
+ {
420
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
421
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
422
+ expect(beforeInputEvent).toBeNull();
423
+ },
424
+ },
425
+ {
426
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
427
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
428
+ expect(beforeInputEvent).toBeNull();
429
+ },
430
+ },
431
+ {
432
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
433
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
434
+ expect(beforeInputEvent).toBeNull();
435
+ },
436
+ },
437
+ {
438
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
439
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
440
+ expect(beforeInputEvent).toBeNull();
441
+ },
442
+ },
443
+ {
444
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
445
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
446
+ expect(beforeInputEvent).toBeNull();
447
+ },
448
+ },
449
+ {
450
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
451
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
452
+ expect(beforeInputEvent).toBeNull();
453
+ },
454
+ },
455
+ ],
456
+ },
457
+ {
458
+ emulator: simulateNoComposition,
459
+ assertions: [
460
+ {
461
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
462
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
463
+ expect(beforeInputEvent).toBeNull();
464
+ },
465
+ },
466
+ {
467
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
468
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
469
+ expect(beforeInputEvent).toBeNull();
470
+ },
471
+ },
472
+ {
473
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
474
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
475
+ expect(beforeInputEvent).toBeNull();
476
+ },
477
+ },
478
+ {
479
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
480
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
481
+ expect(beforeInputEvent).toBeNull();
482
+ },
483
+ },
484
+ {
485
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
486
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
487
+ expect(beforeInputEvent.type).toBe('keypress');
488
+ expect(beforeInputEvent.data).toBe('a');
489
+ },
490
+ },
491
+ {
492
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
493
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
494
+ expect(beforeInputEvent.type).toBe('keypress');
495
+ expect(beforeInputEvent.data).toBe(' ');
496
+ },
497
+ },
498
+ {
499
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
500
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
501
+ expect(beforeInputEvent).toBeNull();
502
+ },
503
+ },
504
+ {
505
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
506
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
507
+ expect(beforeInputEvent).toBeNull();
508
+ },
509
+ },
510
+ {
511
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
512
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
513
+ expect(beforeInputEvent).toBeNull();
514
+ },
515
+ },
516
+ {
517
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
518
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
519
+ expect(beforeInputEvent.type).toBe('keypress');
520
+ expect(beforeInputEvent.data).toBe('c');
521
+ },
522
+ },
523
+ {
524
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
525
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
526
+ expect(beforeInputEvent.type).toBe('keypress');
527
+ expect(beforeInputEvent.data).toBe('\uD83D\uDE0A');
528
+ },
529
+ },
530
+ {
531
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
532
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
533
+ expect(beforeInputEvent).toBeNull();
534
+ },
535
+ },
536
+ {
537
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
538
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
539
+ expect(beforeInputEvent).toBeNull();
540
+ },
541
+ },
542
+ {
543
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
544
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
545
+ expect(beforeInputEvent.type).toBe('keydown');
546
+ expect(beforeInputEvent.data).toBe('bar');
547
+ },
548
+ },
549
+ {
550
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
551
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
552
+ expect(beforeInputEvent).toBeNull();
553
+ },
554
+ },
555
+ {
556
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
557
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
558
+ expect(beforeInputEvent.type).toBe('keyup');
559
+ expect(beforeInputEvent.data).toBe('BAR');
560
+ },
561
+ },
562
+ {
563
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
564
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
565
+ expect(beforeInputEvent).toBeNull();
566
+ },
567
+ },
568
+ {
569
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
570
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
571
+ expect(beforeInputEvent.type).toBe('keypress');
572
+ expect(beforeInputEvent.data).toBe('Bar');
573
+ },
574
+ },
575
+ {
576
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
577
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
578
+ expect(beforeInputEvent).toBeNull();
579
+ },
580
+ },
581
+ ],
582
+ },
583
+ {
584
+ emulator: simulateComposition,
585
+ assertions: [
586
+ {
587
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
588
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
589
+ expect(beforeInputEvent).toBeNull();
590
+ },
591
+ },
592
+ {
593
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
594
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
595
+ expect(beforeInputEvent).toBeNull();
596
+ },
597
+ },
598
+ {
599
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
600
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
601
+ expect(beforeInputEvent.type).toBe('compositionend');
602
+ expect(beforeInputEvent.data).toBe('test string 3');
603
+ },
604
+ },
605
+ {
606
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
607
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
608
+ expect(beforeInputEvent).toBeNull();
609
+ },
610
+ },
611
+ {
612
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
613
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
614
+ expect(beforeInputEvent.type).toBe('keypress');
615
+ expect(beforeInputEvent.data).toBe('a');
616
+ },
617
+ },
618
+ {
619
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
620
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
621
+ expect(beforeInputEvent.type).toBe('keypress');
622
+ expect(beforeInputEvent.data).toBe(' ');
623
+ },
624
+ },
625
+ {
626
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
627
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
628
+ expect(beforeInputEvent).toBeNull();
629
+ },
630
+ },
631
+ {
632
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
633
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
634
+ expect(beforeInputEvent).toBeNull();
635
+ },
636
+ },
637
+ {
638
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
639
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
640
+ expect(beforeInputEvent).toBeNull();
641
+ },
642
+ },
643
+ {
644
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
645
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
646
+ expect(beforeInputEvent.type).toBe('keypress');
647
+ expect(beforeInputEvent.data).toBe('c');
648
+ },
649
+ },
650
+ {
651
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
652
+ expect(spyOnBeforeInput.mock.calls.length).toBe(1);
653
+ expect(beforeInputEvent.type).toBe('keypress');
654
+ expect(beforeInputEvent.data).toBe('\uD83D\uDE0A');
655
+ },
656
+ },
657
+ {
658
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
659
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
660
+ expect(beforeInputEvent).toBeNull();
661
+ },
662
+ },
663
+ {
664
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
665
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
666
+ expect(beforeInputEvent).toBeNull();
667
+ },
668
+ },
669
+ {
670
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
671
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
672
+ expect(beforeInputEvent).toBeNull();
673
+ },
674
+ },
675
+ {
676
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
677
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
678
+ expect(beforeInputEvent).toBeNull();
679
+ },
680
+ },
681
+ {
682
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
683
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
684
+ expect(beforeInputEvent).toBeNull();
685
+ },
686
+ },
687
+ {
688
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
689
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
690
+ expect(beforeInputEvent).toBeNull();
691
+ },
692
+ },
693
+ {
694
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
695
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
696
+ expect(beforeInputEvent).toBeNull();
697
+ },
698
+ },
699
+ {
700
+ run: ({beforeInputEvent, spyOnBeforeInput}) => {
701
+ expect(spyOnBeforeInput.mock.calls.length).toBe(0);
702
+ expect(beforeInputEvent).toBeNull();
703
+ },
704
+ },
705
+ ],
706
+ },
707
+ ];
708
+
709
+ const testInputComponent = (env, scenes) => {
710
+ let beforeInputEvent;
711
+ let compositionStartEvent;
712
+ let compositionUpdateEvent;
713
+ let spyOnBeforeInput;
714
+ let spyOnCompositionStart;
715
+ let spyOnCompositionUpdate;
716
+ ReactDOM = loadReactDOM(env.emulator);
717
+ const node = ReactDOM.render(
718
+ <input
719
+ type="text"
720
+ onBeforeInput={({type, data}) => {
721
+ spyOnBeforeInput();
722
+ beforeInputEvent = {type, data};
723
+ }}
724
+ onCompositionStart={({type, data}) => {
725
+ spyOnCompositionStart();
726
+ compositionStartEvent = {type, data};
727
+ }}
728
+ onCompositionUpdate={({type, data}) => {
729
+ spyOnCompositionUpdate();
730
+ compositionUpdateEvent = {type, data};
731
+ }}
732
+ />,
733
+ container,
734
+ );
735
+
736
+ scenes.forEach((s, id) => {
737
+ beforeInputEvent = null;
738
+ compositionStartEvent = null;
739
+ compositionUpdateEvent = null;
740
+ spyOnBeforeInput = jest.fn();
741
+ spyOnCompositionStart = jest.fn();
742
+ spyOnCompositionUpdate = jest.fn();
743
+ s.eventSimulator.apply(null, [node, ...s.eventSimulatorArgs]);
744
+ env.assertions[id].run({
745
+ beforeInputEvent,
746
+ compositionStartEvent,
747
+ compositionUpdateEvent,
748
+ spyOnBeforeInput,
749
+ spyOnCompositionStart,
750
+ spyOnCompositionUpdate,
751
+ });
752
+ });
753
+ };
754
+
755
+ const testContentEditableComponent = (env, scenes) => {
756
+ let beforeInputEvent;
757
+ let compositionStartEvent;
758
+ let compositionUpdateEvent;
759
+ let spyOnBeforeInput;
760
+ let spyOnCompositionStart;
761
+ let spyOnCompositionUpdate;
762
+ ReactDOM = loadReactDOM(env.emulator);
763
+ const node = ReactDOM.render(
764
+ <div
765
+ contentEditable={true}
766
+ onBeforeInput={({type, data}) => {
767
+ spyOnBeforeInput();
768
+ beforeInputEvent = {type, data};
769
+ }}
770
+ onCompositionStart={({type, data}) => {
771
+ spyOnCompositionStart();
772
+ compositionStartEvent = {type, data};
773
+ }}
774
+ onCompositionUpdate={({type, data}) => {
775
+ spyOnCompositionUpdate();
776
+ compositionUpdateEvent = {type, data};
777
+ }}
778
+ />,
779
+ container,
780
+ );
781
+
782
+ scenes.forEach((s, id) => {
783
+ beforeInputEvent = null;
784
+ compositionStartEvent = null;
785
+ compositionUpdateEvent = null;
786
+ spyOnBeforeInput = jest.fn();
787
+ spyOnCompositionStart = jest.fn();
788
+ spyOnCompositionUpdate = jest.fn();
789
+ s.eventSimulator.apply(null, [node, ...s.eventSimulatorArgs]);
790
+ env.assertions[id].run({
791
+ beforeInputEvent,
792
+ compositionStartEvent,
793
+ compositionUpdateEvent,
794
+ spyOnBeforeInput,
795
+ spyOnCompositionStart,
796
+ spyOnCompositionUpdate,
797
+ });
798
+ });
799
+ };
800
+
801
+ it('should extract onBeforeInput when simulating in Webkit on input[type=text]', () => {
802
+ testInputComponent(environments[0], scenarios);
803
+ });
804
+ it('should extract onBeforeInput when simulating in Webkit on contenteditable', () => {
805
+ testContentEditableComponent(environments[0], scenarios);
806
+ });
807
+
808
+ it('should extract onBeforeInput when simulating in IE11 on input[type=text]', () => {
809
+ testInputComponent(environments[1], scenarios);
810
+ });
811
+ it('should extract onBeforeInput when simulating in IE11 on contenteditable', () => {
812
+ testContentEditableComponent(environments[1], scenarios);
813
+ });
814
+
815
+ it('should extract onBeforeInput when simulating in env with no CompositionEvent on input[type=text]', () => {
816
+ testInputComponent(environments[2], scenarios);
817
+ });
818
+
819
+ // in an environment using composition fallback onBeforeInput will not work
820
+ // as expected on a contenteditable as keydown and keyup events are translated
821
+ // to keypress events
822
+
823
+ it('should extract onBeforeInput when simulating in env with only CompositionEvent on input[type=text]', () => {
824
+ testInputComponent(environments[3], scenarios);
825
+ });
826
+
827
+ it('should extract onBeforeInput when simulating in env with only CompositionEvent on contenteditable', () => {
828
+ testContentEditableComponent(environments[3], scenarios);
829
+ });
830
+});