Skip to content

Commit 98c67e2

Browse files
author
Kent C. Dodds
authored
feat(events): allow setting the files value in change events (#91)
Similar to the value, this works around limitations with DOM properties that make testing certain use cases harder. This simplifies those cases
1 parent dfe9401 commit 98c67e2

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,15 @@ This is particularly useful for a change event:
525525

526526
```javascript
527527
fireEvent.change(getByLabelText(/username/i), {target: {value: 'a'}})
528+
529+
// note: attempting to manually set the files property of an HTMLInputElement
530+
// results in an error as the files property is read-only.
531+
// this feature works around that by using Object.defineProperty.
532+
fireEvent.change(getByLabelText(/picture/i), {
533+
target: {
534+
files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
535+
},
536+
})
528537
```
529538

530539
#### `getNodeText`

src/__tests__/events.js

+9
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,12 @@ test('assigning a value to a target that cannot have a value throws an error', (
168168
`"The given element does not have a value setter"`,
169169
)
170170
})
171+
172+
test('assigning the files property on an input', () => {
173+
const node = document.createElement('input')
174+
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
175+
type: 'image/png',
176+
})
177+
fireEvent.change(node, {target: {files: [file]}})
178+
expect(node.files).toEqual([file])
179+
})

src/events.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ const {
1313
TransitionEvent,
1414
UIEvent,
1515
WheelEvent,
16-
} =
17-
typeof window === 'undefined' ? /* istanbul ignore next */ global : window
16+
} = typeof window === 'undefined' ? /* istanbul ignore next */ global : window
1817

1918
const eventMap = {
2019
// Clipboard Events
@@ -322,11 +321,19 @@ Object.entries(eventMap).forEach(([key, {EventType = Event, defaultInit}]) => {
322321

323322
fireEvent[key] = (node, init) => {
324323
const eventInit = {...defaultInit, ...init}
325-
const {target: {value, ...targetProperties} = {}} = eventInit
324+
const {target: {value, files, ...targetProperties} = {}} = eventInit
326325
Object.assign(node, targetProperties)
327326
if (value !== undefined) {
328327
setNativeValue(node, value)
329328
}
329+
if (files !== undefined) {
330+
// input.files is a read-only property so this is not allowed:
331+
// input.files = [file]
332+
// so we have to use this workaround to set the property
333+
Object.defineProperty(node, 'files', {
334+
value: files,
335+
})
336+
}
330337
const event = new EventType(eventName, eventInit)
331338
return fireEvent(node, event)
332339
}

0 commit comments

Comments
 (0)