Skip to content

Commit eaee597

Browse files
Merge pull request #152 from browserstack/improved_json_reporting
Improved JSON Reporting
2 parents 19083f5 + 04f4ad4 commit eaee597

File tree

3 files changed

+239
-12
lines changed

3 files changed

+239
-12
lines changed

bin/helpers/reporterHTML.js

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ const fs = require('fs'),
44
logger = require('./logger').winstonLogger,
55
utils = require("./utils"),
66
Constants = require('./constants'),
7-
config = require("./config");
7+
config = require("./config"),
8+
axios = require("axios");
89

910
let templatesDir = path.join(__dirname, '../', 'templates');
1011

@@ -100,7 +101,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => {
100101
},
101102
};
102103

103-
return request.get(options, function (err, resp, body) {
104+
return request.get(options, async function (err, resp, body) {
104105
let message = null;
105106
let messageType = null;
106107
let errorCode = null;
@@ -163,7 +164,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => {
163164
} else {
164165
messageType = Constants.messageTypes.SUCCESS;
165166
message = `Report for build: ${buildId} was successfully created.`;
166-
renderReportHTML(build);
167+
await renderReportHTML(build);
167168
logger.info(message);
168169
}
169170
utils.sendUsageReport(bsConfig, args, message, messageType, errorCode);
@@ -173,7 +174,7 @@ let reportGenerator = (bsConfig, buildId, args, cb) => {
173174
});
174175
}
175176

176-
function renderReportHTML(report_data) {
177+
async function renderReportHTML(report_data) {
177178
let resultsDir = 'results';
178179
let metaCharSet = `<meta charset="utf-8">`;
179180
let metaViewPort = `<meta name="viewport" content="width=device-width, initial-scale=1"> `;
@@ -194,12 +195,17 @@ function renderReportHTML(report_data) {
194195
}
195196

196197
// Writing the JSON used in creating the HTML file.
197-
fs.writeFileSync(`${resultsDir}/browserstack-cypress-report.json`, JSON.stringify(report_data), () => {
198-
if(err) {
199-
return logger.error(err);
198+
let reportData = await cypressReportData(report_data);
199+
fs.writeFileSync(
200+
`${resultsDir}/browserstack-cypress-report.json`,
201+
JSON.stringify(reportData),
202+
() => {
203+
if (err) {
204+
return logger.error(err);
205+
}
206+
logger.info("The JSON file is saved");
200207
}
201-
logger.info("The JSON file is saved");
202-
});
208+
);
203209

204210
// Writing the HTML file generated from the JSON data.
205211
fs.writeFileSync(`${resultsDir}/browserstack-cypress-report.html`, html, () => {
@@ -210,4 +216,100 @@ function renderReportHTML(report_data) {
210216
});
211217
}
212218

219+
async function cypressReportData(report_data) {
220+
specFiles = Object.keys(report_data.rows);
221+
combinationPromises = [];
222+
for (let spec of specFiles) {
223+
let specSessions = report_data.rows[spec]["sessions"];
224+
if (specSessions.length > 0) {
225+
for (let combination of specSessions) {
226+
if(utils.isUndefined(report_data.cypress_version) || report_data.cypress_version < "6"){
227+
combinationPromises.push(generateCypressCombinationSpecReportDataWithoutConfigJson(combination));
228+
}else{
229+
combinationPromises.push(generateCypressCombinationSpecReportDataWithConfigJson(combination));
230+
}
231+
}
232+
}
233+
}
234+
await Promise.all(combinationPromises);
235+
return report_data;
236+
}
237+
238+
function generateCypressCombinationSpecReportDataWithConfigJson(combination){
239+
return new Promise(async (resolve, reject) => {
240+
try {
241+
let configJsonError, resultsJsonError;
242+
let [configJsonResponse, resultsJsonResponse] = await axios.all([
243+
axios.get(combination.tests.config_json).catch(function (error) {
244+
configJsonError = true;
245+
}),
246+
axios.get(combination.tests.result_json).catch(function(error){
247+
resultsJsonError = true;
248+
})
249+
]);
250+
if(resultsJsonError || configJsonError){
251+
resolve();
252+
}
253+
let tests = {};
254+
let configJson = configJsonResponse.data;
255+
let resultsJson = resultsJsonResponse.data;
256+
if(utils.isUndefined(configJson.tests) || utils.isUndefined(resultsJson.tests)){
257+
resolve();
258+
}
259+
configJson.tests.forEach((test) => {
260+
tests[test["clientId"]] = test;
261+
});
262+
resultsJson.tests.forEach((test) => {
263+
tests[test["clientId"]] = Object.assign(
264+
tests[test["clientId"]],
265+
test
266+
);
267+
});
268+
let sessionTests = [];
269+
Object.keys(tests).forEach((testId) => {
270+
sessionTests.push({
271+
name: tests[testId]["title"].pop(),
272+
status: tests[testId]["state"],
273+
duration: parseFloat(
274+
tests[testId]["attempts"].pop()["wallClockDuration"] / 1000
275+
).toFixed(2),
276+
});
277+
});
278+
combination.tests = sessionTests;
279+
resolve(combination.tests);
280+
} catch (error) { reject(error) }
281+
})
282+
}
283+
284+
function generateCypressCombinationSpecReportDataWithoutConfigJson(combination){
285+
return new Promise(async (resolve, reject) => {
286+
try {
287+
let resultsJsonError;
288+
let resultsJsonResponse = await axios.get(combination.tests.result_json).catch(function(error){
289+
resultsJsonError = true;
290+
});
291+
if(resultsJsonError || utils.isUndefined(resultsJsonResponse)){
292+
resolve();
293+
}
294+
let resultsJson = resultsJsonResponse.data;
295+
let sessionTests = [];
296+
if(utils.isUndefined(resultsJson.tests)){
297+
resolve();
298+
}
299+
resultsJson.tests.forEach((test) => {
300+
durationKey = utils.isUndefined(test["attempts"]) ? test : test["attempts"].pop()
301+
sessionTests.push({
302+
name: test["title"].pop(),
303+
status: test["state"],
304+
duration: parseFloat(
305+
durationKey["wallClockDuration"] / 1000
306+
).toFixed(2)
307+
})
308+
});
309+
combination.tests = sessionTests;
310+
resolve(combination.tests);
311+
} catch (error) { reject(error) }
312+
})
313+
}
314+
213315
exports.reportGenerator = reportGenerator;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"table": "^5.4.6",
2626
"uuid": "^8.3.2",
2727
"winston": "^2.3.1",
28-
"yargs": "^14.2.3"
28+
"yargs": "^14.2.3",
29+
"axios": "^0.21.1"
2930
},
3031
"repository": {
3132
"type": "git",

test/unit/bin/helpers/reporterHTML.js

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
const { expect } = require("chai");
12
const chai = require("chai"),
23
chaiAsPromised = require("chai-as-promised"),
3-
sinon = require('sinon');
4+
sinon = require('sinon'),
5+
rewire = require('rewire'),
6+
axios = require('axios');
47

58
const fs = require('fs'),
69
path = require('path'),
@@ -266,7 +269,128 @@ describe("reportHTML", () => {
266269

267270
sinon.assert.calledOnce(requestStub);
268271
sinon.assert.calledOnce(getUserAgentStub);
269-
sinon.assert.calledOnceWithExactly(sendUsageReportStub, bsConfig, args, message, messageType, errorCode);
272+
sendUsageReportStub.calledOnceWithExactly(bsConfig, args, message, messageType, errorCode);
273+
});
274+
});
275+
276+
describe("Modify Cypress Report Data", ()=> {
277+
const reporterHTML = rewire('../../../../bin/helpers/reporterHTML');
278+
const cypressReportData = reporterHTML.__get__('cypressReportData');
279+
const cypress_report_data_with_config = {
280+
cypress_version: "6.8.0",
281+
rows: {
282+
"todo.spec.js": {
283+
"sessions": [
284+
{
285+
"tests": {
286+
"config_json": "config_json",
287+
"result_json": "result_json",
288+
}
289+
}
290+
]
291+
}
292+
}
293+
}
294+
const cypress_report_data_without_config = {
295+
cypress_version: "5.6.0",
296+
rows: {
297+
"todo.spec.js": {
298+
"sessions": [
299+
{
300+
"tests": {
301+
"config_json": "config_json",
302+
"result_json": "result_json",
303+
}
304+
}
305+
]
306+
}
307+
}
308+
}
309+
it("Generate Report Data for cypress version > 6", async ()=>{
310+
let configResponse = { data: {
311+
tests: [
312+
{
313+
clientId: "r3",
314+
title:[
315+
"file_name",
316+
"test_case"
317+
]
318+
}
319+
]
320+
} }
321+
let resultsResponse = { data: {
322+
tests: [
323+
{
324+
clientId: "r3",
325+
state: "passed",
326+
attempts:[
327+
{
328+
"state": "passed",
329+
"wallClockDuration": 62
330+
}
331+
]
332+
}
333+
]
334+
} }
335+
let expectedResponse = {
336+
cypress_version: "6.8.0",
337+
rows:{
338+
"todo.spec.js": {
339+
"sessions":[{
340+
"tests":[{
341+
"name":"test_case",
342+
"status":"passed",
343+
"duration":"0.06"}]
344+
}]
345+
}
346+
}
347+
}
348+
let axiosGetStub = sandbox.stub(axios, "get")
349+
let axiosConfigStub = axiosGetStub.withArgs("config_json").resolves(configResponse);
350+
let axiosResultStub = axiosGetStub.withArgs("result_json").resolves(resultsResponse);
351+
let result = await cypressReportData(cypress_report_data_with_config);
352+
sinon.assert.calledOnce(axiosConfigStub);
353+
sinon.assert.calledOnce(axiosResultStub);
354+
expect(JSON.stringify(result)).to.be.equal(JSON.stringify(expectedResponse));
355+
});
356+
357+
it("Generate Report Data for cypress version < 6", async ()=>{
358+
let resultsResponse = { data: {
359+
tests: [
360+
{
361+
clientId: "r3",
362+
state: "passed",
363+
title:[
364+
"file_name",
365+
"test_case"
366+
],
367+
attempts:[
368+
{
369+
"state": "passed",
370+
"wallClockDuration": 62
371+
}
372+
]
373+
}
374+
]
375+
} }
376+
let expectedResponse = {
377+
cypress_version: "5.6.0",
378+
rows:{
379+
"todo.spec.js": {
380+
"sessions":[{
381+
"tests":[{
382+
"name":"test_case",
383+
"status":"passed",
384+
"duration":"0.06"}]
385+
}]
386+
}
387+
}
388+
}
389+
let axiosGetStub = sandbox.stub(axios, "get")
390+
let axiosResultStub = axiosGetStub.withArgs("result_json").resolves(resultsResponse);
391+
let result = await cypressReportData(cypress_report_data_without_config);
392+
sinon.assert.calledOnce(axiosResultStub);
393+
expect(JSON.stringify(result)).to.be.equal(JSON.stringify(expectedResponse));
270394
});
271395
});
272396
});

0 commit comments

Comments
 (0)