Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity.
I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf
and image/*
mime-type files. Doing this with Cypress seems simple enough, but at the time of this article, Cypress does not officially support native file uploads.
I could get into why this process isn’t natively supported, but that’s a topic for another post. Since Cypress has limited functions for this, I had to do some good old Google searching.
I came across this Stack Overflow post.
Let’s go over the solution.
The Solution
I implemented the solution like this:
const uploadFile = (fileName, fileType = '', selector) => { cy.get(selector).then(subject => { cy.fixture(fileName, 'base64') .then(Cypress.Blob.base64StringToBlob) .then(blob => { const el = subject[0] const testFile = new File([blob], fileName, { type: fileType }) const dataTransfer = new DataTransfer() dataTransfer.items.add(testFile) el.files = dataTransfer.files console.log(el.files) }) })
You can also add it as a Cypress command, but I already had a
file. This code will open an image fixture, read the file and translate it to utils.js
base64
. It also utilizes the DataTransfer
API, which is supported natively. No need for external libraries.
Image fixtures must be stored in the
folder. I had an fixtures
folder where I stored test images and PDFs./assets/
This should read the file and give you a FileList
object. To confirm this, run
like in the example above.console.log(el.files)
Forcing UI input change
Some of us need the UI to know that the file has been uploaded. Often times, there is a UI indicator that tells the user the upload was successful. In my case, my JavaScript code relied on the UI state reflecting multiple successful file uploads.
You can force a change event on the file object like this:
// force input event so UI state updates cy.get(selector).trigger('change', { force: true })
Add this under the function to force the UI to reflect an uploaded file.
Using this helper in your tests
This function is mostly standalone, as long as you don’t need any extra info or logic. Here’s an example Cypress test:
import utils from './your-utils-file' const fileName = 'images/fileName.png' const successPrompt = 'Your file has been uploaded!' it('Completes file upload', () => { utils.uploadFile(fileName, 'image/png', '#file-upload') cy.get('#success-message').contains(successPrompt) })
That’s pretty much it! Finding the solution wasn’t easy, and it took me hours of research to find something that worked the way I wanted it to, so I hope this at least gets you part of the way there. Hopefully in the future Cypress will make this whole process easier. For now, this is the most straightforward method I’ve come across.
Posted on
Thanks for the post. What would i put in the file type for an excel file?
Posted on
You can view a list of file types and extensions here. For Excel, it looks like it’s application/vnd.ms-excel
Posted on
Thank you for this. I was trying to use cypress-file-upload, but it was uploading corrupt JPEGs. Your code worked perfectly in Cypress 5.3.0.
Posted on
What about if you were hitting an endpoint? How can you trigger a file upload?
Posted on
Awesome – thanks a lot for this
Posted on
Note that as of 9.3.0 this is natively supported via cy.selectFile
Posted on
Good to know that they fixed this!
More Posts
Let’s Learn SASS & SCSS: Extending your knowledge with @extends and @mixins (Part 4)
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More
(Demo) Converting jQuery Navbar Code to Vanilla JavaScript
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More
Quick Tip: Creating Custom Post Types without A Plugin in WordPress
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More
[Tutorial] Implement Parenthesis Multiplication Using JavaScript & Regex
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More
Getting to Know JS: Destructuring Objects and Arrays
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More
5 Useful Time-Saving Bash Aliases
Cypress is an end-to-end testing framework designed to provide coverage for front-end UIs. Learning how to automate tests has its learning curve, but the benefits grow with your application’s complexity. I was tasked to test a process that involves uploading multiple types of files. In particular, application/pdf and image/* mime-type files. Doing this with Cypress…
Read More