DEV Community

prakash chokalingam
prakash chokalingam

Posted on

13 2

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

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (1)

Collapse
 
rustemyuzlibaev profile image
Rustem

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

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay