Mochawesome with Cypress - how to get aggregated charts at higher level?

Viewed 135

I've just started using mochawesome with Cypress (9.7). Our test structure is basically a number of spec files, each following something like the following format:

describe('(A): description of this spec', () => {
  describe ('(B): description of test abc', () => {
    before(() => {
      // do specific set up bits for this test
    })
    it('(C): runs test abc', () => {
      // do actual test stuff
    })
  })
})

Where within each spec file there would be a single 'A' describe block, but there can be many 'B' level blocks (each with a single 'C') - done this way because the before block for each 'C' is always different - I couldn't use a beforeEach.

When I run my various spec files, each structured similarly to the above, the mochaewsome output is mostly correct - I get a collapsible block for each spec file at level 'A', each with multiple collapsible blocks at level B, each with test info as expected at level C.

But... The circular charts are only displayed at level B. What I was hoping, was that it might be possible to have aggregated charts at level A, and a further aggregated chart for all the level A blocks.

Not sure I've explained this brilliantly(!), but hopefully someone understands, and can offer a suggestion?!

1 Answers

In cypress-mochawesome-reporter there's an alternative setup using on('after:run') which can perform the aggregation.

In Cypress v9.7.0

// cypress/plugins/index.js

const { beforeRunHook, afterRunHook } = require('cypress-mochawesome-reporter/lib');
const { aggregateResults } = require('./aggregate-mochawesome-report-chart');

module.exports = (on, config) => {
  on('before:run', async (details) => {
    await beforeRunHook(details);
  });

  on('after:run', async () => {
    aggregateResults(config)
    await afterRunHook();
  });
};

In Cypress v10+

// cypress.config.js

const { defineConfig } = require('cypress');
const { beforeRunHook, afterRunHook } = require('cypress-mochawesome-reporter/lib');
const { aggregateResults } = require('./aggregate-mochawesome-report-chart');

module.exports = defineConfig({
  reporter: 'cypress-mochawesome-reporter',
  video: false,
  retries: 1,
  reporterOptions: {
    reportDir: 'test-report',
    charts: true,
    reportPageTitle: 'custom-title',
    embeddedScreenshots: true,
    inlineAssets: false,
    saveAllAttempts: false,
    saveJson: true
  },
  e2e: {
    setupNodeEvents(on, config) {
      on('before:run', async (details) => {
        await beforeRunHook(details);
      });

      on('after:run', async () => {
        aggregateResults(config)
        await afterRunHook();
      });
    },
  },
});

The module to do the aggregation is

// aggregate-mochawesome-reporter-chart.js

const path = require('path');
const fs = require('fs-extra')

function aggregateResults(config) {
  const jsonPath = path.join(config.reporterOptions.reportDir , '/.jsons', '\mochawesome.json');
  const report = fs.readJsonSync(jsonPath)
  const topSuite = report.results[0].suites[0]
  aggregate(topSuite)
  fs.writeJsonSync(jsonPath, report)
}
function aggregate(suite, level = 0) {
  const childSuites = suite.suites.map(child => aggregate(child, ++level))
  suite.passes = suite.passes.concat(childSuites.map(child => child.passes)).flat()
  suite.failures = suite.failures.concat(childSuites.map(child => child.failures)).flat()
  suite.pending = suite.pending.concat(childSuites.map(child => child.pending)).flat()
  suite.skipped = suite.skipped.concat(childSuites.map(child => child.skipped)).flat()
  if (!suite.tests.length && suite.suites[0].tests.length) {
    // trigger chart when to describe has no tests
    suite.tests = [               
      {
        "title": "Aggregate of tests",
        "duration": 20,
        "pass": true,
        "context": null,
        "err": {},
        "uuid": "0",
        "parentUUID": suite.uuid,
      },
    ]
  }
  return suite
}

module.exports = {
  aggregateResults
}

The function aggregate() recursively loops down through child suites and adds the test results to the parent.

json files

Note the json file is different at the point where afterRunHook runs and at the end of the test run.

If you have the option saveJson: true set, you will get a final json file in the report directory called index.json.

At the afterRunHook stage the file is mochawesome.json.

Before aggregation

After aggregation

Related