diff --git a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js index 052f1c084529..1112ca4fb015 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js @@ -9,79 +9,170 @@ 'use strict'; -var SyntheticEvent; var React; var ReactDOM; var ReactTestUtils; describe('SyntheticEvent', () => { - var createEvent; + var container; beforeEach(() => { - // TODO: can we express this test with only public API? - SyntheticEvent = require('events/SyntheticEvent').default; React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('react-dom/test-utils'); - createEvent = function(nativeEvent) { - var target = require('../getEventTarget').default(nativeEvent); - return SyntheticEvent.getPooled({}, '', nativeEvent, target); - }; + container = document.createElement('div'); + document.body.appendChild(container); + }); + + afterEach(() => { + document.body.removeChild(container); + container = null; }); it('should normalize `target` from the nativeEvent', () => { - var target = document.createElement('div'); - var syntheticEvent = createEvent({srcElement: target}); + var node; + var expectedCount = 0; + + var eventHandler = syntheticEvent => { + expect(syntheticEvent.target).toBe(node); + + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + // Emulate IE8 + Object.defineProperty(event, 'target', { + get() {}, + }); + Object.defineProperty(event, 'srcElement', { + get() { + return node; + }, + }); + node.dispatchEvent(event); - expect(syntheticEvent.target).toBe(target); - expect(syntheticEvent.type).toBe(undefined); + expect(expectedCount).toBe(1); }); it('should be able to `preventDefault`', () => { - var nativeEvent = {}; - var syntheticEvent = createEvent(nativeEvent); + var node; + var expectedCount = 0; - expect(syntheticEvent.isDefaultPrevented()).toBe(false); - syntheticEvent.preventDefault(); - expect(syntheticEvent.isDefaultPrevented()).toBe(true); + var eventHandler = syntheticEvent => { + expect(syntheticEvent.isDefaultPrevented()).toBe(false); + syntheticEvent.preventDefault(); + expect(syntheticEvent.isDefaultPrevented()).toBe(true); + expect(syntheticEvent.defaultPrevented).toBe(true); + + expectedCount++; + }; + node = ReactDOM.render(
, container); - expect(syntheticEvent.defaultPrevented).toBe(true); + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); - expect(nativeEvent.returnValue).toBe(false); + expect(expectedCount).toBe(1); }); it('should be prevented if nativeEvent is prevented', () => { - expect(createEvent({defaultPrevented: true}).isDefaultPrevented()).toBe( - true, - ); - expect(createEvent({returnValue: false}).isDefaultPrevented()).toBe(true); + var node; + var expectedCount = 0; + + var eventHandler = syntheticEvent => { + expect(syntheticEvent.isDefaultPrevented()).toBe(true); + + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event; + event = document.createEvent('Event'); + event.initEvent('click', true, true); + event.preventDefault(); + node.dispatchEvent(event); + + event = document.createEvent('Event'); + event.initEvent('click', true, true); + // Emulate IE8 + Object.defineProperty(event, 'defaultPrevented', { + get() {}, + }); + Object.defineProperty(event, 'returnValue', { + get() { + return false; + }, + }); + node.dispatchEvent(event); + + expect(expectedCount).toBe(2); }); it('should be able to `stopPropagation`', () => { - var nativeEvent = {}; - var syntheticEvent = createEvent(nativeEvent); + var node; + var expectedCount = 0; - expect(syntheticEvent.isPropagationStopped()).toBe(false); - syntheticEvent.stopPropagation(); - expect(syntheticEvent.isPropagationStopped()).toBe(true); + var eventHandler = syntheticEvent => { + expect(syntheticEvent.isPropagationStopped()).toBe(false); + syntheticEvent.stopPropagation(); + expect(syntheticEvent.isPropagationStopped()).toBe(true); - expect(nativeEvent.cancelBubble).toBe(true); + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); + + expect(expectedCount).toBe(1); }); it('should be able to `persist`', () => { - var syntheticEvent = createEvent({}); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + expect(e.isPersistent()).toBe(false); + e.persist(); + syntheticEvent = e; + expect(e.isPersistent()).toBe(true); + + expectedCount++; + }; + node = ReactDOM.render(
, container); - expect(syntheticEvent.isPersistent()).toBe(false); - syntheticEvent.persist(); - expect(syntheticEvent.isPersistent()).toBe(true); + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); + + expect(syntheticEvent.type).toBe('click'); + expect(syntheticEvent.bubbles).toBe(true); + expect(syntheticEvent.cancelable).toBe(true); + expect(expectedCount).toBe(1); }); - it('should be nullified if the synthetic event has called destructor and log warnings', () => { + it('should be nullified and log warnings if the synthetic event has not been persisted', () => { spyOn(console, 'error'); - var target = document.createElement('div'); - var syntheticEvent = createEvent({srcElement: target}); - syntheticEvent.destructor(); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + syntheticEvent = e; + + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); + expect(syntheticEvent.type).toBe(null); expect(syntheticEvent.nativeEvent).toBe(null); expect(syntheticEvent.target).toBe(null); @@ -95,14 +186,27 @@ describe('SyntheticEvent', () => { 'keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', ); + expect(expectedCount).toBe(1); }); - it('should warn when setting properties of a destructored synthetic event', () => { + it('should warn when setting properties of a synthetic event that has not been persisted', () => { spyOn(console, 'error'); - var target = document.createElement('div'); - var syntheticEvent = createEvent({srcElement: target}); - syntheticEvent.destructor(); - expect((syntheticEvent.type = 'MouseEvent')).toBe('MouseEvent'); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + syntheticEvent = e; + + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); + + syntheticEvent.type = 'MouseEvent'; expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toBe( 'Warning: This synthetic event is reused for performance reasons. If ' + @@ -111,12 +215,25 @@ describe('SyntheticEvent', () => { 'keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', ); + expect(expectedCount).toBe(1); }); - it('should warn if the synthetic event has been released when calling `preventDefault`', () => { + it('should warn when calling `preventDefault` if the synthetic event has not been persisted', () => { spyOn(console, 'error'); - var syntheticEvent = createEvent({}); - SyntheticEvent.release(syntheticEvent); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + syntheticEvent = e; + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + node.dispatchEvent(event); + syntheticEvent.preventDefault(); expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toBe( @@ -126,12 +243,26 @@ describe('SyntheticEvent', () => { 'keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', ); + expect(expectedCount).toBe(1); }); - it('should warn if the synthetic event has been released when calling `stopPropagation`', () => { + it('should warn when calling `stopPropagation` if the synthetic event has not been persisted', () => { spyOn(console, 'error'); - var syntheticEvent = createEvent({}); - SyntheticEvent.release(syntheticEvent); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + syntheticEvent = e; + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + + node.dispatchEvent(event); + syntheticEvent.stopPropagation(); expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toBe( @@ -141,6 +272,7 @@ describe('SyntheticEvent', () => { 'keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', ); + expect(expectedCount).toBe(1); }); // TODO: reenable this test. We are currently silencing these warnings when @@ -153,8 +285,8 @@ describe('SyntheticEvent', () => { function assignEvent(e) { event = e; } - var instance = ReactDOM.render(
, element); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance)); + var node = ReactDOM.render(
, element); + ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(node)); expectDev(console.error.calls.count()).toBe(0); // access a property to cause the warning @@ -172,9 +304,22 @@ describe('SyntheticEvent', () => { it('should warn if Proxy is supported and the synthetic event is added a property', () => { spyOn(console, 'error'); - var syntheticEvent = createEvent({}); - syntheticEvent.foo = 'bar'; - SyntheticEvent.release(syntheticEvent); + var node; + var expectedCount = 0; + var syntheticEvent; + + var eventHandler = e => { + e.foo = 'bar'; + syntheticEvent = e; + expectedCount++; + }; + node = ReactDOM.render(
, container); + + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + + node.dispatchEvent(event); + expect(syntheticEvent.foo).toBe('bar'); if (typeof Proxy === 'function') { expectDev(console.error.calls.count()).toBe(1); @@ -187,5 +332,6 @@ describe('SyntheticEvent', () => { } else { expectDev(console.error.calls.count()).toBe(0); } + expect(expectedCount).toBe(1); }); });