Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cypress - check if the file is downloaded

I have a little problem with trying to check if a file is downloaded.

Button click generates a PDF file and starts its download.

I need to check if it works.

Can Cypress do this?

like image 982
Dominik Skála Avatar asked Mar 03 '20 14:03

Dominik Skála


People also ask

How do you check if a file is downloaded or not in Cypress?

To verify that the file has been downloaded we can install simple Cypress command, which will set up downloads directory, will wait and will verify that the file is downloaded.

How to verify that file is downloaded with cypress?

In this article I’ll show how you can verify that file is downloaded with Cypress. First, imagine situation that you have a functionality where user clicks on the Download button, and file is starting to download to your computer. So, you have to test download functionality and you’re using cypress as a tool for testing.

How to read large file in Cypress?

We can’t read large file. However, we don’t need it. To verify that the file has been downloaded we can install simple Cypress command, which will set up downloads directory, will wait and will verify that the file is downloaded. Oh, wait, just one command?

What is Cy-verify-downloads and how to use it?

This is a Cypress custom command to wait and to verify that a file has been successfully downloaded. cy-verify-downloads extends Cypress' cy command. So, you need to add this line to your project's cypress/support/commands.js:

How do I read a file with null in Cypress?

Using null explicitly will return the file as a Cypress.Buffer instance, regardless of file extension. Pass in an options object to change the default behavior of cy.readFile (). cy.readFile () yields the contents of the file. For any file other than JSON, the contents of the file are returned.


2 Answers

cypress/plugins/index.js

    const path = require('path');
    const fs = require('fs');
    
    const downloadDirectory = path.join(__dirname, '..', 'downloads');
    
    const findPDF = (PDFfilename) => {
      const PDFFileName = `${downloadDirectory}/${PDFfilename}`;
      const contents = fs.existsSync(PDFFileName);
      return contents;
    };
    
    const hasPDF = (PDFfilename, ms) => {
      const delay = 10;
      return new Promise((resolve, reject) => {
        if (ms < 0) {
          return reject(
            new Error(`Could not find PDF ${downloadDirectory}/${PDFfilename}`)
          );
        }
        const found = findPDF(PDFfilename);
        if (found) {
          return resolve(true);
        }
        setTimeout(() => {
          hasPDF(PDFfilename, ms - delay).then(resolve, reject);
        }, delay);
      });
    };
    
    module.exports = (on, config) => {
      require('@cypress/code-coverage/task')(on, config);
      on('before:browser:launch', (browser, options) => {
        if (browser.family === 'chromium') {
          options.preferences.default['download'] = {
            default_directory: downloadDirectory,
          };
          return options;
        }
        if (browser.family === 'firefox') {
          options.preferences['browser.download.dir'] = downloadDirectory;
          options.preferences['browser.download.folderList'] = 2;
          options.preferences['browser.helperApps.neverAsk.saveToDisk'] =
            'text/csv';
          return options;
        }
      });
    
      on('task', {
        isExistPDF(PDFfilename, ms = 4000) {
          console.log(
            `looking for PDF file in ${downloadDirectory}`,
            PDFfilename,
            ms
          );
          return hasPDF(PDFfilename, ms);
        },
      });
    
      return config;
    };

integration/pdfExport.spec.js

    before('Clear downloads folder', () => {
       cy.exec('rm cypress/downloads/*', { log: true, failOnNonZeroExit: false });
    });
        
    it('Should download my PDF file and verify its present', () => {
        cy.get('ExportPdfButton').click();
        cy.task('isExistPDF', 'MyPDF.pdf').should('equal', true);
    });
like image 101
abdp Avatar answered Oct 31 '22 01:10

abdp


I would suggest you to have a look to the HTTP response body. You can get the response with cy.server().route('GET', 'url').as('download') (check cypress documentation if you don't know these methods).

and catch the response to verify the body is not empty:

cy.wait('@download')
    .then((xhr) => {
        assert.isNotNull(xhr.response.body, 'Body not empty')
    })

Or if you have a popup announcing success when the download went successfully, you can as well verify the existence of the popup:

cy.get('...').find('.my-pop-up-success').should('be.visible')

Best,

EDIT

Please note cy.server().route() may be deprecated:

cy.server() and cy.route() are deprecated in Cypress 6.0.0. In a future release, support for cy.server() and cy.route() will be removed. Consider using cy.intercept() instead.

According to the migration guide, this is the equivalent: cy.intercept('GET', 'url').as('download')

like image 31
François Avatar answered Oct 31 '22 02:10

François