DEV Community

Cover image for E2E Testing of excel file downloads with cypress
Vivek Nayyar
Vivek Nayyar

Posted on • Edited on

E2E Testing of excel file downloads with cypress

Recently while working on a project, I had to create a functionality where users can download an excel file consisting of some data.

In this process, since I am a big fan of E2E Testing with Cypress.io, I decided to write a test suite that could make sure that the excel is being downloaded correctly and also consists of the correct data that our users would expect.

This article assumes a basic understanding of cypress.

Disclaimer

If you haven't tried e2e testing with cypress before, I would highly recommend skipping over to the References section and following some of the getting started guides.


📦 Installation

1) Assuming you have a repo named dashboard-ui , create a new folder in it named e2e.

2) cd into that folder and execute the following commands inside it

npm init
npm install cypress --save-dev
Enter fullscreen mode Exit fullscreen mode

3) Update the project’s scripts by opening package.json and updating your scripts to the following:

"scripts": {
   "cy:run": "cypress run --headless -b chrome",
   "cy:open": "cypress open"
}
Enter fullscreen mode Exit fullscreen mode

4) You should also see some default folders and files created by cypress for you after you have installed cypress.

cypress default folders image

5) The test that we will write will go inside integration folder.


⚙️ Functionality

For the sake of simplicity, let's say our application only has one feature where users can click on a download template button, which can download an excel file comprising of some data in it.

ui screenshot showing a download template button

On click of the download template button a file gets downloaded which looks something like this:

downloaded excel file screenshot

Demo

gif to demo excel file download


🧪 E2E Testing

1) Create a new file inside integration folder with the name ExcelDownload.spec.js.

2) Inside this file our test would first start with checking for existence of our button and then we will click on it.

cy.get("[data-test-id=export-template-btn")
  .should("be.visible")
  .click();
Enter fullscreen mode Exit fullscreen mode

3) After clicking on it, the file should ideally have been downloaded and now we need to somehow read that file and check if it exists and also check if it consists of the right data in it.

4) To do that, we will first need to install another npm package which can parse the excel and convert it to a json

npm install node-xlsx --save-dev
Enter fullscreen mode Exit fullscreen mode

5) After this inside your plugins/index.js file we will create a new task

const xlsx = require("node-xlsx").default;
const fs = require("fs");
const path = require("path");

module.exports = (on, config) => {
  // `on` is used to hook into various events Cypress emits
  on("task", {
    parseXlsx({ filePath }) {
      return new Promise((resolve, reject) => {
        try {
          const jsonData = xlsx.parse(fs.readFileSync(filePath));
          resolve(jsonData);
        } catch (e) {
          reject(e);
        }
      });
    }
  });
};
Enter fullscreen mode Exit fullscreen mode

This function will parse our excel file and convert it to json.

6) Finally let’s complete our test for excel file download

// data to check against
const data = [
  "id",
  "config_sku",
  "simple_sku",
  "fallback_type",
  "field",
  "value",
  "command"
];
// check for existence of the button on the ui and then click it
cy.get("[data-test-id=export-template-btn")
    .should("be.visible")
    .click();

// arbitrary wait so that the download can complete
cy.wait(2000);
// call the parseXlsx task we created above to parse the excel and return data as json
cy.parseXlsx("/Users/Downloads/overrides-template.xlsx").then(
  jsonData => {
    // finally we write the assertion rule to check if that data matches the data we expected the excel file to have.
    expect(jsonData[0].data[0]).to.eqls(data);
  }
);
Enter fullscreen mode Exit fullscreen mode

7) With this we can be sure that our excel download functionality is working as expected.

Test Execution

demo of running e2e test in cypress

8) The only caveat here is how do you know the download path for your CI/CD Pipeline or how can you change that path to something else.

The solution to that is built into cypress. Again inside plugins/index.js file we will create another task.

on("before:browser:launch", (browser = {}, launchOptions) => {
  const downloadDirectory = path.join(__dirname, '..', 'excelDownloads')

  if (browser.family === 'chromium') {
   launchOptions.preferences.default['download'] = { default_directory: downloadDirectory }
  }
  return launchOptions;
});
Enter fullscreen mode Exit fullscreen mode

Here we are changing the default directory of download to a directory named excelDownloads inside of cypress folder.

https://docs.cypress.io/api/plugins/browser-launch-api.html#Change-download-directory


💡 Conclusion

In conclusion, E2E tests are really important for every app and you should write one too because this is the closest you can get to test how an actual user will use your application.

And as @tlakomy says:

Sleep better at night with e2e tests and cypress.io

👯 Share this article if you found it helpful!

You can follow me on twitter @VivekNayyar09 for more updates.

Also please don't forget to maintain social distance to prevent the virus from spreading and wash your hands regularly. Stay safe and stay at home.

🚀 References

Top comments (8)

Collapse
 
tuly12 profile image
tuly12

i tried this code buy inside the spec file the parseXlsx wasn't recognized - any idea why?

Collapse
 
adrianflutur profile image
Adrian Flutur

Hi. Same for me. I'm very new to Cypress. Going out an a limb here, but shouldn't parseXLSX also be added to the cypress commands? Also how would you go about testing data on an excel file containing multiple sheets?

Collapse
 
tuly12 profile image
tuly12

another issue,
i finally succeeded to run the code but it fail with the following error :
fs.readFileSync is not a function

i read that it because :
fs will not work in the browser. This is by design as to protect your filesystem from potential security threats.

in case it is true, how the demo show that it is possible?

Thread Thread
 
prabhat66in profile image
Prabhat66in • Edited

you need to add this in command.js file for above code to work
Cypress.Commands.add("parseXlsx", (inputFile) => {
return cy.task('parseXlsx', { filePath: inputFile })
});

Collapse
 
rolkool profile image
rolkool • Edited

Unfortunately, this will not work on headless mode.
Clicking on download button does not have any effect. Neither the file appears on browser footer nor it is saved anywhere.

As a result, such tests have to be skipped when run on CI, unless there is a workaround.

Collapse
 
mythily1426 profile image
Mythily

hi, any luck running these tests in CI? have you gt any solution?

Collapse
 
suprabha_chaudhary_fb8ad0 profile image
Suprabha Chaudhary

This piece of code does not work for me even after adding below in command.js
Cypress.Commands.add("parseXlsx", (inputFile) => {
return cy.task('parseXlsx', { filePath: inputFile })
});

Getting error "cy.parseXlsx is not a function" is not a function
Can someone help . Thanks heaps

Collapse
 
abhimassive profile image
Abhi

Anti-pattern, and very bad practice to arbitrarily wait for cy.wait(2000);
What if its a large file of 20MB or you are on a slow internet connection?
Will you wait for 60 seconds then?