File upload testing made easy.
This package adds a custom Cypress command that allows you to make an abstraction on how exactly you upload files through HTML controls and focus on testing user workflows.
The package is distributed via npm and should be installed as one of your project's devDependencies
:
npm install --save-dev cypress-file-upload
cypress-file-upload
extends Cypress' cy
command.
Add this line to your project's cypress/support/commands.js
or cypress/support/commands.ts
file:
import 'cypress-file-upload';
Note: With Typescript, ensure the following is in your cypress\tsconfig.json
file:
"compilerOptions": {
"types": ["cypress", "cypress-file-upload"]
Now you are ready to actually test uploading. Here are some basic examples:
/* Plain HTML input */
const yourFixturePath = 'data.json'; // the file to be uploaded, from the cypress/fixtures/ directory
cy.get('[data-cy="file-input"]').attachFile(yourFixturePath);
/* Drag-n-drop component */
cy.get('[data-cy="dropzone"]').attachFile(yourFixturePath, { subjectType: 'drag-n-drop' });
/* You can also attach multiple files by chaining the command */
const yourBestPicture = 'meow.png';
cy.get('[data-cy="file-input"]')
.attachFile(yourFixturePath)
.attachFile(yourBestPicture);
/* If your file encoding is not supported out of the box, make sure to pass it explicitly */
const weirdo = 'test.shp';
cy.get('[data-cy="file-input"]').attachFile({ filePath: weirdo, encoding: 'utf-8' });
/* If your input element is invisible or stays within shadow DOM, make sure enforcing manual event triggering */
cy.get('[data-cy="file-input"]').attachFile(yourFixturePath, { force: true });
/* If you want to overwrite the file name */
const data = 'test.json';
cy.get('[data-cy="file-input"]').attachFile({ filePath: data, fileName: 'users.json' });
/* If your file needs special processing not supported out of the box, you can pass fileContent directly */
const special = 'file.spss';
cy.fixture(special, 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then((fileContent) => {
cy.get('[data-cy="file-input"]').attachFile({ fileContent, filePath: special, encoding: 'utf-8' });
})
/* when providing fileContent is possible to ignore filePath but fileName and mime type must be provided */
const special = 'file.spss';
cy.fixture(special, 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then((fileContent) => {
cy.get('[data-cy="file-input"]').attachFile({ fileContent, fileName: 'special', mimeType: 'application/octet-stream', encoding: 'utf-8' });
})
Trying to upload a file that does not supported by Cypress by default? Make sure you pass encoding
property (see API).
See more usage guidelines in recipes.
Exposed command in a nutshell:
cySubject.attachFile(fixture, processingOpts);
fixture
is a string path (or object with same purpose) that represents your local fixture file and contains following properties:
- {String}
filePath
– file path (with extension) - {String}
fileName
- (optional) the name of the file to be attached, this allows to override the name provided byfilePath
- {Blob}
fileContent
- (optional) the binary content of the file to be attached - {String}
mimeType
– (optional) file MIME type. By default, it gets resolved automatically based on file extension. Learn more about mime - {String}
encoding
– (optional) normallycy.fixture
resolves encoding automatically, but in case it cannot be determined you can provide it manually. For a list of allowed encodings, see here
processingOpts
(optional) contains following properties:
- {String}
subjectType
– target (aka subject) element kind:'drag-n-drop'
component or plain HTML'input'
element. Defaults to'input'
- {Boolean}
force
– (optional) same as forcy.trigger
it enforces events triggering on HTML subject element. Usually this is necessary when you use hidden HTML controls for your file upload. Defaults tofalse
- {Boolean}
allowEmpty
- (optional) when true, do not throw an error iffileContent
is zero length. Defaults tofalse
Most common frontend UI setups along with Cypress & file upload testing are located at recipes.
Any contributions are welcome!
During the lifetime plugin faced some issues you might need to be aware of:
- Chrome 73 changes related to HTML file input behavior: #34
- Force event triggering (same as for
cy.trigger
) should happen when you use hidden HTML controls: #41 - Binary fixture has a workarounded encoding: #70
- Video fixture has a workarounded encoding: #136
- Shadow DOM compatibility: #74
- Reading file content after upload: #104
Here is step-by-step guide:
- Check Caveats – maybe there is a tricky thing about exactly your setup
- Submit the issue and let us know about you problem
- In case you're using a file with encoding and/or extension that is not yet supported by Cypress, make sure you've tried to explicitly set the
encoding
property (see API) - Comment your issue describing what happened after you've set the
encoding
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!