DEV Community

prakash chokalingam
prakash chokalingam

Posted on

Codebytes: How to mock upload files in the test cases

Mocking file uploads with file input elements is not straight forward as mocking other HTML elements while writing test cases. Why and how do we do that?



<input type="file" id="file-upload" onchange="doSomething" />


Enter fullscreen mode Exit fullscreen mode

The file input elements have FileList object as its value. The FileList is nothing but a collection of File objects. The FileList object is read-only and we cannot construct custom FileList since it has no implementation of its constructor.

However, there is a way to construct them using the DataTransfer object.

DataTransfer object is responsible for holding the file objects in FileList during files drag & drop. We are gonna bypass the DataTransfer event's file addition methods to construct a FileList with our mocked files.

Let's create one,



const dt = () => new DataTransfer() || new ClipboardEvent('').clipboardData;


Enter fullscreen mode Exit fullscreen mode

If the browser didn't support constructing a new DataTransfer, let's get the DataTransfer object from the ClipboardEvent (mock's file copy-paste) alternatively.

let's create a blob to construct a file object.



let fileString = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HgAGgwJ/lK3Q6wAAAABJRU5ErkJggg==';

(or)

let fileString = 'https://some-image-url.png';

let blob = await fetch(fileString).then(res => {
  return res.blob();
});


Enter fullscreen mode Exit fullscreen mode

And now file object,



let file = new File([blob], "sample.jpg", { type: 'image/png'})


Enter fullscreen mode Exit fullscreen mode

will add the file object to the DataTransfer,



let dt = dt();
dt.items.add(file);


Enter fullscreen mode Exit fullscreen mode

and it's time to add the FileList to the file input element



let $fileElement = document.getElementById('file-upload');
$fileElement.files = dt.files;


Enter fullscreen mode Exit fullscreen mode

🎉 Yay! The files have been added to the file element and now let's emit the change event so that your UI can respond to the file upload.



let changeEvent = new Event('change');
$fileElement.dispatchEvent(changeEvent);


Enter fullscreen mode Exit fullscreen mode

To ease this, I have created a test helper util to fill files to the file input element.



await fillInFIle('#file-upload') ✅


Enter fullscreen mode Exit fullscreen mode

Check the GitHub repo for more details on the util:

GitHub logo prakashchokalingam / fill-in-file

A test util that helps to fill files in your file input element

Top comments (1)

Collapse
 
rustemyuzlibaev profile image
Rustem

DataTransfer object is not defined in Jest (jsdom). So, how to use it in this case?