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:
- Click the ‘Choose File’ button to open the native file selection dialog.
- Select a file in the dialog window.
- 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