Test File Upload

This article describes how to interact with file upload forms in TestCafe tests.

Note

View the complete code example on GitHub.

What makes file inputs different

File upload interactions require a different testing approach.

Consider a page with the following markup:

<body>
    <form action="http://localhost:3000/upload" method="post" enctype="multipart/form-data">
        <input id="upload-input" type="file" name="files" multiple />
        <input type="submit" id="upload-btn" value="Upload Files"/>
    </form>
</body>

The <form> element in the example has two descendants:

  • An <input> element that holds the selected files.
  • A submit button that initiates the file upload.

End users perform the following page actions to upload a file:

  1. Click the ‘Choose File’ button to open the native file selection dialog.
  2. Select a file in the dialog window.
  3. Submit the form.

The file selection dialog is a part of the user’s operating system. TestCafe cannot interact with the operating system’s UI. Therefore, if you want to upload files during your test, you must use a different strategy.

Upload Files with TestCafe

Do not click <input type="file"> elements to upload files during tests. Use the dedicated setFilesToUpload action instead. This action directly changes the state of the <input type="file"> element.

Example

Use the setFilesToUpload method to populate the <input> element with files. Then, click the submit button.

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `./index.html`

test('Check uploaded files', async t => {

    await t
        .setFilesToUpload('#upload-input', [
            './uploads/text-file-1.txt',
            './uploads/text-file-2.txt'
        ])
        .click('#upload-btn');
});

Empty the file input

Use the clearUpload action to empty the <input>:

    await t.clearUpload('#upload-input');

Observe input state

To observe the state of the input element, examine its value with a Selector query.

await t.setFilesToUpload(uploadInput, file);
console.log(await uploadInput.value) // 'C:\fakepath\text-file.txt'
await t.clearUpload(uploadInput);
console.log(await uploadInput.value) // ''

or

const uploadInput= Selector('#upload').addCustomDOMProperties({
    filesLength: el => el.files.length
});

await t.setFilesToUpload(uploadInput, file);
console.log(await uploadInput.filesLength) // 1
await t.clearUpload(uploader);
console.log(await uploadInput.filesLength) // 0