diff --git a/bin/helpers/reporterHTML.js b/bin/helpers/reporterHTML.js index b71c1e07..db18b4df 100644 --- a/bin/helpers/reporterHTML.js +++ b/bin/helpers/reporterHTML.js @@ -4,7 +4,8 @@ const fs = require('fs'), logger = require('./logger').winstonLogger, utils = require("./utils"), Constants = require('./constants'), - config = require("./config"); + config = require("./config"), + axios = require("axios"); let templatesDir = path.join(__dirname, '../', 'templates'); @@ -100,7 +101,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => { }, }; - return request.get(options, function (err, resp, body) { + return request.get(options, async function (err, resp, body) { let message = null; let messageType = null; let errorCode = null; @@ -163,7 +164,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => { } else { messageType = Constants.messageTypes.SUCCESS; message = `Report for build: ${buildId} was successfully created.`; - renderReportHTML(build); + await renderReportHTML(build); logger.info(message); } utils.sendUsageReport(bsConfig, args, message, messageType, errorCode); @@ -173,7 +174,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => { }); } -function renderReportHTML(report_data) { +async function renderReportHTML(report_data) { let resultsDir = 'results'; let metaCharSet = ``; let metaViewPort = ` `; @@ -194,12 +195,17 @@ function renderReportHTML(report_data) { } // Writing the JSON used in creating the HTML file. - fs.writeFileSync(`${resultsDir}/browserstack-cypress-report.json`, JSON.stringify(report_data), () => { - if(err) { - return logger.error(err); + let reportData = await cypressReportData(report_data); + fs.writeFileSync( + `${resultsDir}/browserstack-cypress-report.json`, + JSON.stringify(reportData), + () => { + if (err) { + return logger.error(err); + } + logger.info("The JSON file is saved"); } - logger.info("The JSON file is saved"); - }); + ); // Writing the HTML file generated from the JSON data. fs.writeFileSync(`${resultsDir}/browserstack-cypress-report.html`, html, () => { @@ -210,4 +216,100 @@ function renderReportHTML(report_data) { }); } +async function cypressReportData(report_data) { + specFiles = Object.keys(report_data.rows); + combinationPromises = []; + for (let spec of specFiles) { + let specSessions = report_data.rows[spec]["sessions"]; + if (specSessions.length > 0) { + for (let combination of specSessions) { + if(utils.isUndefined(report_data.cypress_version) || report_data.cypress_version < "6"){ + combinationPromises.push(generateCypressCombinationSpecReportDataWithoutConfigJson(combination)); + }else{ + combinationPromises.push(generateCypressCombinationSpecReportDataWithConfigJson(combination)); + } + } + } + } + await Promise.all(combinationPromises); + return report_data; +} + +function generateCypressCombinationSpecReportDataWithConfigJson(combination){ + return new Promise(async (resolve, reject) => { + try { + let configJsonError, resultsJsonError; + let [configJsonResponse, resultsJsonResponse] = await axios.all([ + axios.get(combination.tests.config_json).catch(function (error) { + configJsonError = true; + }), + axios.get(combination.tests.result_json).catch(function(error){ + resultsJsonError = true; + }) + ]); + if(resultsJsonError || configJsonError){ + resolve(); + } + let tests = {}; + let configJson = configJsonResponse.data; + let resultsJson = resultsJsonResponse.data; + if(utils.isUndefined(configJson.tests) || utils.isUndefined(resultsJson.tests)){ + resolve(); + } + configJson.tests.forEach((test) => { + tests[test["clientId"]] = test; + }); + resultsJson.tests.forEach((test) => { + tests[test["clientId"]] = Object.assign( + tests[test["clientId"]], + test + ); + }); + let sessionTests = []; + Object.keys(tests).forEach((testId) => { + sessionTests.push({ + name: tests[testId]["title"].pop(), + status: tests[testId]["state"], + duration: parseFloat( + tests[testId]["attempts"].pop()["wallClockDuration"] / 1000 + ).toFixed(2), + }); + }); + combination.tests = sessionTests; + resolve(combination.tests); + } catch (error) { reject(error) } + }) +} + +function generateCypressCombinationSpecReportDataWithoutConfigJson(combination){ + return new Promise(async (resolve, reject) => { + try { + let resultsJsonError; + let resultsJsonResponse = await axios.get(combination.tests.result_json).catch(function(error){ + resultsJsonError = true; + }); + if(resultsJsonError || utils.isUndefined(resultsJsonResponse)){ + resolve(); + } + let resultsJson = resultsJsonResponse.data; + let sessionTests = []; + if(utils.isUndefined(resultsJson.tests)){ + resolve(); + } + resultsJson.tests.forEach((test) => { + durationKey = utils.isUndefined(test["attempts"]) ? test : test["attempts"].pop() + sessionTests.push({ + name: test["title"].pop(), + status: test["state"], + duration: parseFloat( + durationKey["wallClockDuration"] / 1000 + ).toFixed(2) + }) + }); + combination.tests = sessionTests; + resolve(combination.tests); + } catch (error) { reject(error) } + }) +} + exports.reportGenerator = reportGenerator; diff --git a/package.json b/package.json index aed0c50a..025f6c79 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "table": "^5.4.6", "uuid": "^8.3.2", "winston": "^2.3.1", - "yargs": "^14.2.3" + "yargs": "^14.2.3", + "axios": "^0.21.1" }, "repository": { "type": "git", diff --git a/test/unit/bin/helpers/reporterHTML.js b/test/unit/bin/helpers/reporterHTML.js index fbf95495..9f68b151 100644 --- a/test/unit/bin/helpers/reporterHTML.js +++ b/test/unit/bin/helpers/reporterHTML.js @@ -1,6 +1,9 @@ +const { expect } = require("chai"); const chai = require("chai"), chaiAsPromised = require("chai-as-promised"), - sinon = require('sinon'); + sinon = require('sinon'), + rewire = require('rewire'), + axios = require('axios'); const fs = require('fs'), path = require('path'), @@ -266,7 +269,128 @@ describe("reportHTML", () => { sinon.assert.calledOnce(requestStub); sinon.assert.calledOnce(getUserAgentStub); - sinon.assert.calledOnceWithExactly(sendUsageReportStub, bsConfig, args, message, messageType, errorCode); + sendUsageReportStub.calledOnceWithExactly(bsConfig, args, message, messageType, errorCode); + }); + }); + + describe("Modify Cypress Report Data", ()=> { + const reporterHTML = rewire('../../../../bin/helpers/reporterHTML'); + const cypressReportData = reporterHTML.__get__('cypressReportData'); + const cypress_report_data_with_config = { + cypress_version: "6.8.0", + rows: { + "todo.spec.js": { + "sessions": [ + { + "tests": { + "config_json": "config_json", + "result_json": "result_json", + } + } + ] + } + } + } + const cypress_report_data_without_config = { + cypress_version: "5.6.0", + rows: { + "todo.spec.js": { + "sessions": [ + { + "tests": { + "config_json": "config_json", + "result_json": "result_json", + } + } + ] + } + } + } + it("Generate Report Data for cypress version > 6", async ()=>{ + let configResponse = { data: { + tests: [ + { + clientId: "r3", + title:[ + "file_name", + "test_case" + ] + } + ] + } } + let resultsResponse = { data: { + tests: [ + { + clientId: "r3", + state: "passed", + attempts:[ + { + "state": "passed", + "wallClockDuration": 62 + } + ] + } + ] + } } + let expectedResponse = { + cypress_version: "6.8.0", + rows:{ + "todo.spec.js": { + "sessions":[{ + "tests":[{ + "name":"test_case", + "status":"passed", + "duration":"0.06"}] + }] + } + } + } + let axiosGetStub = sandbox.stub(axios, "get") + let axiosConfigStub = axiosGetStub.withArgs("config_json").resolves(configResponse); + let axiosResultStub = axiosGetStub.withArgs("result_json").resolves(resultsResponse); + let result = await cypressReportData(cypress_report_data_with_config); + sinon.assert.calledOnce(axiosConfigStub); + sinon.assert.calledOnce(axiosResultStub); + expect(JSON.stringify(result)).to.be.equal(JSON.stringify(expectedResponse)); + }); + + it("Generate Report Data for cypress version < 6", async ()=>{ + let resultsResponse = { data: { + tests: [ + { + clientId: "r3", + state: "passed", + title:[ + "file_name", + "test_case" + ], + attempts:[ + { + "state": "passed", + "wallClockDuration": 62 + } + ] + } + ] + } } + let expectedResponse = { + cypress_version: "5.6.0", + rows:{ + "todo.spec.js": { + "sessions":[{ + "tests":[{ + "name":"test_case", + "status":"passed", + "duration":"0.06"}] + }] + } + } + } + let axiosGetStub = sandbox.stub(axios, "get") + let axiosResultStub = axiosGetStub.withArgs("result_json").resolves(resultsResponse); + let result = await cypressReportData(cypress_report_data_without_config); + sinon.assert.calledOnce(axiosResultStub); + expect(JSON.stringify(result)).to.be.equal(JSON.stringify(expectedResponse)); }); }); });