@samitouri / QOS-React / commits / d1cb28c86b

Refactor SyntheticKeyboardEvent tests to only use the public API (#11631)

* KeyboardEvent interface-keypress * Pass first 6 tests * Roll getEventCharCode-test into SyntheticKeyboardEvent-test * Run SyntheticKeyboardEvent-test on bundles * Remove unused code

Anton Arboleda committed Nov 25, 2017 at 07:47 UTC d1cb28c86b966cb33c373b532abe62dfe563d00e
3 files changed +577 -211
packages/react-dom/src/events/__tests__/SyntheticKeyboardEvent-test.internal.js deleted
-122
@@ -1,122 +0,0 @@
1 -/**
2 - * Copyright (c) 2016-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 -var SyntheticKeyboardEvent;
13 -var getEventCharCode;
14 -
15 -describe('SyntheticKeyboardEvent', () => {
16 - var createEvent;
17 -
18 - beforeEach(() => {
19 - // Mock getEventCharCode for proper unit testing
20 - jest.mock('../getEventCharCode');
21 - getEventCharCode = require('../getEventCharCode').default;
22 -
23 - // TODO: can we express this test with only public API?
24 - SyntheticKeyboardEvent = require('../SyntheticKeyboardEvent').default;
25 - createEvent = function(nativeEvent) {
26 - var target = require('../getEventTarget').default(nativeEvent);
27 - return SyntheticKeyboardEvent.getPooled({}, '', nativeEvent, target);
28 - };
29 - });
30 -
31 - describe('KeyboardEvent interface', () => {
32 - describe('charCode', () => {
33 - describe('when event is `keypress`', () => {
34 - it('returns whatever getEventCharCode returns', () => {
35 - getEventCharCode.mockReturnValue(100500);
36 - var keyboardEvent = createEvent({type: 'keypress', charCode: 50});
37 -
38 - expect(keyboardEvent.charCode).toBe(100500);
39 - });
40 - });
41 -
42 - describe('when event is not `keypress`', () => {
43 - it('returns 0', () => {
44 - var keyboardEvent = createEvent({type: 'keyup', charCode: 50});
45 - expect(keyboardEvent.charCode).toBe(0);
46 - });
47 - });
48 - });
49 -
50 - describe('keyCode', () => {
51 - describe('when event is `keydown` or `keyup`', () => {
52 - it('returns a passed keyCode', () => {
53 - var keyboardEvent = createEvent({type: 'keyup', keyCode: 40});
54 - expect(keyboardEvent.keyCode).toBe(40);
55 - });
56 - });
57 -
58 - describe('when event is `keypress`', () => {
59 - it('returns 0', () => {
60 - var keyboardEvent = createEvent({type: 'keypress', charCode: 40});
61 - expect(keyboardEvent.keyCode).toBe(0);
62 - });
63 - });
64 - });
65 -
66 - describe('which', () => {
67 - describe('when event is `keypress`', () => {
68 - it('returns whatever getEventCharCode returns', () => {
69 - getEventCharCode.mockReturnValue(9001);
70 - var keyboardEvent = createEvent({type: 'keypress', charCode: 50});
71 -
72 - expect(keyboardEvent.which).toBe(9001);
73 - });
74 - });
75 -
76 - describe('when event is `keydown` or `keyup`', () => {
77 - it('returns a passed keyCode', () => {
78 - var keyboardEvent = createEvent({type: 'keyup', keyCode: 40});
79 - expect(keyboardEvent.which).toBe(40);
80 - });
81 - });
82 -
83 - describe('when event type is unknown', () => {
84 - it('returns 0', () => {
85 - var keyboardEvent = createEvent({type: 'keysmack', keyCode: 40});
86 - expect(keyboardEvent.which).toBe(0);
87 - });
88 - });
89 - });
90 - });
91 -
92 - describe('EventInterface', () => {
93 - it('normalizes properties from the Event interface', () => {
94 - var target = document.createElement('div');
95 - var syntheticEvent = createEvent({srcElement: target});
96 -
97 - expect(syntheticEvent.target).toBe(target);
98 - expect(syntheticEvent.type).toBe(undefined);
99 - });
100 -
101 - it('is able to `preventDefault` and `stopPropagation`', () => {
102 - var nativeEvent = {};
103 - var syntheticEvent = createEvent(nativeEvent);
104 -
105 - expect(syntheticEvent.isDefaultPrevented()).toBe(false);
106 - syntheticEvent.preventDefault();
107 - expect(syntheticEvent.isDefaultPrevented()).toBe(true);
108 -
109 - expect(syntheticEvent.isPropagationStopped()).toBe(false);
110 - syntheticEvent.stopPropagation();
111 - expect(syntheticEvent.isPropagationStopped()).toBe(true);
112 - });
113 -
114 - it('is able to `persist`', () => {
115 - var syntheticEvent = createEvent({});
116 -
117 - expect(syntheticEvent.isPersistent()).toBe(false);
118 - syntheticEvent.persist();
119 - expect(syntheticEvent.isPersistent()).toBe(true);
120 - });
121 - });
122 -});
packages/react-dom/src/events/__tests__/SyntheticKeyboardEvent-test.js new
+577
@@ -0,0 +1,577 @@
1 +/**
2 + * Copyright (c) 2016-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('SyntheticKeyboardEvent', () => {
16 + let container;
17 +
18 + beforeEach(() => {
19 + React = require('react');
20 + ReactDOM = require('react-dom');
21 + // The container has to be attached for events to fire.
22 + container = document.createElement('div');
23 + document.body.appendChild(container);
24 + });
25 +
26 + afterEach(() => {
27 + document.body.removeChild(container);
28 + container = null;
29 + });
30 +
31 + describe('KeyboardEvent interface', () => {
32 + describe('charCode', () => {
33 + describe('when event is `keypress`', () => {
34 + describe('when charCode is present in nativeEvent', () => {
35 + it('when charCode is 0 and keyCode is 13, returns 13', () => {
36 + let charCode = null;
37 + const node = ReactDOM.render(
38 + <input
39 + onKeyPress={e => {
40 + charCode = e.charCode;
41 + }}
42 + />,
43 + container,
44 + );
45 + node.dispatchEvent(
46 + new KeyboardEvent('keypress', {
47 + charCode: 0,
48 + keyCode: 13,
49 + bubbles: true,
50 + cancelable: true,
51 + }),
52 + );
53 + expect(charCode).toBe(13);
54 + });
55 +
56 + it('when charCode is 32 or bigger and keyCode is missing, returns charCode', () => {
57 + let charCode = null;
58 + const node = ReactDOM.render(
59 + <input
60 + onKeyPress={e => {
61 + charCode = e.charCode;
62 + }}
63 + />,
64 + container,
65 + );
66 + node.dispatchEvent(
67 + new KeyboardEvent('keypress', {
68 + charCode: 32,
69 + bubbles: true,
70 + cancelable: true,
71 + }),
72 + );
73 + expect(charCode).toBe(32);
74 + });
75 +
76 + it('when charCode is 13 and keyCode is missing, returns charCode', () => {
77 + let charCode = null;
78 + const node = ReactDOM.render(
79 + <input
80 + onKeyPress={e => {
81 + charCode = e.charCode;
82 + }}
83 + />,
84 + container,
85 + );
86 + node.dispatchEvent(
87 + new KeyboardEvent('keypress', {
88 + charCode: 13,
89 + bubbles: true,
90 + cancelable: true,
91 + }),
92 + );
93 + expect(charCode).toBe(13);
94 + });
95 +
96 + // Firefox creates a keypress event for function keys too. This removes
97 + // the unwanted keypress events. Enter is however both printable and
98 + // non-printable. One would expect Tab to be as well (but it isn't).
99 + it('when charCode is smaller than 32 but is not 13, and keyCode is missing, ignores keypress', () => {
100 + let called = false;
101 + const node = ReactDOM.render(
102 + <input
103 + onKeyPress={() => {
104 + called = true;
105 + }}
106 + />,
107 + container,
108 + );
109 + node.dispatchEvent(
110 + new KeyboardEvent('keypress', {
111 + charCode: 31,
112 + bubbles: true,
113 + cancelable: true,
114 + }),
115 + );
116 + expect(called).toBe(false);
117 + });
118 + });
119 +
120 + // TODO: this seems IE8 specific.
121 + // We can probably remove this normalization.
122 + describe('when charCode is not present in nativeEvent', () => {
123 + let charCodeDescriptor;
124 +
125 + beforeEach(() => {
126 + charCodeDescriptor = Object.getOwnPropertyDescriptor(
127 + KeyboardEvent.prototype,
128 + 'charCode',
129 + );
130 + delete KeyboardEvent.prototype.charCode;
131 + });
132 +
133 + afterEach(() => {
134 + // Don't forget to restore for other tests.
135 + Object.defineProperty(
136 + KeyboardEvent.prototype,
137 + 'charCode',
138 + charCodeDescriptor,
139 + );
140 + charCodeDescriptor = null;
141 + });
142 +
143 + it('when keyCode is 32 or bigger, returns keyCode', () => {
144 + let charCode = null;
145 + const node = ReactDOM.render(
146 + <input
147 + onKeyPress={e => {
148 + charCode = e.charCode;
149 + }}
150 + />,
151 + container,
152 + );
153 + node.dispatchEvent(
154 + new KeyboardEvent('keypress', {
155 + keyCode: 32,
156 + bubbles: true,
157 + cancelable: true,
158 + }),
159 + );
160 + expect(charCode).toBe(32);
161 + });
162 +
163 + it('when keyCode is 13, returns 13', () => {
164 + let charCode = null;
165 + const node = ReactDOM.render(
166 + <input
167 + onKeyPress={e => {
168 + charCode = e.charCode;
169 + }}
170 + />,
171 + container,
172 + );
173 + node.dispatchEvent(
174 + new KeyboardEvent('keypress', {
175 + keyCode: 13,
176 + bubbles: true,
177 + cancelable: true,
178 + }),
179 + );
180 + expect(charCode).toBe(13);
181 + });
182 +
183 + it('when keyCode is smaller than 32 and is not 13, ignores keypress', () => {
184 + let called = false;
185 + const node = ReactDOM.render(
186 + <input
187 + onKeyPress={e => {
188 + called = true;
189 + }}
190 + />,
191 + container,
192 + );
193 + node.dispatchEvent(
194 + new KeyboardEvent('keypress', {
195 + keyCode: 31,
196 + bubbles: true,
197 + cancelable: true,
198 + }),
199 + );
200 + expect(called).toBe(false);
201 + });
202 + });
203 + });
204 +
205 + describe('when event is not `keypress`', () => {
206 + it('returns 0', () => {
207 + let charCodeDown = null;
208 + let charCodeUp = null;
209 + const node = ReactDOM.render(
210 + <input
211 + onKeyDown={e => {
212 + charCodeDown = e.charCode;
213 + }}
214 + onKeyUp={e => {
215 + charCodeUp = e.charCode;
216 + }}
217 + />,
218 + container,
219 + );
220 + node.dispatchEvent(
221 + new KeyboardEvent('keydown', {
222 + key: 'Del',
223 + bubbles: true,
224 + cancelable: true,
225 + }),
226 + );
227 + node.dispatchEvent(
228 + new KeyboardEvent('keyup', {
229 + key: 'Del',
230 + bubbles: true,
231 + cancelable: true,
232 + }),
233 + );
234 + expect(charCodeDown).toBe(0);
235 + expect(charCodeUp).toBe(0);
236 + });
237 + });
238 +
239 + it('when charCode is smaller than 32 but is not 13, and keyCode is missing, charCode is 0', () => {
240 + let charCode = null;
241 + const node = ReactDOM.render(
242 + <input
243 + onKeyDown={e => {
244 + charCode = e.charCode;
245 + }}
246 + />,
247 + container,
248 + );
249 + node.dispatchEvent(
250 + new KeyboardEvent('keydown', {
251 + charCode: 31,
252 + bubbles: true,
253 + cancelable: true,
254 + }),
255 + );
256 + expect(charCode).toBe(0);
257 + });
258 + });
259 +
260 + describe('keyCode', () => {
261 + describe('when event is `keydown` or `keyup`', () => {
262 + it('returns a passed keyCode', () => {
263 + let keyCodeDown = null;
264 + let keyCodeUp = null;
265 + const node = ReactDOM.render(
266 + <input
267 + onKeyDown={e => {
268 + keyCodeDown = e.keyCode;
269 + }}
270 + onKeyUp={e => {
271 + keyCodeUp = e.keyCode;
272 + }}
273 + />,
274 + container,
275 + );
276 + node.dispatchEvent(
277 + new KeyboardEvent('keydown', {
278 + keyCode: 40,
279 + bubbles: true,
280 + cancelable: true,
281 + }),
282 + );
283 + node.dispatchEvent(
284 + new KeyboardEvent('keyup', {
285 + keyCode: 40,
286 + bubbles: true,
287 + cancelable: true,
288 + }),
289 + );
290 + expect(keyCodeDown).toBe(40);
291 + expect(keyCodeUp).toBe(40);
292 + });
293 + });
294 +
295 + describe('when event is `keypress`', () => {
296 + it('returns 0', () => {
297 + let keyCode = null;
298 + const node = ReactDOM.render(
299 + <input
300 + onKeyPress={e => {
301 + keyCode = e.keyCode;
302 + }}
303 + />,
304 + container,
305 + );
306 + node.dispatchEvent(
307 + new KeyboardEvent('keypress', {
308 + charCode: 65,
309 + bubbles: true,
310 + cancelable: true,
311 + }),
312 + );
313 + expect(keyCode).toBe(0);
314 + });
315 + });
316 + });
317 +
318 + describe('which', () => {
319 + describe('when event is `keypress`', () => {
320 + it('is consistent with `charCode`', () => {
321 + let calls = 0;
322 + const node = ReactDOM.render(
323 + <input
324 + onKeyPress={e => {
325 + expect(e.which).toBe(e.charCode);
326 + calls++;
327 + }}
328 + />,
329 + container,
330 + );
331 + // Try different combinations from other tests.
332 + node.dispatchEvent(
333 + new KeyboardEvent('keypress', {
334 + charCode: 0,
335 + keyCode: 13,
336 + bubbles: true,
337 + cancelable: true,
338 + }),
339 + );
340 + node.dispatchEvent(
341 + new KeyboardEvent('keypress', {
342 + charCode: 32,
343 + bubbles: true,
344 + cancelable: true,
345 + }),
346 + );
347 + node.dispatchEvent(
348 + new KeyboardEvent('keypress', {
349 + charCode: 13,
350 + bubbles: true,
351 + cancelable: true,
352 + }),
353 + );
354 + expect(calls).toBe(3);
355 + });
356 + });
357 +
358 + describe('when event is `keydown` or `keyup`', () => {
359 + it('is consistent with `keyCode`', () => {
360 + let calls = 0;
361 + const node = ReactDOM.render(
362 + <input
363 + onKeyDown={e => {
364 + expect(e.which).toBe(e.keyCode);
365 + calls++;
366 + }}
367 + onKeyUp={e => {
368 + expect(e.which).toBe(e.keyCode);
369 + calls++;
370 + }}
371 + />,
372 + container,
373 + );
374 + node.dispatchEvent(
375 + new KeyboardEvent('keydown', {
376 + key: 'Del',
377 + bubbles: true,
378 + cancelable: true,
379 + }),
380 + );
381 + node.dispatchEvent(
382 + new KeyboardEvent('keydown', {
383 + charCode: 31,
384 + bubbles: true,
385 + cancelable: true,
386 + }),
387 + );
388 + node.dispatchEvent(
389 + new KeyboardEvent('keydown', {
390 + keyCode: 40,
391 + bubbles: true,
392 + cancelable: true,
393 + }),
394 + );
395 + node.dispatchEvent(
396 + new KeyboardEvent('keyup', {
397 + key: 'Del',
398 + bubbles: true,
399 + cancelable: true,
400 + }),
401 + );
402 + node.dispatchEvent(
403 + new KeyboardEvent('keyup', {
404 + keyCode: 40,
405 + bubbles: true,
406 + cancelable: true,
407 + }),
408 + );
409 + expect(calls).toBe(5);
410 + });
411 + });
412 + });
413 + });
414 +
415 + describe('EventInterface', () => {
416 + it('normalizes properties from the Event interface', () => {
417 + let expectedCount = 0;
418 + let div;
419 + const eventHandler = type => event => {
420 + expect(event.target).toBe(div);
421 + expect(event.type).toBe(type);
422 + expectedCount++;
423 + };
424 + div = ReactDOM.render(
425 + <div
426 + onKeyDown={eventHandler('keydown')}
427 + onKeyPress={eventHandler('keypress')}
428 + onKeyUp={eventHandler('keyup')}
429 + />,
430 + container,
431 + );
432 +
433 + let event;
434 + event = new KeyboardEvent('keydown', {
435 + keyCode: 40,
436 + bubbles: true,
437 + cancelable: true,
438 + });
439 + // Emulate IE8
440 + Object.defineProperty(event, 'target', {
441 + get() {},
442 + });
443 + Object.defineProperty(event, 'srcElement', {
444 + get() {
445 + return div;
446 + },
447 + });
448 + div.dispatchEvent(event);
449 +
450 + event = new KeyboardEvent('keyup', {
451 + keyCode: 40,
452 + bubbles: true,
453 + cancelable: true,
454 + });
455 + // Emulate IE8
456 + Object.defineProperty(event, 'target', {
457 + get() {},
458 + });
459 + Object.defineProperty(event, 'srcElement', {
460 + get() {
461 + return div;
462 + },
463 + });
464 + div.dispatchEvent(event);
465 +
466 + event = new KeyboardEvent('keypress', {
467 + charCode: 40,
468 + keyCode: 40,
469 + bubbles: true,
470 + cancelable: true,
471 + });
472 + // Emulate IE8
473 + Object.defineProperty(event, 'target', {
474 + get() {},
475 + });
476 + Object.defineProperty(event, 'srcElement', {
477 + get() {
478 + return div;
479 + },
480 + });
481 + div.dispatchEvent(event);
482 +
483 + expect(expectedCount).toBe(3);
484 + });
485 +
486 + it('is able to `preventDefault` and `stopPropagation`', () => {
487 + let expectedCount = 0;
488 + const eventHandler = event => {
489 + expect(event.isDefaultPrevented()).toBe(false);
490 + event.preventDefault();
491 + expect(event.isDefaultPrevented()).toBe(true);
492 +
493 + expect(event.isPropagationStopped()).toBe(false);
494 + event.stopPropagation();
495 + expect(event.isPropagationStopped()).toBe(true);
496 + expectedCount++;
497 + };
498 + let div = ReactDOM.render(
499 + <div
500 + onKeyDown={eventHandler}
501 + onKeyUp={eventHandler}
502 + onKeyPress={eventHandler}
503 + />,
504 + container,
505 + );
506 +
507 + div.dispatchEvent(
508 + new KeyboardEvent('keydown', {
509 + keyCode: 40,
510 + bubbles: true,
511 + cancelable: true,
512 + }),
513 + );
514 + div.dispatchEvent(
515 + new KeyboardEvent('keyup', {
516 + keyCode: 40,
517 + bubbles: true,
518 + cancelable: true,
519 + }),
520 + );
521 + div.dispatchEvent(
522 + new KeyboardEvent('keypress', {
523 + charCode: 40,
524 + keyCode: 40,
525 + bubbles: true,
526 + cancelable: true,
527 + }),
528 + );
529 + expect(expectedCount).toBe(3);
530 + });
531 +
532 + it('is able to `persist`', () => {
533 + const persistentEvents = [];
534 + const eventHandler = event => {
535 + expect(event.isPersistent()).toBe(false);
536 + event.persist();
537 + expect(event.isPersistent()).toBe(true);
538 + persistentEvents.push(event);
539 + };
540 + let div = ReactDOM.render(
541 + <div
542 + onKeyDown={eventHandler}
543 + onKeyUp={eventHandler}
544 + onKeyPress={eventHandler}
545 + />,
546 + container,
547 + );
548 +
549 + div.dispatchEvent(
550 + new KeyboardEvent('keydown', {
551 + keyCode: 40,
552 + bubbles: true,
553 + cancelable: true,
554 + }),
555 + );
556 + div.dispatchEvent(
557 + new KeyboardEvent('keyup', {
558 + keyCode: 40,
559 + bubbles: true,
560 + cancelable: true,
561 + }),
562 + );
563 + div.dispatchEvent(
564 + new KeyboardEvent('keypress', {
565 + charCode: 40,
566 + keyCode: 40,
567 + bubbles: true,
568 + cancelable: true,
569 + }),
570 + );
571 + expect(persistentEvents.length).toBe(3);
572 + expect(persistentEvents[0].type).toBe('keydown');
573 + expect(persistentEvents[1].type).toBe('keyup');
574 + expect(persistentEvents[2].type).toBe('keypress');
575 + });
576 + });
577 +});
packages/react-dom/src/events/__tests__/getEventCharCode-test.js deleted
-89
@@ -1,89 +0,0 @@
1 -/**
2 - * Copyright (c) 2016-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 -// TODO: can we express this test with only public API?
13 -var getEventCharCode = require('../getEventCharCode').default;
14 -
15 -describe('getEventCharCode', () => {
16 - describe('when charCode is present in nativeEvent', () => {
17 - describe('when charCode is 0 and keyCode is 13', () => {
18 - it('returns 13', () => {
19 - var nativeEvent = new KeyboardEvent('keypress', {
20 - charCode: 0,
21 - keyCode: 13,
22 - });
23 -
24 - expect(getEventCharCode(nativeEvent)).toBe(13);
25 - });
26 - });
27 -
28 - describe('when charCode is not 0 and/or keyCode is not 13', () => {
29 - describe('when charCode is 32 or bigger', () => {
30 - it('returns charCode', () => {
31 - var nativeEvent = new KeyboardEvent('keypress', {charCode: 32});
32 -
33 - expect(getEventCharCode(nativeEvent)).toBe(32);
34 - });
35 - });
36 -
37 - describe('when charCode is smaller than 32', () => {
38 - describe('when charCode is 13', () => {
39 - it('returns 13', () => {
40 - var nativeEvent = new KeyboardEvent('keypress', {charCode: 13});
41 -
42 - expect(getEventCharCode(nativeEvent)).toBe(13);
43 - });
44 - });
45 -
46 - describe('when charCode is not 13', () => {
47 - it('returns 0', () => {
48 - var nativeEvent = new KeyboardEvent('keypress', {charCode: 31});
49 -
50 - expect(getEventCharCode(nativeEvent)).toBe(0);
51 - });
52 - });
53 - });
54 - });
55 - });
56 -
57 - /**
58 - nativeEvent is represented as a plain object here to ease testing, because
59 - KeyboardEvent's 'charCode' event key cannot be deleted to simulate a missing
60 - charCode key.
61 - */
62 - describe('when charCode is not present in nativeEvent', () => {
63 - describe('when keyCode is 32 or bigger', () => {
64 - it('returns keyCode', () => {
65 - var nativeEvent = {keyCode: 32};
66 -
67 - expect(getEventCharCode(nativeEvent)).toBe(32);
68 - });
69 - });
70 -
71 - describe('when keyCode is smaller than 32', () => {
72 - describe('when keyCode is 13', () => {
73 - it('returns 13', () => {
74 - var nativeEvent = {keyCode: 13};
75 -
76 - expect(getEventCharCode(nativeEvent)).toBe(13);
77 - });
78 - });
79 -
80 - describe('when keyCode is not 13', () => {
81 - it('returns 0', () => {
82 - var nativeEvent = {keyCode: 31};
83 -
84 - expect(getEventCharCode(nativeEvent)).toBe(0);
85 - });
86 - });
87 - });
88 - });
89 -});