Uploading Files Directly Through the API with Cypress

Reaching a higher level of automated API testing

File uploads are a hit and miss with Cypress. There are no built-in commands that handle file uploads and you typically need to get creative with jquery events or install a node package such as cypress-file-upload to try and get your files uploaded through the frontend. In this post, I’ll be demonstrating how I’ve tackled this and what I use to test endpoints with file uploads.

Blobs

Multipart/Form-Data.

Solution

  • Param-1: The file to upload, which is found and read from the fixtures folder
  • Param-2: A uniqueName (this is just used as an example, your endpoint might need other keys and values appended)
  • Param-3: An alias name that we can call back later in the test once this request has fired off
  • The hasHeader option is set to true as I needed to inform the endpoint that I’ve set headers on this request
  • Leveraging cy.server and cy.route to inform Cypress of the request that is about to be sent where the alias name is a reference to this request
  • Using cy.fixture to read the file with a specific encoding type, in this case I’ve used binary
  • Once read and resolved, the object that is now in binary is converted to a Blob using .binaryStringToBlob
  • Once resolved, the blob is passed down to the XMLHttpRequest
  • Using the formdata.set method, I’ve specified the key (user-file), value (blob) and name of the file (fileToUpload)
  • Using the XMLHttpRequest .open method to open a channel of communication to the specified endpoint, here I’ve specified the type of request (“POST”) and the endpoint (“/fileToUpload”) — You don’t need to specify the full path as this is abstracted from the baseURL similar to cy.request
  • Using the XMLHttpRequest .setRequestHeader method, I’ve set the auth token that I’ve got stored as a request header
  • Finally, the XMLHttpRequest .send method is used to (as you’ve guessed) send the request

Usage

Cypress Test Runner Log

As we’ve given this request an alias, we can use all of Cypress` alias functionality to run assertions on the contents of that alias as well as wait for it, which might be useful if you’re uploading a large file. Here’s how this could look:

Cypress Test Runner Log
API response for the specified alias

Conclusion

Cy.route and server have been deprecated as of the latest Cypress versions, which doesn’t mean you cannot use this approach, but you just need to be mindful of the Cypress version you are running and whether you are planning to upgrade in the near-future. Alternatively, adjust the custom command code to use Cy.intercept !

Thanks for reading!

Software Developer in Test