mercredi 5 août 2020

Cypress: verify content of xlsx file generated on frontend in headless mode

We are using npm xlsx to generate xlsx document containing data presented in React view. We want to implement Cypress UI test which verifies that data are exported correctly by downloading generated file, opening it and asserting its content. Test is being executed within our CI pipeline - meaning it runs in headless mode (and using electron browser).

This is how we generate data:

import XLSX from "xlsx";

export function createXlsx(data, sheetName, fileName) {
  const workSheet = XLSX.utils.aoa_to_sheet(data);

  const workBook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workBook, workSheet, sheetName);

  XLSX.writeFile(workBook, fileName);
}

When user clicks "Export" button, data are passed to createXlsx method and user is prompted with save dialog.

For Cypress part, we have followed tutorial*, having following setup in plugins/index.js:

  on('before:browser:launch', (browser = {}, launchOptions) => {
    const downloadDirectory = path.join(process.cwd(), config.env.testDownloadsDirectory);

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

    return launchOptions;
  });

  on('task', {
    parseXlsx({ filePath }) {
      return new Promise((resolve, reject) => {
        try {
          const workBook = xlsx.readFile(filePath);
          const data = xlsx.utils.sheet_to_json(workBook.Sheets.Data);
          resolve(data);
        } catch (e) {
          reject(e);
        }
      });
    }
  });

... and test:

    ...

    cy.get('button[data-cy="export"]').click();

    cy.readFile(filePath, 'binary', { log: true, timeout: 5000 })
      .should('exist');

    cy.task('parseXlsx', { filePath })
      .then(data => {
        // assertions here
      });

    ...

All this works nicely when running locally with --headed --browser chrome - file is saved, then loaded and asserted.

It does not work when executing tests --headless (* this is mentioned in comments below tutorial).

Since I'm relatively new to JavaScript/React, I'm wondering if this could be done somehow. Firstly, I don't really understand how XLSX.writeFile(...) makes browser to open save dialog and if it would be possible to hook into it.

Another idea I had was to create regular React endpoint (having own URI, e.g. /#/xlsx-export) which would generate the file, so I could try to call http.get(...) from registered Cypress task event handler, but since it is still React app, I'm suspecting it won't make any difference. (This approach also prevents me from doing data manipulation before I press export button)

Aucun commentaire:

Enregistrer un commentaire