Skip to content

Commit 39dc929

Browse files
apalaniukeps1lon
andauthored
fix(fireEvent): Set composed property on relevant synthetic events (#496)
* fix: set composed init option for relevant UI events * test: add composed event tests * test: use closed shadow roots for composed event tests * refact: move event maps into shared file * test: forgot to fully genericize event alias tests * fix: align pointer events with spec (Chrome is non-conformant) * test: derive event init classes from event map Co-authored-by: Sebastian Silbermann <[email protected]>
1 parent 0f8f029 commit 39dc929

File tree

3 files changed

+406
-442
lines changed

3 files changed

+406
-442
lines changed

src/__tests__/events.js

Lines changed: 55 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import {eventMap, eventAliasMap} from '../event-map'
12
import {fireEvent} from '..'
23

34
const eventTypes = [
45
{
56
type: 'Clipboard',
6-
events: ['copy', 'paste'],
7+
events: ['copy', 'cut', 'paste'],
78
elementType: 'input',
89
},
910
{
@@ -137,92 +138,19 @@ const eventTypes = [
137138
},
138139
]
139140

140-
const bubblingEvents = [
141-
'copy',
142-
'cut',
143-
'paste',
144-
'compositionEnd',
145-
'compositionStart',
146-
'compositionUpdate',
147-
'keyDown',
148-
'keyPress',
149-
'keyUp',
150-
'focusIn',
151-
'focusOut',
152-
'change',
153-
'input',
154-
'submit',
155-
'reset',
156-
'click',
157-
'contextMenu',
158-
'dblClick',
159-
'drag',
160-
'dragEnd',
161-
'dragEnter',
162-
'dragExit',
163-
'dragLeave',
164-
'dragOver',
165-
'dragStart',
166-
'drop',
167-
'mouseDown',
168-
'mouseMove',
169-
'mouseOut',
170-
'mouseOver',
171-
'mouseUp',
172-
'select',
173-
'touchCancel',
174-
'touchEnd',
175-
'touchMove',
176-
'touchStart',
177-
'wheel',
178-
'animationStart',
179-
'animationEnd',
180-
'animationIteration',
181-
'transitionEnd',
182-
'pointerOver',
183-
'pointerDown',
184-
'pointerMove',
185-
'pointerUp',
186-
'pointerCancel',
187-
'pointerOut',
188-
]
141+
const allEvents = Object.keys(eventMap)
189142

190-
const nonBubblingEvents = [
191-
'focus',
192-
'blur',
193-
'invalid',
194-
'mouseEnter',
195-
'mouseLeave',
196-
'scroll',
197-
'abort',
198-
'canPlay',
199-
'canPlayThrough',
200-
'durationChange',
201-
'emptied',
202-
'encrypted',
203-
'ended',
204-
'loadedData',
205-
'loadedMetadata',
206-
'loadStart',
207-
'pause',
208-
'play',
209-
'playing',
210-
'progress',
211-
'rateChange',
212-
'seeked',
213-
'seeking',
214-
'stalled',
215-
'suspend',
216-
'timeUpdate',
217-
'volumeChange',
218-
'waiting',
219-
'load',
220-
'error',
221-
'pointerEnter',
222-
'pointerLeave',
223-
'gotPointerCapture',
224-
'lostPointerCapture',
225-
]
143+
const bubblingEvents = allEvents
144+
.filter(eventName => eventMap[eventName].defaultInit.bubbles)
145+
146+
const composedEvents = allEvents
147+
.filter(eventName => eventMap[eventName].defaultInit.composed)
148+
149+
const nonBubblingEvents = allEvents
150+
.filter(eventName => !bubblingEvents.includes(eventName))
151+
152+
const nonComposedEvents = allEvents
153+
.filter(eventName => !composedEvents.includes(eventName))
226154

227155
eventTypes.forEach(({type, events, elementType}) => {
228156
describe(`${type} Events`, () => {
@@ -268,13 +196,48 @@ describe(`Bubbling Events`, () => {
268196
)
269197
})
270198

199+
describe(`Composed Events`, () => {
200+
composedEvents.forEach(event =>
201+
it(`${event} crosses shadow DOM boundary`, () => {
202+
const node = document.createElement('div')
203+
const spy = jest.fn()
204+
node.addEventListener(event.toLowerCase(), spy)
205+
206+
const shadowRoot = node.attachShadow({ mode: 'closed' })
207+
const innerNode = document.createElement('div')
208+
shadowRoot.appendChild(innerNode)
209+
210+
fireEvent[event](innerNode)
211+
expect(spy).toHaveBeenCalledTimes(1)
212+
}),
213+
)
214+
215+
nonComposedEvents.forEach(event =>
216+
it(`${event} does not cross shadow DOM boundary`, () => {
217+
const node = document.createElement('div')
218+
const spy = jest.fn()
219+
node.addEventListener(event.toLowerCase(), spy)
220+
221+
const shadowRoot = node.attachShadow({ mode: 'closed' })
222+
const innerNode = document.createElement('div')
223+
shadowRoot.appendChild(innerNode)
224+
225+
fireEvent[event](innerNode)
226+
expect(spy).not.toHaveBeenCalled()
227+
}),
228+
)
229+
})
230+
271231
describe(`Aliased Events`, () => {
272-
it(`fires doubleClick`, () => {
273-
const node = document.createElement('div')
274-
const spy = jest.fn()
275-
node.addEventListener('dblclick', spy)
276-
fireEvent.doubleClick(node)
277-
expect(spy).toHaveBeenCalledTimes(1)
232+
Object.keys(eventAliasMap).forEach(eventAlias => {
233+
it(`fires ${eventAlias}`, () => {
234+
const node = document.createElement('div')
235+
const spy = jest.fn()
236+
node.addEventListener(eventAliasMap[eventAlias].toLowerCase(), spy)
237+
238+
fireEvent[eventAlias](node)
239+
expect(spy).toHaveBeenCalledTimes(1)
240+
})
278241
})
279242
})
280243

0 commit comments

Comments
 (0)