JavaScript testing #12. Testing downloaded files and file inputs with Cypress

Testing

This entry is part 12 of 18 in the JavaScript testing tutorial

Our applications sometimes have features that allow users to choose files from their machine. Also, we might allow the users to download various files. Testing that with Cypress might not seem straightforward at first.

In this article, we build a simple React application that allows the users to choose a JSON file from the hard drive. Our application downloads a formatted version of the provided JSON when the users provide a valid file. Then, we use Cypress to test the file input and check whether the downloaded file is correct.

Creating a React application that deals with files

First, let’s make a component that contains a file input.

JsonFormatter.tsx

Thanks to creating the above component, we end up with the following user interface:

We contain the crucial part of the logic in the hook.

useJsonFormatter.tsx

The above function:

  • extracts the text from the chosen file,
  • parses the text as json,
  • formats it using two spaces,
  • sends the formatted file to the user.

If the users choose a valid JSON file, they receive a formatted version with the same filename.

If the users choose an invalid JSON file, they see an error message.

Providing a file through Cypress

To create a Cypress test that interacts with file input, let’s install the library.

Installing the cypress-file-upload library

To use the above library properly, we need to add it to our file:

tsconfig.json

We also need to import it through the file.

cypress/support/commands.tsx

Creating the necessary files

We expect the user to choose a file from the hard drive in our application. To simulate that, we need to put the files in the directory. Let’s start by creating two files – one invalid and one valid.

cypress/fixtures/invalid-data.txt

Above, we use the .txt extension to avoid Cypress complaining about our JSON file not being valid.

cypress/fixtures/data.json

Writing tests that interact with the file input

Thanks to doing all of the above, we can now write our first tests.

cypress/integration/JsonFormatter.test.tsx

We use above, because we’ve put the URL of our application into the property. If you want to know more, check out JavaScript testing #6. Introduction to End-to-End testing with Cypress

Thanks to using the library, we can use the function in our tests and provide the name of a file we’ve put into the fixtures directory.

Running the above tests results in success.

Testing if a file was downloaded

When Cypress runs our tests and downloads files, it saves them in the directory. To check this downloaded file, we can use Node.js. First, we need to define a task through the file.

To check if a file exists, we can use the function provided by Node.js. It throws an error if a file does not exist.

If you want to know more about how Node.js and the File system module work, check out Node.js TypeScript #1. Modules, process arguments, basics of the File System

Since the function uses callbacks, we can utilize to use promises instead.

cypress/plugins/index.ts

Thanks to registering a task in the above file, we can now use it in our tests. To access the path of the downloads directory, we can use .

cypress/integration/JsonFormatter.test.tsx

Verifying the contents of a file

Let’s create an additional task to verify the contents of a file. To do that, we can use .

cypress/plugins/index.ts

Above, we first get a buffer containing the data. Then, since we want to verify its content, we use the function to receive a string.

If you want to know more about buffers, check out Node.js TypeScript #3. Explaining the Buffer

Once we have the above task ready, we can use it in our tests.

cypress/integration/JsonFormatter.test.tsx

When we run all of the above tests, we see that they pass.

Summary

In this article, we’ve gone through the idea of combining Cypress with Node.js to deal with files. While doing so, we’ve learned how to simulate choosing a file from the hard drive. We’ve also verified the files saved in the downloads directory to ensure they exist and contain the correct data. The above might come in handy when working with various use-cases involving files.

Series Navigation<< JavaScript testing #11. Spying on functions. Pitfalls of not resetting Jest mocksJavaScript testing #13. Mocking a REST API with the Mock Service Worker >>
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Martin del Necesario
Martin del Necesario
2 years ago

Thank you for this great article, I learned about useful functions that where new to me!

How would you go about to handle downloaded files with dynamic file names. I need to get the last downloaded file (a solution to get the only file in the download fodler is also applicable). I didn’t find a solution to get the name of the file while downloading, to change the filename or to intercept the traffic (the file is downloaded without any requests that can be intercepted).
Thank you!