Skip to content

Commit 5c9f475

Browse files
authored
Merge pull request #295 from browserstack/CYP-1100-cli-changes-record-flag
Add code to output custom error messages on CLI from backend
2 parents b9f6455 + 1aae0d2 commit 5c9f475

File tree

6 files changed

+140
-14
lines changed

6 files changed

+140
-14
lines changed

bin/helpers/constants.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ const REDACTED_AUTH =`auth: { "username": ${REDACTED}, "access_key": ${REDACTED}
245245

246246
const SPEC_TIMEOUT_LIMIT = 120 // IN MINS
247247

248+
const CYPRESS_CUSTOM_ERRORS_TO_PRINT_KEY = "custom_errors_to_print";
249+
248250
module.exports = Object.freeze({
249251
syncCLI,
250252
userMessages,
@@ -269,5 +271,6 @@ module.exports = Object.freeze({
269271
REDACTED_AUTH,
270272
REDACTED,
271273
BUILD_FAILED_EXIT_CODE,
272-
SPEC_TIMEOUT_LIMIT
274+
SPEC_TIMEOUT_LIMIT,
275+
CYPRESS_CUSTOM_ERRORS_TO_PRINT_KEY
273276
});

bin/helpers/sync/specsSummary.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const logger = require("../logger").syncCliLogger;
2+
const winstonlogger = require("../logger").winstonLogger;
23

34
/**
45
*
@@ -16,7 +17,7 @@ const logger = require("../logger").syncCliLogger;
1617
// {specName: 'spec8.alias.js', status: 'Skipped', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'}
1718
// ]
1819
//
19-
let printSpecsRunSummary = (data, machines) => {
20+
let printSpecsRunSummary = (data, machines, customErrorsToPrint) => {
2021
return new Promise((resolve, _reject) => {
2122
let summary = {
2223
total: 0,
@@ -32,6 +33,21 @@ let printSpecsRunSummary = (data, machines) => {
3233
logger.info(`Total tests: ${summary.total}, passed: ${summary.passed}, failed: ${summary.failed}, skipped: ${summary.skipped}`);
3334
logger.info(`Done in ${data.duration/1000} seconds using ${machines} machines\n`);
3435

36+
if (customErrorsToPrint && customErrorsToPrint.length > 0) {
37+
for (const error of customErrorsToPrint) {
38+
switch(error.level) {
39+
case 'info':
40+
winstonlogger.info(error.message);
41+
break;
42+
case 'error':
43+
winstonlogger.error(error.message);
44+
break;
45+
default:
46+
winstonlogger.warn(error.message);
47+
}
48+
}
49+
}
50+
3551
resolve(data.exitCode);
3652
})
3753
};

bin/helpers/sync/syncSpecsLogs.js

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ let whileLoop = true, whileTries = config.retries, options, timeout = 3000, n =
1313
let specSummary = {
1414
"buildError": null,
1515
"specs": [],
16-
"duration": null
16+
"duration": null,
17+
"customErrorsToPrint": []
1718
}
19+
1820
let noWrap = false;
1921
let terminalWidth = (process.stdout.columns) * 0.9;
2022
let lineSeparator = Constants.syncCLI.DEFAULT_LINE_SEP;
@@ -166,18 +168,22 @@ let getStackTraceUrl = () => {
166168
let showSpecsStatus = (data) => {
167169
let specData = JSON.parse(data);
168170
specData.forEach(specDetails => {
169-
if (specDetails == "created") {
170-
return;
171-
} else if (specDetails["stacktrace_url"]) {
172-
specSummary.exitCode = Constants.BUILD_FAILED_EXIT_CODE;
173-
specSummary.buildError = specDetails["stacktrace_url"]
174-
winstonLogger.error(chalk.red(specDetails["message"]));
171+
if (specDetails.type === Constants.CYPRESS_CUSTOM_ERRORS_TO_PRINT_KEY) {
172+
addCustomErrorToPrint(specDetails);
175173
} else {
176-
if(!buildStarted) {
177-
buildStarted = true
178-
printInitialLog();
174+
if (specDetails == "created") {
175+
return;
176+
} else if (specDetails["stacktrace_url"]) {
177+
specSummary.exitCode = Constants.BUILD_FAILED_EXIT_CODE;
178+
specSummary.buildError = specDetails["stacktrace_url"]
179+
winstonLogger.error(chalk.red(specDetails["message"]));
180+
} else {
181+
if(!buildStarted) {
182+
buildStarted = true
183+
printInitialLog();
184+
}
185+
printSpecData(JSON.parse(specDetails));
179186
}
180-
printSpecData(JSON.parse(specDetails));
181187
}
182188
});
183189
}
@@ -200,6 +206,17 @@ let writeToTable = (combination, specName, status) => {
200206
stream.write([combination , ":", `${specName} ${status}`]);
201207
}
202208

209+
let addCustomErrorToPrint = (error_object) => {
210+
if (error_object["should_be_unique"]) {
211+
for (const error of specSummary.customErrorsToPrint) {
212+
if (error.id === error_object.id) {
213+
return;
214+
}
215+
}
216+
}
217+
specSummary.customErrorsToPrint.push(error_object);
218+
}
219+
203220
let addSpecToSummary = (specName, status, combination, session_id) => {
204221
// Format for part 3: {specName: 'spec1.failed.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
205222
specSummary["specs"].push({

bin/helpers/syncRunner.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ const syncSpecsLogs = require('./sync/syncSpecsLogs'),
44
specsSummary = require('./sync/specsSummary');
55

66
exports.pollBuildStatus = (bsConfig, buildDetails) => {
7+
let customErrorsToPrint;
78
return new Promise((resolve, reject) => {
89
syncSpecsLogs.printSpecsStatus(bsConfig, buildDetails).then((data) => {
10+
if(data.customErrorsToPrint && data.customErrorsToPrint.length > 0) {
11+
customErrorsToPrint = data.customErrorsToPrint;
12+
}
913
return specDetails.failedSpecsDetails(data);
1014
}).then((data) => {
11-
return specsSummary.printSpecsRunSummary(data, buildDetails.machines);
15+
return specsSummary.printSpecsRunSummary(data, buildDetails.machines, customErrorsToPrint);
1216
}).then((successExitCode) => {
1317
resolve(successExitCode); // exit code 0
1418
}).catch((nonZeroExitCode) => {

test/unit/bin/helpers/sync/specSummary.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const chai = require("chai"),
66

77
chai.use(chaiAsPromised);
88
var logger = require("../../../../../bin/helpers/logger").syncCliLogger;
9+
var winstonLogger = require("../../../../../bin/helpers/logger").winstonLogger;
910
var specSummary = require('../../../../../bin/helpers/sync/specsSummary');
1011

1112
describe("printSpecsRunSummary", () => {
@@ -52,4 +53,36 @@ describe("printSpecsRunSummary", () => {
5253
loggerInfoSpy.restore();
5354
});
5455
});
56+
57+
context("with custom error data", () => {
58+
let time = 6000,
59+
machines = 2,
60+
specs = [
61+
{specName: 'spec2.name.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
62+
{specName: 'spec2.name.js', status: 'Skipped', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
63+
{specName: 'spec2.name.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
64+
{specName: 'spec2.name.js', status: 'Passed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'}
65+
],
66+
data = {
67+
specs: specs,
68+
duration: time,
69+
exitCode: 0
70+
},
71+
customErrorsToPrint = [
72+
{ id: "custom_error", type: "custom_errors_to_print", level: "warn", should_be_unique: true, message: "custom error message" }
73+
];
74+
75+
it('prints the custom error message along with build details', () => {
76+
var loggerInfoSpy = sinon.spy(logger, 'info');
77+
var loggerWarnSpy = sinon.spy(winstonLogger, 'warn');
78+
79+
specSummary.printSpecsRunSummary(data, machines, customErrorsToPrint);
80+
sinon.assert.calledWith(loggerInfoSpy, 'Total tests: 4, passed: 1, failed: 2, skipped: 1');
81+
sinon.assert.calledWith(loggerInfoSpy, `Done in ${time / 1000} seconds using ${machines} machines\n`);
82+
sinon.assert.calledWith(loggerWarnSpy, `custom error message`);
83+
84+
loggerInfoSpy.restore();
85+
loggerWarnSpy.restore();
86+
});
87+
});
5588
});

test/unit/bin/helpers/sync/syncSpecsLogs.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,42 @@ describe("syncSpecsLogs", () => {
8787
});
8888
});
8989

90+
context("addCustomErrorToPrint", () => {
91+
const addCustomErrorToPrint = syncSpecsLogs.__get__("addCustomErrorToPrint");
92+
let specSummary = {
93+
"buildError": null,
94+
"specs": [],
95+
"duration": null,
96+
"customErrorsToPrint": [
97+
{ id: "custom_error_1", type: "custom_errors_to_print", level: "warn", should_be_unique: true, message: "custom error message" }
98+
]
99+
}
100+
const uniqueError = { id: "custom_error_1", type: "custom_errors_to_print", level: "warn", should_be_unique: true, message: "custom error message" };
101+
const notUniqueError = { id: "custom_error_2", type: "custom_errors_to_print", level: "warn", should_be_unique: false, message: "custom error message" };
102+
103+
it('should add a new Error if its meant to be unique and not added to the error list', () => {
104+
addCustomErrorToPrint(uniqueError);
105+
expect(JSON.stringify(syncSpecsLogs.__get__("specSummary"))).to.equal(JSON.stringify(specSummary));
106+
});
107+
108+
it('should not add a new Error if its meant to be unique and already added to the error list', () => {
109+
addCustomErrorToPrint(uniqueError);
110+
expect(JSON.stringify(syncSpecsLogs.__get__("specSummary"))).to.equal(JSON.stringify(specSummary));
111+
});
112+
113+
it('should add a new Error if its not meant to be unique and not added to the error list', () => {
114+
addCustomErrorToPrint(notUniqueError);
115+
specSummary.customErrorsToPrint.push(notUniqueError);
116+
expect(JSON.stringify(syncSpecsLogs.__get__("specSummary"))).to.equal(JSON.stringify(specSummary));
117+
});
118+
119+
it('should not add a new Error if its not meant to not be unique and already added to the error list', () => {
120+
addCustomErrorToPrint(notUniqueError);
121+
specSummary.customErrorsToPrint.push(notUniqueError);
122+
expect(JSON.stringify(syncSpecsLogs.__get__("specSummary"))).to.equal(JSON.stringify(specSummary));
123+
});
124+
});
125+
90126
context("getTableConfig", () => {
91127
const getTableConfig = syncSpecsLogs.__get__("getTableConfig");
92128

@@ -212,6 +248,23 @@ describe("syncSpecsLogs", () => {
212248
expect(printSpecData.calledOnce).to.be.true;
213249
expect(printInitialLog.calledOnce).to.be.true;
214250
});
251+
252+
it('should add custom error, print initial and spec details when spec related data is sent in polling response', () => {
253+
let specResult = JSON.stringify({"path": "path"})
254+
let customError = { id: "custom_error_1", type: "custom_errors_to_print", level: "warn", should_be_unique: true, message: "custom error message" }
255+
syncSpecsLogs.__set__('buildStarted', false)
256+
let data = JSON.stringify(["created", specResult, customError])
257+
var printSpecData = sandbox.stub();
258+
syncSpecsLogs.__set__('printSpecData', printSpecData);
259+
var printInitialLog = sandbox.stub();
260+
syncSpecsLogs.__set__('printInitialLog', printInitialLog);
261+
var addCustomErrorToPrint = sandbox.stub();
262+
syncSpecsLogs.__set__('addCustomErrorToPrint', addCustomErrorToPrint);
263+
showSpecsStatus(data);
264+
expect(printSpecData.calledOnce).to.be.true;
265+
expect(printInitialLog.calledOnce).to.be.true;
266+
expect(addCustomErrorToPrint.calledOnce).to.be.true;
267+
});
215268
});
216269

217270
context("printSpecsStatus", () => {

0 commit comments

Comments
 (0)