diff --git a/src/__tests__/upload.js b/src/__tests__/upload.js
index f09a6ae2..fb6a2b7d 100644
--- a/src/__tests__/upload.js
+++ b/src/__tests__/upload.js
@@ -163,3 +163,55 @@ test('should call onChange/input bubbling up the event when a file is selected',
expect(onInputInput).toHaveBeenCalledTimes(1)
expect(onInputForm).toHaveBeenCalledTimes(1)
})
+
+test('should upload file with accepted format', () => {
+ const file = new File(['hello'], 'hello.png', {type: 'image/png'})
+ const {element} = setup('')
+
+ userEvent.upload(element, file)
+
+ expect(element.files).toHaveLength(1)
+})
+
+test('should upload multiple files with accepted format', () => {
+ const files = [
+ new File(['hello'], 'hello.png', {type: 'image/png'}),
+ new File(['there'], 'there.jpg', {type: 'audio/mp3'}),
+ new File(['there'], 'there.csv', {type: 'text/csv'}),
+ new File(['there'], 'there.jpg', {type: 'video/mp4'}),
+ ]
+ const {element} = setup(`
+
+ `)
+
+ userEvent.upload(element, files)
+
+ expect(element.files).toHaveLength(3)
+})
+
+test('should not upload file with unaccepted format', () => {
+ const file = new File(['hello'], 'hello.png', {type: 'image/png'})
+ const {element} = setup('')
+
+ userEvent.upload(element, file)
+
+ expect(element.files).toHaveLength(0)
+})
+
+test('should not upload multiple files with unaccepted formats', () => {
+ const files = [
+ new File(['hello'], 'hello.txt', {type: 'text/plain'}),
+ new File(['there'], 'there.pdf', {type: 'application/pdf'}),
+ new File(['there'], 'there.png', {type: 'image/png'}),
+ ]
+ const {element} = setup(`
+
+ `)
+
+ userEvent.upload(element, files)
+
+ expect(element.files).toHaveLength(0)
+})
diff --git a/src/upload.js b/src/upload.js
index a252b438..7a3b990a 100644
--- a/src/upload.js
+++ b/src/upload.js
@@ -10,16 +10,20 @@ function upload(element, fileOrFiles, init) {
const input = element.tagName === 'LABEL' ? element.control : element
- const files = (Array.isArray(fileOrFiles)
- ? fileOrFiles
- : [fileOrFiles]
- ).slice(0, input.multiple ? undefined : 1)
+ const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles])
+ .filter(file => isAcceptableFile(file, element.accept))
+ .slice(0, input.multiple ? undefined : 1)
// blur fires when the file selector pops up
blur(element, init)
// focus fires when they make their selection
focus(element, init)
+ // treat empty array as if the user just closed the file upload dialog
+ if (files.length === 0) {
+ return
+ }
+
// the event fired in the browser isn't actually an "input" or "change" event
// but a new Event with a type set to "input" and "change"
// Kinda odd...
@@ -46,4 +50,22 @@ function upload(element, fileOrFiles, init) {
})
}
+function isAcceptableFile(file, accept) {
+ if (!accept) {
+ return true
+ }
+
+ const wildcards = ['audio/*', 'image/*', 'video/*']
+
+ return accept.split(',').some(acceptToken => {
+ if (acceptToken[0] === '.') {
+ // tokens starting with a dot represent a file extension
+ return file.name.endsWith(acceptToken)
+ } else if (wildcards.includes(acceptToken)) {
+ return file.type.startsWith(acceptToken.substr(0, acceptToken.length - 1))
+ }
+ return file.type === acceptToken
+ })
+}
+
export {upload}