How To Use Cypress To Download File With Dynamic Name
From time to time I get an idea to automate a test with the following scenario. The user clicks on a button and starts a file download. The user should check the file content or verify if the download was successful. Nothing specific about this automation task and many of us have been in the same position. Any automation framework has support for file downloads. For example, Cypress has this nice command called readFile where you pass the path of the file as an argument. Selenium does not provide a method for making such asserts out of the box. However, there are other ways to do it like using File class in Java or FileInfo class in C#. But what if the file name contains time stamp which changes all the time?
Dynamic naming of downloaded files
It is not uncommon that downloaded files would have time stamp appended to the file name. In this way the developers ensure easier search for the file in the folder. Also it is useful to prevent dozens of file copies with a number of file copy appended to the file name something like “C:\Desktop\fakeFile(25).txt”. This is not the best strategy for user experience, but it is not uncommon either. However, it is as equally painful as having a time stamp in the file name, at least from the test automation perspective. Let’s face it, this cannot happen in Cypress because by default the files are downloaded in Cypress Downloads folder which is emptied before each test run. In this case we wouldn’t have to worry about appending the version of the file to the file name.
Time stamp in file name – problem decomposition
In every automation framework or tool we might be using for test automation we can expect that for checking the downloaded file we would need to pass the correct path to the file as an argument. If we don’t know the time indicated in the file name, we cannot locate the file. There are two things we can do. We can find the exact time of the click and add it as a time stamp to the file name when the download starts. Second is to make sure that the time stamp is known to us before the click. The first option is error prone and it may lead to inconsistent behavior. Second option is interesting but quite challenging to achieve it. Luckily for Cypress users, they have a command to set the time and date programmatically during test execution. Let’s see how to use Cypress to download a file and check if it was downloaded.
Stopping the time
Honestly, the time will not stop literally but it may seem like that to the test. Cypress offers clock command which can be used to set time and date during the test run. To do it correctly, this is what you need to do:
const year = date.year();
const month = date.month();
const day = date.date();
const hour = date.hour();
//first you set the time and date to the value you need
cy.clock(new Date(year, month, day, hour, 0, 0));
//next you click on the export button
cy.get(.exportButton).click();
//then you use cy.readFile to assert if the file was downloaded
cy.readFile(`C:\Downloads\fakeFile_${day.toString()}_${month.toString()} ${year.toString()}_${hour.toString()}_0000.xlsx`, 'binary');
//cy.read() is a query command and assertions do not have to be directly attached as of v13
//In the end you restore the clock to current time
cy.clock().then((clock) => {
clock.restore()
})
When passing arguments in Date class constructor you should pay attention to the format of the inputs.
In the above example I populated year, month, day and hour constants by grabbing the current values for each of the variables, but you can set a fixed values in the test. Remember that hardcoding the values in the script is not suggested because of test maintenance. If you have any comments or questions about using Cypress to download a file please let us know in the comment section.