08.28.2022 - Typescript/Mocking File and FileList in Jest

« All posts

Sometimes we need to mock a FileList, for example, when we need to test file upload features.

First, create a mock File object:

const mockFile = (type: string, size: number): File => {
    const fileName = (Math.random() * 1000).toString().replace(".", "") + type.toLowerCase();
    const file = new File([""], fileName);
    Object.defineProperty(file, 'size', { value: size });
    return file;
};

The above function creates a file with a custom extension and size.

Next, create a FileList so we can add multiple mock files. There’s no straightforward way to mock these objects (a couple of answers on StackOverflow suggest using DataTransfer object, but unfortunately, this object is not supported in Jest), so we have to go for a slightly ugly approach.

const mockFileList = (files: File[]): FileList => {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("name", "file-upload");
    input.multiple = true;
    const fileList: FileList = Object.create(input.files);
    for (let i = 0; i < files.length; i++) {
        fileList[i] = files[i];
    }
    Object.defineProperty(fileList, 'length', { value: files.length });
    return fileList;
};

I know… we have to create an upload input using DOM API, and get the FileList object from there.

Now, we can use it like this:

it('should throw error if there is a file larger than 5MB', () => {
    const fileList = mockFileList([
        mockFile("PDF", 2 * 1024 * 1024), // 2MB
        mockFile("PDF", 6 * 1024 * 1024) // 6MB
    ]);
    component.addFile(fileList);
    ...
})

Read more