From 05cf902f031c979aadbe297063b29c0371ecd960 Mon Sep 17 00:00:00 2001 From: Bernardo Smaniotto Date: Wed, 25 Oct 2017 20:08:11 -0200 Subject: [PATCH 1/7] Refactor SyntheticClipboardEvent tests to only use the public API --- .../__tests__/SyntheticClipboardEvent-test.js | 140 ++++++++++++++---- 1 file changed, 115 insertions(+), 25 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index f671f39a5ac98..88af1c73675ba 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -9,17 +9,30 @@ 'use strict'; -var SyntheticClipboardEvent; +var jsdom; +var React; +var ReactDOM; describe('SyntheticClipboardEvent', () => { - var createEvent; + var document; + var simulateEvent; beforeEach(() => { - // TODO: can we express this test with only public API? - SyntheticClipboardEvent = require('SyntheticClipboardEvent'); - createEvent = function(nativeEvent) { - var target = require('getEventTarget')(nativeEvent); - return SyntheticClipboardEvent.getPooled({}, '', nativeEvent, target); + jsdom = require('jsdom').jsdom; + React = require('react'); + ReactDOM = require('react-dom'); + + document = jsdom(''); + + simulateEvent = (element, type, data) => { + var event = document.createEvent('Event'); + event.initEvent(type, true, true); + + if (data) { + event.clipboardData = data; + } + + element.dispatchEvent(event); }; }); @@ -27,6 +40,8 @@ describe('SyntheticClipboardEvent', () => { describe('clipboardData', () => { describe('when event has clipboardData', () => { it("returns event's clipboardData", () => { + var expectedCount = 3; + // Mock clipboardData since native implementation doesn't have a constructor var clipboardData = { dropEffect: null, @@ -35,9 +50,28 @@ describe('SyntheticClipboardEvent', () => { items: null, types: null, }; - var clipboardEvent = createEvent({clipboardData: clipboardData}); - expect(clipboardEvent.clipboardData).toBe(clipboardData); + var eventHandler = event => { + expect(event.clipboardData).toBe(clipboardData); + expectedCount -= 1; + }; + + var container = document.createElement('div'); + var div = ReactDOM.render( +
, + container, + ); + document.body.appendChild(div); + + simulateEvent(div, 'copy', clipboardData); + simulateEvent(div, 'cut', clipboardData); + simulateEvent(div, 'paste', clipboardData); + + expect(expectedCount).toBe(0); }); }); }); @@ -45,32 +79,88 @@ describe('SyntheticClipboardEvent', () => { describe('EventInterface', () => { it('normalizes properties from the Event interface', () => { - var target = document.createElement('div'); - var syntheticEvent = createEvent({srcElement: target}); + var expectedCount = 3; + var div; + + var eventHandler = type => event => { + expect(event.target).toBe(div); + expect(event.type).toBe(type); + expectedCount -= 1; + }; + + var container = document.createElement('div'); + div = ReactDOM.render( +
, + container, + ); + document.body.appendChild(div); + + simulateEvent(div, 'copy'); + simulateEvent(div, 'cut'); + simulateEvent(div, 'paste'); - expect(syntheticEvent.target).toBe(target); - expect(syntheticEvent.type).toBe(undefined); + expect(expectedCount).toBe(0); }); it('is able to `preventDefault` and `stopPropagation`', () => { - var nativeEvent = {}; - var syntheticEvent = createEvent(nativeEvent); + var expectedCount = 3; + var eventHandler = event => { + expect(event.isDefaultPrevented()).toBe(false); + event.preventDefault(); + expect(event.isDefaultPrevented()).toBe(true); + expect(event.isPropagationStopped()).toBe(false); + event.stopPropagation(); + expect(event.isPropagationStopped()).toBe(true); + expectedCount -= 1; + }; - expect(syntheticEvent.isDefaultPrevented()).toBe(false); - syntheticEvent.preventDefault(); - expect(syntheticEvent.isDefaultPrevented()).toBe(true); + var container = document.createElement('div'); + var div = ReactDOM.render( +
, + container, + ); + document.body.appendChild(div); - expect(syntheticEvent.isPropagationStopped()).toBe(false); - syntheticEvent.stopPropagation(); - expect(syntheticEvent.isPropagationStopped()).toBe(true); + simulateEvent(div, 'copy'); + simulateEvent(div, 'cut'); + simulateEvent(div, 'paste'); + + expect(expectedCount).toBe(0); }); it('is able to `persist`', () => { - var syntheticEvent = createEvent({}); + var expectedCount = 3; + var eventHandler = event => { + expect(event.isPersistent()).toBe(false); + event.persist(); + expect(event.isPersistent()).toBe(true); + expectedCount -= 1; + }; + + var container = document.createElement('div'); + var div = ReactDOM.render( +
, + container, + ); + document.body.appendChild(div); + + simulateEvent(div, 'copy'); + simulateEvent(div, 'cut'); + simulateEvent(div, 'paste'); - expect(syntheticEvent.isPersistent()).toBe(false); - syntheticEvent.persist(); - expect(syntheticEvent.isPersistent()).toBe(true); + expect(expectedCount).toBe(0); }); }); }); From 5a45e2fdfb4d8ede97ee90612973a3702ec8e46e Mon Sep 17 00:00:00 2001 From: Bernardo Smaniotto Date: Tue, 31 Oct 2017 19:28:55 -0200 Subject: [PATCH 2/7] Replace local document creation by document body reset on each test case execution --- .../src/events/__tests__/SyntheticClipboardEvent-test.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index 88af1c73675ba..ffa21be48a831 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -9,20 +9,17 @@ 'use strict'; -var jsdom; var React; var ReactDOM; describe('SyntheticClipboardEvent', () => { - var document; var simulateEvent; beforeEach(() => { - jsdom = require('jsdom').jsdom; React = require('react'); ReactDOM = require('react-dom'); - document = jsdom(''); + document.body.innerHTML = ''; simulateEvent = (element, type, data) => { var event = document.createEvent('Event'); @@ -108,6 +105,7 @@ describe('SyntheticClipboardEvent', () => { it('is able to `preventDefault` and `stopPropagation`', () => { var expectedCount = 3; + var eventHandler = event => { expect(event.isDefaultPrevented()).toBe(false); event.preventDefault(); @@ -138,6 +136,7 @@ describe('SyntheticClipboardEvent', () => { it('is able to `persist`', () => { var expectedCount = 3; + var eventHandler = event => { expect(event.isPersistent()).toBe(false); event.persist(); From 7843de1b02989e2c161a7cfce4d2694d05545b76 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 10 Nov 2017 12:07:27 +0000 Subject: [PATCH 3/7] Set up and tear down container separately --- .../__tests__/SyntheticClipboardEvent-test.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index ffa21be48a831..3eefff2ad171f 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -14,25 +14,30 @@ var ReactDOM; describe('SyntheticClipboardEvent', () => { var simulateEvent; + var container; beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); - document.body.innerHTML = ''; + container = document.createElement('div'); + document.body.appendChild(container); simulateEvent = (element, type, data) => { var event = document.createEvent('Event'); event.initEvent(type, true, true); - if (data) { event.clipboardData = data; } - element.dispatchEvent(event); }; }); + afterEach(() => { + document.body.removeChild(container); + container = null; + }); + describe('ClipboardEvent interface', () => { describe('clipboardData', () => { describe('when event has clipboardData', () => { @@ -53,7 +58,6 @@ describe('SyntheticClipboardEvent', () => { expectedCount -= 1; }; - var container = document.createElement('div'); var div = ReactDOM.render(
{ />, container, ); - document.body.appendChild(div); simulateEvent(div, 'copy', clipboardData); simulateEvent(div, 'cut', clipboardData); @@ -85,7 +88,6 @@ describe('SyntheticClipboardEvent', () => { expectedCount -= 1; }; - var container = document.createElement('div'); div = ReactDOM.render(
{ />, container, ); - document.body.appendChild(div); simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); @@ -116,7 +117,6 @@ describe('SyntheticClipboardEvent', () => { expectedCount -= 1; }; - var container = document.createElement('div'); var div = ReactDOM.render(
{ />, container, ); - document.body.appendChild(div); simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); @@ -144,7 +143,6 @@ describe('SyntheticClipboardEvent', () => { expectedCount -= 1; }; - var container = document.createElement('div'); var div = ReactDOM.render(
{ />, container, ); - document.body.appendChild(div); simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); From 6746cb25234ad4e5d3fc641bc4197d25dcf21dea Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 10 Nov 2017 12:49:07 +0000 Subject: [PATCH 4/7] Tweak test assertion logic for clarity --- .../__tests__/SyntheticClipboardEvent-test.js | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index 3eefff2ad171f..61bfd667bf476 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -42,7 +42,7 @@ describe('SyntheticClipboardEvent', () => { describe('clipboardData', () => { describe('when event has clipboardData', () => { it("returns event's clipboardData", () => { - var expectedCount = 3; + var expectedCount = 0; // Mock clipboardData since native implementation doesn't have a constructor var clipboardData = { @@ -52,12 +52,10 @@ describe('SyntheticClipboardEvent', () => { items: null, types: null, }; - var eventHandler = event => { expect(event.clipboardData).toBe(clipboardData); - expectedCount -= 1; + expectedCount++; }; - var div = ReactDOM.render(
{ simulateEvent(div, 'copy', clipboardData); simulateEvent(div, 'cut', clipboardData); simulateEvent(div, 'paste', clipboardData); - - expect(expectedCount).toBe(0); + expect(expectedCount).toBe(3); }); }); }); @@ -79,15 +76,14 @@ describe('SyntheticClipboardEvent', () => { describe('EventInterface', () => { it('normalizes properties from the Event interface', () => { - var expectedCount = 3; + var expectedCount = 0; var div; var eventHandler = type => event => { expect(event.target).toBe(div); expect(event.type).toBe(type); - expectedCount -= 1; + expectedCount++; }; - div = ReactDOM.render(
{ simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); simulateEvent(div, 'paste'); - - expect(expectedCount).toBe(0); + expect(expectedCount).toBe(3); }); it('is able to `preventDefault` and `stopPropagation`', () => { - var expectedCount = 3; + var expectedCount = 0; var eventHandler = event => { expect(event.isDefaultPrevented()).toBe(false); @@ -114,9 +109,8 @@ describe('SyntheticClipboardEvent', () => { expect(event.isPropagationStopped()).toBe(false); event.stopPropagation(); expect(event.isPropagationStopped()).toBe(true); - expectedCount -= 1; + expectedCount++; }; - var div = ReactDOM.render(
{ simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); simulateEvent(div, 'paste'); - - expect(expectedCount).toBe(0); + expect(expectedCount).toBe(3); }); it('is able to `persist`', () => { - var expectedCount = 3; + var expectedCount = 0; var eventHandler = event => { expect(event.isPersistent()).toBe(false); event.persist(); expect(event.isPersistent()).toBe(true); - expectedCount -= 1; + expectedCount++; }; - var div = ReactDOM.render(
{ simulateEvent(div, 'copy'); simulateEvent(div, 'cut'); simulateEvent(div, 'paste'); - - expect(expectedCount).toBe(0); + expect(expectedCount).toBe(3); }); }); }); From 21b7bda4159d688d79913ece3383f41d959e9f78 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 10 Nov 2017 15:37:33 +0000 Subject: [PATCH 5/7] Remove simulate abstraction and create events directly --- .../__tests__/SyntheticClipboardEvent-test.js | 81 ++++++++++++++----- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index 61bfd667bf476..0cffef9cf6493 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -22,15 +22,6 @@ describe('SyntheticClipboardEvent', () => { container = document.createElement('div'); document.body.appendChild(container); - - simulateEvent = (element, type, data) => { - var event = document.createEvent('Event'); - event.initEvent(type, true, true); - if (data) { - event.clipboardData = data; - } - element.dispatchEvent(event); - }; }); afterEach(() => { @@ -44,7 +35,7 @@ describe('SyntheticClipboardEvent', () => { it("returns event's clipboardData", () => { var expectedCount = 0; - // Mock clipboardData since native implementation doesn't have a constructor + // Mock clipboardData since jsdom implementation doesn't have a constructor var clipboardData = { dropEffect: null, effectAllowed: null, @@ -65,9 +56,22 @@ describe('SyntheticClipboardEvent', () => { container, ); - simulateEvent(div, 'copy', clipboardData); - simulateEvent(div, 'cut', clipboardData); - simulateEvent(div, 'paste', clipboardData); + var event; + event = document.createEvent('Event'); + event.initEvent('copy', true, true); + event.clipboardData = clipboardData; + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('cut', true, true); + event.clipboardData = clipboardData; + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('paste', true, true); + event.clipboardData = clipboardData; + div.dispatchEvent(event); + expect(expectedCount).toBe(3); }); }); @@ -84,6 +88,7 @@ describe('SyntheticClipboardEvent', () => { expect(event.type).toBe(type); expectedCount++; }; + div = ReactDOM.render(
{ container, ); - simulateEvent(div, 'copy'); - simulateEvent(div, 'cut'); - simulateEvent(div, 'paste'); + var event; + event = document.createEvent('Event'); + event.initEvent('copy', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('cut', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('paste', true, true); + div.dispatchEvent(event); + expect(expectedCount).toBe(3); }); @@ -111,6 +126,7 @@ describe('SyntheticClipboardEvent', () => { expect(event.isPropagationStopped()).toBe(true); expectedCount++; }; + var div = ReactDOM.render(
{ container, ); - simulateEvent(div, 'copy'); - simulateEvent(div, 'cut'); - simulateEvent(div, 'paste'); + var event; + event = document.createEvent('Event'); + event.initEvent('copy', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('cut', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('paste', true, true); + div.dispatchEvent(event); + expect(expectedCount).toBe(3); }); @@ -135,6 +161,7 @@ describe('SyntheticClipboardEvent', () => { expect(event.isPersistent()).toBe(true); expectedCount++; }; + var div = ReactDOM.render(
{ container, ); - simulateEvent(div, 'copy'); - simulateEvent(div, 'cut'); - simulateEvent(div, 'paste'); + var event; + event = document.createEvent('Event'); + event.initEvent('copy', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('cut', true, true); + div.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('paste', true, true); + div.dispatchEvent(event); + expect(expectedCount).toBe(3); }); }); From 5cf9b45b17de6742fad650fada49724e3f15907c Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 10 Nov 2017 15:39:02 +0000 Subject: [PATCH 6/7] Ensure the test covers IE8 behavior --- .../__tests__/SyntheticClipboardEvent-test.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index 0cffef9cf6493..5dc56dceb817a 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -101,14 +101,41 @@ describe('SyntheticClipboardEvent', () => { var event; event = document.createEvent('Event'); event.initEvent('copy', true, true); + // Emulate IE8 + Object.defineProperty(event, 'target', { + get() {}, + }); + Object.defineProperty(event, 'srcElement', { + get() { + return div; + }, + }); div.dispatchEvent(event); event = document.createEvent('Event'); event.initEvent('cut', true, true); + // Emulate IE8 + Object.defineProperty(event, 'target', { + get() {}, + }); + Object.defineProperty(event, 'srcElement', { + get() { + return div; + }, + }); div.dispatchEvent(event); event = document.createEvent('Event'); event.initEvent('paste', true, true); + // Emulate IE8 + Object.defineProperty(event, 'target', { + get() {}, + }); + Object.defineProperty(event, 'srcElement', { + get() { + return div; + }, + }); div.dispatchEvent(event); expect(expectedCount).toBe(3); From 3cf7e3ae45c264118df7ab7a7b0797a06e80060b Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 10 Nov 2017 15:47:07 +0000 Subject: [PATCH 7/7] Verify that persistence works --- .../src/events/__tests__/SyntheticClipboardEvent-test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js index 5dc56dceb817a..4496e388bbe9d 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js @@ -182,11 +182,12 @@ describe('SyntheticClipboardEvent', () => { it('is able to `persist`', () => { var expectedCount = 0; + const persistentEvents = []; var eventHandler = event => { expect(event.isPersistent()).toBe(false); event.persist(); expect(event.isPersistent()).toBe(true); - expectedCount++; + persistentEvents.push(event); }; var div = ReactDOM.render( @@ -211,7 +212,10 @@ describe('SyntheticClipboardEvent', () => { event.initEvent('paste', true, true); div.dispatchEvent(event); - expect(expectedCount).toBe(3); + expect(persistentEvents.length).toBe(3); + expect(persistentEvents[0].type).toBe('copy'); + expect(persistentEvents[1].type).toBe('cut'); + expect(persistentEvents[2].type).toBe('paste'); }); }); });