Skip to content

Commit

Permalink
perf(upload): handle higher range of mime types
Browse files Browse the repository at this point in the history
  • Loading branch information
LauraBeatris committed Feb 18, 2021
1 parent 831e922 commit a7c715a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
42 changes: 33 additions & 9 deletions src/__tests__/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,31 +164,55 @@ test('should call onChange/input bubbling up the event when a file is selected',
expect(onInputForm).toHaveBeenCalledTimes(1)
})

test('should not upload file with invalid unaccepted format', () => {
test('should upload file with accepted format', () => {
const file = new File(['hello'], 'hello.png', {type: 'image/png'})
const {element} = setup('<input type="file" accept="image/png" />')

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(`
<input
type="file"
accept="image/*,audio/*,text/csv" multiple
/>
`)

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('<input type="file" accept="image/jpg" />')

userEvent.upload(element, file)

expect(element.files[0]).toBeUndefined()
expect(element.files.item(0)).toBeNull()
expect(element.files).toHaveLength(0)
})

test('should not upload multiple files with invalid unaccepted formats', () => {
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'}),
new File(['there'], 'there.mp4', {type: 'video/mp4'}),
]

const {element} = setup(`
<input id="files" type="file" accept="image/jpeg,image/png" multiple />
<input id="files" type="file" accept="video/*" multiple />
`)

userEvent.upload(element, files)

expect(element.files[0]).toBeUndefined()
expect(element.files.item(0)).toBeNull()
expect(element.files).toHaveLength(0)
expect(element.files).toHaveLength(1)
})
18 changes: 15 additions & 3 deletions src/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ import {click} from './click'
import {blur} from './blur'
import {focus} from './focus'

const isValidFileType = (acceptAttribute, type) => {
const acceptManyExtensions = /(video|audio|image)\/?\*/.test(acceptAttribute)

if (!acceptManyExtensions) {
return acceptAttribute.includes(type)
}

const fileMimeType = type.match(/\w+\/+/g)
const isValidMimeType = acceptAttribute.includes(fileMimeType)

return isValidMimeType
}

function upload(element, fileOrFiles, init) {
const hasFileWithInvalidType =
!Array.isArray(fileOrFiles) &&
Boolean(element.accept) &&
!element.accept.includes(fileOrFiles.type)
!isValidFileType(element.accept, fileOrFiles.type)

if (hasFileWithInvalidType || element.disabled) return

Expand All @@ -19,14 +32,13 @@ function upload(element, fileOrFiles, init) {

if (Array.isArray(fileOrFiles)) {
files = element.accept
? fileOrFiles.filter(file => element.accept.includes(file.type))
? fileOrFiles.filter(file => isValidFileType(element.accept, file.type))
: fileOrFiles
} else {
files = [fileOrFiles]
}

const hasFilesWithInvalidTypes = files.length === 0

if (hasFilesWithInvalidTypes) return

files = files.slice(0, input.multiple ? undefined : 1)
Expand Down

0 comments on commit a7c715a

Please sign in to comment.