From 37815d5224537a50dff35c32289b9cf38fe61d9d Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Mon, 23 Mar 2020 12:57:42 -0500 Subject: [PATCH 1/7] fix: set composed init option for relevant UI events --- src/events.js | 90 +++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/events.js b/src/events.js index f6896c3c..7b819792 100644 --- a/src/events.js +++ b/src/events.js @@ -3,58 +3,58 @@ const eventMap = { // Clipboard Events copy: { EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, cut: { EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, paste: { EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, // Composition Events compositionEnd: { EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, compositionStart: { EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, compositionUpdate: { EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, // Keyboard Events keyDown: { EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0}, + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, }, keyPress: { EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0}, + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, }, keyUp: { EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0}, + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, }, // Focus Events focus: { EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, blur: { EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, focusIn: { EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, focusOut: { EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, // Form Events change: { @@ -63,7 +63,7 @@ const eventMap = { }, input: { EventType: 'InputEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, invalid: { EventType: 'Event', @@ -80,75 +80,75 @@ const eventMap = { // Mouse Events click: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, button: 0}, + defaultInit: {bubbles: true, cancelable: true, button: 0, composed: true}, }, contextMenu: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, dblClick: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, drag: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, dragEnd: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, dragEnter: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, dragExit: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, dragLeave: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, dragOver: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, dragStart: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, drop: { EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, mouseDown: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, mouseEnter: { EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, mouseLeave: { EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, mouseMove: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, mouseOut: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, mouseOver: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, mouseUp: { EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, // Selection Events select: { @@ -158,19 +158,19 @@ const eventMap = { // Touch Events touchCancel: { EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, touchEnd: { EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, touchMove: { EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, touchStart: { EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, // UI Events scroll: { @@ -180,7 +180,7 @@ const eventMap = { // Wheel Events wheel: { EventType: 'WheelEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, // Media Events abort: { @@ -301,35 +301,35 @@ const eventMap = { // pointer events pointerOver: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, pointerEnter: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, pointerDown: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, pointerMove: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, pointerUp: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, pointerCancel: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: false}, + defaultInit: {bubbles: true, cancelable: false, composed: true}, }, pointerOut: { EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true}, + defaultInit: {bubbles: true, cancelable: true, composed: true}, }, pointerLeave: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, gotPointerCapture: { EventType: 'PointerEvent', From 71bab0a7233ae6a0f645b1d9f1482ef8f3b3c0b7 Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Mon, 23 Mar 2020 16:05:10 -0500 Subject: [PATCH 2/7] test: add composed event tests --- src/__tests__/events.js | 115 +++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index fdf78083..39728541 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -3,7 +3,7 @@ import {fireEvent} from '..' const eventTypes = [ { type: 'Clipboard', - events: ['copy', 'paste'], + events: ['copy', 'cut', 'paste'], elementType: 'input', }, { @@ -137,6 +137,12 @@ const eventTypes = [ }, ] +const allEvents = eventTypes + .reduce((acc, curr) => { + acc.push(...curr.events) + return acc + }, []) + const bubblingEvents = [ 'copy', 'cut', @@ -187,43 +193,58 @@ const bubblingEvents = [ 'pointerOut', ] -const nonBubblingEvents = [ +const nonBubblingEvents = allEvents.filter(evt => !bubblingEvents.includes(evt)) + +const composedEvents = [ + 'copy', + 'cut', + 'paste', + 'compositionEnd', + 'compositionStart', + 'compositionUpdate', + 'keyDown', + 'keyPress', + 'keyUp', 'focus', 'blur', - 'invalid', + 'focusIn', + 'focusOut', + 'input', + 'click', + 'contextMenu', + 'dblClick', + 'drag', + 'dragEnd', + 'dragEnter', + 'dragExit', + 'dragLeave', + 'dragOver', + 'dragStart', + 'drop', + 'mouseDown', 'mouseEnter', 'mouseLeave', - 'scroll', - 'abort', - 'canPlay', - 'canPlayThrough', - 'durationChange', - 'emptied', - 'encrypted', - 'ended', - 'loadedData', - 'loadedMetadata', - 'loadStart', - 'pause', - 'play', - 'playing', - 'progress', - 'rateChange', - 'seeked', - 'seeking', - 'stalled', - 'suspend', - 'timeUpdate', - 'volumeChange', - 'waiting', - 'load', - 'error', + 'mouseMove', + 'mouseOut', + 'mouseOver', + 'mouseUp', + 'touchCancel', + 'touchEnd', + 'touchMove', + 'touchStart', + 'wheel', + 'pointerOver', 'pointerEnter', + 'pointerDown', + 'pointerMove', + 'pointerUp', + 'pointerCancel', + 'pointerOut', 'pointerLeave', - 'gotPointerCapture', - 'lostPointerCapture', ] +const nonComposedEvents = allEvents.filter(evt => !composedEvents.includes(evt)) + eventTypes.forEach(({type, events, elementType}) => { describe(`${type} Events`, () => { events.forEach(eventName => { @@ -268,6 +289,40 @@ describe(`Bubbling Events`, () => { ) }) +describe(`Composed Events`, () => { + composedEvents.forEach(event => + it(`${event} crosses shadow DOM boundary`, () => { + const node = document.createElement('div') + const spy = jest.fn() + node.addEventListener(event.toLowerCase(), spy) + + const shadowRoot = node.attachShadow({ mode: 'open' }) + const innerNode = document.createElement('div') + + shadowRoot.appendChild(innerNode) + + fireEvent[event](innerNode) + expect(spy).toHaveBeenCalledTimes(1) + }), + ) + + nonComposedEvents.forEach(event => + it(`${event} does not cross shadow DOM boundary`, () => { + const node = document.createElement('div') + const spy = jest.fn() + node.addEventListener(event.toLowerCase(), spy) + + const shadowRoot = node.attachShadow({ mode: 'open' }) + const innerNode = document.createElement('div') + + shadowRoot.appendChild(innerNode) + + fireEvent[event](innerNode) + expect(spy).not.toHaveBeenCalled() + }), + ) +}) + describe(`Aliased Events`, () => { it(`fires doubleClick`, () => { const node = document.createElement('div') From 632cf768d2b13dcbcb8e6564537da9a09670cf93 Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Mon, 23 Mar 2020 17:01:26 -0500 Subject: [PATCH 3/7] test: use closed shadow roots for composed event tests --- src/__tests__/events.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index 39728541..7e5a7ecd 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -296,9 +296,8 @@ describe(`Composed Events`, () => { const spy = jest.fn() node.addEventListener(event.toLowerCase(), spy) - const shadowRoot = node.attachShadow({ mode: 'open' }) + const shadowRoot = node.attachShadow({ mode: 'closed' }) const innerNode = document.createElement('div') - shadowRoot.appendChild(innerNode) fireEvent[event](innerNode) @@ -312,9 +311,8 @@ describe(`Composed Events`, () => { const spy = jest.fn() node.addEventListener(event.toLowerCase(), spy) - const shadowRoot = node.attachShadow({ mode: 'open' }) + const shadowRoot = node.attachShadow({ mode: 'closed' }) const innerNode = document.createElement('div') - shadowRoot.appendChild(innerNode) fireEvent[event](innerNode) From 0f2a018b2a7483856dcf5e20b498770e747dd2ab Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Wed, 25 Mar 2020 20:41:27 -0500 Subject: [PATCH 4/7] refact: move event maps into shared file --- src/__tests__/events.js | 22 +-- src/event-map.js | 350 +++++++++++++++++++++++++++++++++++++++ src/events.js | 351 +--------------------------------------- 3 files changed, 362 insertions(+), 361 deletions(-) create mode 100644 src/event-map.js diff --git a/src/__tests__/events.js b/src/__tests__/events.js index 7e5a7ecd..8333ab08 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -1,3 +1,4 @@ +import {eventMap, eventAliasMap} from '../event-map' import {fireEvent} from '..' const eventTypes = [ @@ -137,11 +138,7 @@ const eventTypes = [ }, ] -const allEvents = eventTypes - .reduce((acc, curr) => { - acc.push(...curr.events) - return acc - }, []) +const allEvents = Object.keys(eventMap) const bubblingEvents = [ 'copy', @@ -191,6 +188,7 @@ const bubblingEvents = [ 'pointerUp', 'pointerCancel', 'pointerOut', + 'popState', ] const nonBubblingEvents = allEvents.filter(evt => !bubblingEvents.includes(evt)) @@ -322,12 +320,14 @@ describe(`Composed Events`, () => { }) describe(`Aliased Events`, () => { - it(`fires doubleClick`, () => { - const node = document.createElement('div') - const spy = jest.fn() - node.addEventListener('dblclick', spy) - fireEvent.doubleClick(node) - expect(spy).toHaveBeenCalledTimes(1) + Object.keys(eventAliasMap).forEach(eventAlias => { + it(`fires ${eventAlias}`, () => { + const node = document.createElement('div') + const spy = jest.fn() + node.addEventListener(eventAliasMap[eventAlias].toLowerCase(), spy) + fireEvent.doubleClick(node) + expect(spy).toHaveBeenCalledTimes(1) + }) }) }) diff --git a/src/event-map.js b/src/event-map.js new file mode 100644 index 00000000..5eb27af3 --- /dev/null +++ b/src/event-map.js @@ -0,0 +1,350 @@ +export const eventMap = { + // Clipboard Events + copy: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + cut: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + paste: { + EventType: 'ClipboardEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Composition Events + compositionEnd: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + compositionStart: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + compositionUpdate: { + EventType: 'CompositionEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Keyboard Events + keyDown: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + keyPress: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + keyUp: { + EventType: 'KeyboardEvent', + defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, + }, + // Focus Events + focus: { + EventType: 'FocusEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + blur: { + EventType: 'FocusEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + focusIn: { + EventType: 'FocusEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + focusOut: { + EventType: 'FocusEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + // Form Events + change: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: false}, + }, + input: { + EventType: 'InputEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + invalid: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: true}, + }, + submit: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: true}, + }, + reset: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: true}, + }, + // Mouse Events + click: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, button: 0, composed: true}, + }, + contextMenu: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dblClick: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + drag: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragEnd: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragEnter: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragExit: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragLeave: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + dragOver: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + dragStart: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + drop: { + EventType: 'DragEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseDown: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseEnter: { + EventType: 'MouseEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + mouseLeave: { + EventType: 'MouseEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + mouseMove: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseOut: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseOver: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + mouseUp: { + EventType: 'MouseEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Selection Events + select: { + EventType: 'Event', + defaultInit: {bubbles: true, cancelable: false}, + }, + // Touch Events + touchCancel: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + touchEnd: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + touchMove: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + touchStart: { + EventType: 'TouchEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // UI Events + scroll: { + EventType: 'UIEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Wheel Events + wheel: { + EventType: 'WheelEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + // Media Events + abort: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + canPlay: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + canPlayThrough: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + durationChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + emptied: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + encrypted: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + ended: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadedData: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadedMetadata: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + loadStart: { + EventType: 'ProgressEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + pause: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + play: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + playing: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + progress: { + EventType: 'ProgressEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + rateChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + seeked: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + seeking: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + stalled: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + suspend: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + timeUpdate: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + volumeChange: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + waiting: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Image Events + load: { + EventType: 'UIEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + error: { + EventType: 'Event', + defaultInit: {bubbles: false, cancelable: false}, + }, + // Animation Events + animationStart: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + animationEnd: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + animationIteration: { + EventType: 'AnimationEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + // Transition Events + transitionEnd: { + EventType: 'TransitionEvent', + defaultInit: {bubbles: true, cancelable: true}, + }, + // pointer events + pointerOver: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerEnter: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + pointerDown: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerMove: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerUp: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerCancel: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: false, composed: true}, + }, + pointerOut: { + EventType: 'PointerEvent', + defaultInit: {bubbles: true, cancelable: true, composed: true}, + }, + pointerLeave: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false, composed: true}, + }, + gotPointerCapture: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + lostPointerCapture: { + EventType: 'PointerEvent', + defaultInit: {bubbles: false, cancelable: false}, + }, + // history events + popState: { + EventType: 'PopStateEvent', + defaultInit: {bubbles: true, cancelable: false}, + }, + } + + export const eventAliasMap = { + doubleClick: 'dblClick', + } diff --git a/src/events.js b/src/events.js index 7b819792..389fdab3 100644 --- a/src/events.js +++ b/src/events.js @@ -1,354 +1,5 @@ import {getWindowFromNode} from './helpers' -const eventMap = { - // Clipboard Events - copy: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - cut: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - paste: { - EventType: 'ClipboardEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Composition Events - compositionEnd: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - compositionStart: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - compositionUpdate: { - EventType: 'CompositionEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Keyboard Events - keyDown: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - keyPress: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - keyUp: { - EventType: 'KeyboardEvent', - defaultInit: {bubbles: true, cancelable: true, charCode: 0, composed: true}, - }, - // Focus Events - focus: { - EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - blur: { - EventType: 'FocusEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - focusIn: { - EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - focusOut: { - EventType: 'FocusEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - // Form Events - change: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: false}, - }, - input: { - EventType: 'InputEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - invalid: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: true}, - }, - submit: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: true}, - }, - reset: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: true}, - }, - // Mouse Events - click: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, button: 0, composed: true}, - }, - contextMenu: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dblClick: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - drag: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragEnd: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragEnter: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragExit: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragLeave: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - dragOver: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - dragStart: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - drop: { - EventType: 'DragEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseDown: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseEnter: { - EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - mouseLeave: { - EventType: 'MouseEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - mouseMove: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseOut: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseOver: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - mouseUp: { - EventType: 'MouseEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Selection Events - select: { - EventType: 'Event', - defaultInit: {bubbles: true, cancelable: false}, - }, - // Touch Events - touchCancel: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - touchEnd: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - touchMove: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - touchStart: { - EventType: 'TouchEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // UI Events - scroll: { - EventType: 'UIEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Wheel Events - wheel: { - EventType: 'WheelEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - // Media Events - abort: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - canPlay: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - canPlayThrough: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - durationChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - emptied: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - encrypted: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - ended: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadedData: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadedMetadata: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - loadStart: { - EventType: 'ProgressEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - pause: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - play: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - playing: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - progress: { - EventType: 'ProgressEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - rateChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - seeked: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - seeking: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - stalled: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - suspend: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - timeUpdate: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - volumeChange: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - waiting: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Image Events - load: { - EventType: 'UIEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - error: { - EventType: 'Event', - defaultInit: {bubbles: false, cancelable: false}, - }, - // Animation Events - animationStart: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - animationEnd: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - animationIteration: { - EventType: 'AnimationEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, - // Transition Events - transitionEnd: { - EventType: 'TransitionEvent', - defaultInit: {bubbles: true, cancelable: true}, - }, - // pointer events - pointerOver: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerEnter: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - pointerDown: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerMove: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerUp: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerCancel: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: false, composed: true}, - }, - pointerOut: { - EventType: 'PointerEvent', - defaultInit: {bubbles: true, cancelable: true, composed: true}, - }, - pointerLeave: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, - }, - gotPointerCapture: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - lostPointerCapture: { - EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, - }, - // history events - popState: { - EventType: 'PopStateEvent', - defaultInit: {bubbles: true, cancelable: false}, - }, -} - -const eventAliasMap = { - doubleClick: 'dblClick', -} +import {eventMap, eventAliasMap} from './event-map' function fireEvent(element, event) { if (!event) { From f43370fda1a22111eef3b8b2ab4e1bdbdca18950 Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Wed, 25 Mar 2020 20:49:52 -0500 Subject: [PATCH 5/7] test: forgot to fully genericize event alias tests --- src/__tests__/events.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index 8333ab08..e93ddb80 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -325,7 +325,8 @@ describe(`Aliased Events`, () => { const node = document.createElement('div') const spy = jest.fn() node.addEventListener(eventAliasMap[eventAlias].toLowerCase(), spy) - fireEvent.doubleClick(node) + + fireEvent[eventAlias](node) expect(spy).toHaveBeenCalledTimes(1) }) }) From 18a38329bf15378d1612673cad06d93a17cfed4e Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Wed, 25 Mar 2020 21:32:51 -0500 Subject: [PATCH 6/7] fix: align pointer events with spec (Chrome is non-conformant) --- src/__tests__/events.js | 4 ++-- src/event-map.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index e93ddb80..fbef9d05 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -232,13 +232,13 @@ const composedEvents = [ 'touchStart', 'wheel', 'pointerOver', - 'pointerEnter', 'pointerDown', 'pointerMove', 'pointerUp', 'pointerCancel', 'pointerOut', - 'pointerLeave', + 'gotPointerCapture', + 'lostPointerCapture', ] const nonComposedEvents = allEvents.filter(evt => !composedEvents.includes(evt)) diff --git a/src/event-map.js b/src/event-map.js index 5eb27af3..98d78e66 100644 --- a/src/event-map.js +++ b/src/event-map.js @@ -304,7 +304,7 @@ export const eventMap = { }, pointerEnter: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, + defaultInit: {bubbles: false, cancelable: false}, }, pointerDown: { EventType: 'PointerEvent', @@ -328,15 +328,15 @@ export const eventMap = { }, pointerLeave: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false, composed: true}, + defaultInit: {bubbles: false, cancelable: false}, }, gotPointerCapture: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, lostPointerCapture: { EventType: 'PointerEvent', - defaultInit: {bubbles: false, cancelable: false}, + defaultInit: {bubbles: false, cancelable: false, composed: true}, }, // history events popState: { From 13e3d5ee94a6d1ea95c61dc94de35eea9c971ebe Mon Sep 17 00:00:00 2001 From: Adam Palaniuk Date: Fri, 27 Mar 2020 11:41:27 -0500 Subject: [PATCH 7/7] test: derive event init classes from event map --- src/__tests__/events.js | 107 +++------------------------------------- 1 file changed, 8 insertions(+), 99 deletions(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index fbef9d05..f91cf408 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -140,108 +140,17 @@ const eventTypes = [ const allEvents = Object.keys(eventMap) -const bubblingEvents = [ - 'copy', - 'cut', - 'paste', - 'compositionEnd', - 'compositionStart', - 'compositionUpdate', - 'keyDown', - 'keyPress', - 'keyUp', - 'focusIn', - 'focusOut', - 'change', - 'input', - 'submit', - 'reset', - 'click', - 'contextMenu', - 'dblClick', - 'drag', - 'dragEnd', - 'dragEnter', - 'dragExit', - 'dragLeave', - 'dragOver', - 'dragStart', - 'drop', - 'mouseDown', - 'mouseMove', - 'mouseOut', - 'mouseOver', - 'mouseUp', - 'select', - 'touchCancel', - 'touchEnd', - 'touchMove', - 'touchStart', - 'wheel', - 'animationStart', - 'animationEnd', - 'animationIteration', - 'transitionEnd', - 'pointerOver', - 'pointerDown', - 'pointerMove', - 'pointerUp', - 'pointerCancel', - 'pointerOut', - 'popState', -] +const bubblingEvents = allEvents + .filter(eventName => eventMap[eventName].defaultInit.bubbles) -const nonBubblingEvents = allEvents.filter(evt => !bubblingEvents.includes(evt)) +const composedEvents = allEvents + .filter(eventName => eventMap[eventName].defaultInit.composed) -const composedEvents = [ - 'copy', - 'cut', - 'paste', - 'compositionEnd', - 'compositionStart', - 'compositionUpdate', - 'keyDown', - 'keyPress', - 'keyUp', - 'focus', - 'blur', - 'focusIn', - 'focusOut', - 'input', - 'click', - 'contextMenu', - 'dblClick', - 'drag', - 'dragEnd', - 'dragEnter', - 'dragExit', - 'dragLeave', - 'dragOver', - 'dragStart', - 'drop', - 'mouseDown', - 'mouseEnter', - 'mouseLeave', - 'mouseMove', - 'mouseOut', - 'mouseOver', - 'mouseUp', - 'touchCancel', - 'touchEnd', - 'touchMove', - 'touchStart', - 'wheel', - 'pointerOver', - 'pointerDown', - 'pointerMove', - 'pointerUp', - 'pointerCancel', - 'pointerOut', - 'gotPointerCapture', - 'lostPointerCapture', -] +const nonBubblingEvents = allEvents + .filter(eventName => !bubblingEvents.includes(eventName)) -const nonComposedEvents = allEvents.filter(evt => !composedEvents.includes(evt)) +const nonComposedEvents = allEvents + .filter(eventName => !composedEvents.includes(eventName)) eventTypes.forEach(({type, events, elementType}) => { describe(`${type} Events`, () => {