diff --git a/src/utility/upload.ts b/src/utility/upload.ts index 72abedbd..84efc930 100644 --- a/src/utility/upload.ts +++ b/src/utility/upload.ts @@ -1,4 +1,10 @@ -import {createFileList, isDisabled, isElementType, setFiles} from '../utils' +import { + createFileList, + getWindow, + isDisabled, + isElementType, + setFiles, +} from '../utils' import {Config, Instance} from '../setup' export interface uploadInit { @@ -36,7 +42,7 @@ export async function upload( return } - setFiles(input, createFileList(files)) + setFiles(input, createFileList(getWindow(element), files)) this.dispatchUIEvent(input, 'input') this.dispatchUIEvent(input, 'change') } diff --git a/src/utils/dataTransfer/DataTransfer.ts b/src/utils/dataTransfer/DataTransfer.ts index fe622a12..fb13967a 100644 --- a/src/utils/dataTransfer/DataTransfer.ts +++ b/src/utils/dataTransfer/DataTransfer.ts @@ -74,63 +74,65 @@ function getTypeMatcher(type: string, exact: boolean) { } } -class DataTransferStub implements DataTransfer { - getData(format: string) { - const match = - this.items.find(getTypeMatcher(format, true)) ?? - this.items.find(getTypeMatcher(format, false)) - - let text = '' - match?.getAsString(t => { - text = t - }) - - return text - } - - setData(format: string, data: string) { - const matchIndex = this.items.findIndex(getTypeMatcher(format, true)) - - const item = new DataTransferItemStub(data, format) as DataTransferItem - if (matchIndex >= 0) { - this.items.splice(matchIndex, 1, item) - } else { - this.items.push(item) +function createDataTransferStub(window: Window & typeof globalThis) { + return new (class DataTransferStub implements DataTransfer { + getData(format: string) { + const match = + this.items.find(getTypeMatcher(format, true)) ?? + this.items.find(getTypeMatcher(format, false)) + + let text = '' + match?.getAsString(t => { + text = t + }) + + return text } - } - clearData(format?: string) { - if (format) { + setData(format: string, data: string) { const matchIndex = this.items.findIndex(getTypeMatcher(format, true)) + const item = new DataTransferItemStub(data, format) as DataTransferItem if (matchIndex >= 0) { - this.items.remove(matchIndex) + this.items.splice(matchIndex, 1, item) + } else { + this.items.push(item) } - } else { - this.items.clear() } - } - - dropEffect: DataTransfer['dropEffect'] = 'none' - effectAllowed: DataTransfer['effectAllowed'] = 'uninitialized' - readonly items = new DataTransferItemListStub() - readonly files = createFileList([]) + clearData(format?: string) { + if (format) { + const matchIndex = this.items.findIndex(getTypeMatcher(format, true)) - get types() { - const t = [] - if (this.files.length) { - t.push('Files') + if (matchIndex >= 0) { + this.items.remove(matchIndex) + } + } else { + this.items.clear() + } } - this.items.forEach(i => t.push(i.type)) - Object.freeze(t) + dropEffect: DataTransfer['dropEffect'] = 'none' + effectAllowed: DataTransfer['effectAllowed'] = 'uninitialized' - return t - } + readonly items = new DataTransferItemListStub() + readonly files = createFileList(window, []) - /* istanbul ignore next */ - setDragImage() {} + get types() { + const t = [] + if (this.files.length) { + t.push('Files') + } + this.items.forEach(i => t.push(i.type)) + + Object.freeze(t) + + return t + } + + /* istanbul ignore next */ + setDragImage() {} + })() } export function createDataTransfer( @@ -140,10 +142,10 @@ export function createDataTransfer( // Use real DataTransfer if available const dt = typeof window.DataTransfer === 'undefined' - ? (new DataTransferStub() as DataTransfer) + ? createDataTransferStub(window) : /* istanbul ignore next */ new window.DataTransfer() - Object.defineProperty(dt, 'files', {get: () => createFileList(files)}) + Object.defineProperty(dt, 'files', {get: () => createFileList(window, files)}) return dt } diff --git a/src/utils/dataTransfer/FileList.ts b/src/utils/dataTransfer/FileList.ts index 1de62055..ed5e3b5e 100644 --- a/src/utils/dataTransfer/FileList.ts +++ b/src/utils/dataTransfer/FileList.ts @@ -1,6 +1,9 @@ // FileList can not be created per constructor. -export function createFileList(files: File[]): FileList { +export function createFileList( + window: Window & typeof globalThis, + files: File[], +): FileList { const list: FileList & Iterable = { ...files, length: files.length, @@ -11,8 +14,8 @@ export function createFileList(files: File[]): FileList { } }, } - list.constructor = FileList - Object.setPrototypeOf(list, FileList.prototype) + list.constructor = window.FileList + Object.setPrototypeOf(list, window.FileList.prototype) Object.freeze(list) return list diff --git a/tests/utils/dataTransfer/FileList.ts b/tests/utils/dataTransfer/FileList.ts index e6ac8826..49d2f67a 100644 --- a/tests/utils/dataTransfer/FileList.ts +++ b/tests/utils/dataTransfer/FileList.ts @@ -2,7 +2,7 @@ import {createFileList} from '#src/utils' test('implement FileList', () => { const file = new File(['hello'], 'hello.png', {type: 'image/png'}) - const list = createFileList([file]) + const list = createFileList(window, [file]) expect(list).toBeInstanceOf(FileList) expect(list).toHaveLength(1) diff --git a/tests/utils/edit/setFiles.ts b/tests/utils/edit/setFiles.ts index 8168f18e..17c20a10 100644 --- a/tests/utils/edit/setFiles.ts +++ b/tests/utils/edit/setFiles.ts @@ -6,7 +6,7 @@ test('set files', () => { ``, ) - const list = createFileList([new File(['foo'], 'foo.txt')]) + const list = createFileList(window, [new File(['foo'], 'foo.txt')]) setFiles(element, list) expect(element).toHaveProperty('files', list) @@ -20,7 +20,7 @@ test('switching type resets value', () => { expect(element).toHaveValue('') - const list = createFileList([new File(['foo'], 'foo.txt')]) + const list = createFileList(window, [new File(['foo'], 'foo.txt')]) setFiles(element as HTMLInputElement & {type: 'file'}, list) element.type = 'file' @@ -38,7 +38,7 @@ test('setting value resets `files`', () => { ``, ) - const list = createFileList([new File(['foo'], 'foo.txt')]) + const list = createFileList(window, [new File(['foo'], 'foo.txt')]) setFiles(element, list) // Everything but an empty string throws an error in the browser @@ -58,7 +58,7 @@ test('is save to call multiple times', () => { ``, ) - const list = createFileList([new File(['foo'], 'foo.txt')]) + const list = createFileList(window, [new File(['foo'], 'foo.txt')]) setFiles(element, list) setFiles(element, list)