Skip to content

Commit daea598

Browse files
authored
Merge pull request #62 from browserstack/sync-cli-part-4
Sync cli part 4 messaging
2 parents 36111bc + 842f841 commit daea598

File tree

6 files changed

+137
-21
lines changed

6 files changed

+137
-21
lines changed

bin/helpers/constants.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
const syncCLI = {
2+
FAILED_SPEC_DETAILS_COL_HEADER: ['Spec', 'Status', 'Browser', 'BrowserStack Session ID']
3+
};
4+
15
const userMessages = {
26
BUILD_FAILED: "Build creation failed.",
37
BUILD_CREATED: "Build created",
48
BUILD_INFO_FAILED: "Failed to get build info.",
59
BUILD_STOP_FAILED: "Failed to stop build.",
6-
BUILD_REPORT_MESDSAGE: "See the entire build report here:",
10+
BUILD_REPORT_MESSAGE: "See the entire build report here:",
711
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
812
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
913
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
@@ -94,6 +98,7 @@ const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf
9498
const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json']
9599

96100
module.exports = Object.freeze({
101+
syncCLI,
97102
userMessages,
98103
cliMessages,
99104
validationMessages,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
const tablePrinter = require('table'), // { table, getBorderCharacters }
2+
chalk = require('chalk'),
3+
Constants = require("../constants"),
4+
logger = require("../logger").syncCliLogger;
5+
6+
/**
7+
*
8+
* @param {Array.<{specName: string, status: string, combination: string, sessionId: string}>} data
9+
* @returns {Promise.resolve || Promise.reject}
10+
*/
11+
// Example:
12+
// [
13+
// {specName: 'spec1.failed.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
14+
// {specName: 'spec2.name.js', status: 'Skipped', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
15+
// {specName: 'spec3.network.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
16+
// {specName: 'spec6.utils.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'},
17+
// {specName: 'spec8.alias.js', status: 'Skipped', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'}
18+
// ]
19+
//
20+
let failedSpecsDetails = (data) => {
21+
return new Promise((resolve, reject) => {
22+
if (data.length === 0) resolve(0); // return if no failed/skipped tests.
23+
24+
let failedSpecs = false;
25+
let specResultHeader = Constants.syncCLI.FAILED_SPEC_DETAILS_COL_HEADER.map((col) => {
26+
return chalk.blueBright(col);
27+
});
28+
29+
let specData = [specResultHeader]; // 2-D array
30+
31+
data.forEach((spec) => {
32+
if (spec.status && spec.status.toLowerCase() === 'failed' && !failedSpecs)
33+
failedSpecs = true;
34+
35+
let specStatus = (spec.status && spec.status.toLowerCase() === 'failed') ?
36+
chalk.red(spec.status) : chalk.yellow(spec.status);
37+
specData.push([spec.specName, specStatus, spec.combination, spec.sessionId]);
38+
});
39+
40+
let config = {
41+
border: tablePrinter.getBorderCharacters('ramac'),
42+
columns: {
43+
0: { alignment: 'left' },
44+
1: { alignment: 'left' },
45+
2: { alignment: 'left' },
46+
3: { alignment: 'left' },
47+
},
48+
/**
49+
* @typedef {function} drawHorizontalLine
50+
* @param {number} index
51+
* @param {number} size
52+
* @return {boolean}
53+
*/
54+
drawHorizontalLine: (index, size) => {
55+
return (index === 0 || index === 1 || index === size);
56+
}
57+
}
58+
59+
let result = tablePrinter.table(specData, config);
60+
61+
logger.info('Failed / skipped test report');
62+
logger.info(result);
63+
64+
if (failedSpecs) reject(1); // specs failed, send exitCode as 1
65+
resolve(0); // No Specs failed, maybe skipped, but not failed, send exitCode as 0
66+
});
67+
}
68+
69+
exports.failedSpecsDetails = failedSpecsDetails;

bin/helpers/syncRunner.js

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
'use strict';
2-
const config = require("./config"),
2+
const Config = require("./config"),
33
logger = require("./logger").syncCliLogger,
44
Constants = require("./constants"),
55
utils = require("./utils"),
6-
request = require('request');
6+
request = require('request'),
7+
specDetails = require('./sync/failedSpecsDetails'),
8+
{ table, getBorderCharacters } = require('table'),
9+
chalk = require('chalk');
710

811
exports.pollBuildStatus = (bsConfig, buildId) => {
912
logBuildDetails().then((data) => {
1013
printSpecsStatus();
1114
}).then((data) => {
1215
printSpecsRunSummary();
1316
}).then((data) => {
14-
printFailedSpecsDetails();
15-
}).then((data) => {
16-
printBuildDashboardLink(buildId);
17-
}).then((data) => {
18-
// success case!
19-
return 0; // exit code 0
20-
}).catch((err) => {
21-
// failed case!
22-
return 1; // exit code 1
17+
return specDetails.failedSpecsDetails(data);
18+
}).then((successExitCode) => {
19+
return resolveExitCode(successExitCode); // exit code 0
20+
}).catch((nonZeroExitCode) => {
21+
return resolveExitCode(nonZeroExitCode); // exit code 1
22+
}).finally(() => {
23+
logger.info(Constants.userMessages.BUILD_REPORT_MESSAGE);
24+
logger.info(`${Config.dashboardUrl}${buildId}`);
2325
});
2426
};
2527

@@ -35,13 +37,6 @@ let printSpecsRunSummary = () => {
3537

3638
};
3739

38-
let printFailedSpecsDetails = () => {
39-
40-
};
41-
42-
let printBuildDashboardLink = (buildId) => {
43-
new Promise((resolve, reject) => {
44-
logger.info(Constants.userMessages.BUILD_REPORT_MESSAGE);
45-
logger.info(`${config.dashboardUrl}${buildId}`);
46-
});
40+
let resolveExitCode = (exitCode) => {
41+
return new Promise((resolve, _reject) => { resolve(exitCode) });
4742
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"dependencies": {
1515
"archiver": "^3.1.1",
16+
"chalk": "^4.1.0",
1617
"fs-extra": "^8.1.0",
1718
"mkdirp": "^1.0.3",
1819
"request": "^2.88.0",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
const chai = require("chai"),
3+
expect = chai.expect,
4+
chaiAsPromised = require("chai-as-promised");
5+
6+
chai.use(chaiAsPromised);
7+
const specDetails = require('../../../../../bin/helpers/sync/failedSpecsDetails');
8+
9+
describe("failedSpecsDetails", () => {
10+
context("data is empty", () => {
11+
let data = [];
12+
it('returns 0 exit code', () => {
13+
return specDetails.failedSpecsDetails(data).then((status) => {
14+
expect(status).to.equal(0);
15+
});
16+
});
17+
});
18+
19+
context("data does not have failed specs", () => {
20+
let data = [
21+
{specName: 'spec2.name.js', status: 'Skipped', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'}
22+
];
23+
24+
it("returns 0 exit code", () => {
25+
return specDetails.failedSpecsDetails(data).then((status) => {
26+
expect(status).to.equal(0);
27+
});
28+
});
29+
});
30+
31+
context("data has failed specs", () => {
32+
let data = [
33+
{specName: 'spec2.name.js', status: 'Failed', combination: 'Win 10 / Chrome 78', sessionId: '3d3rdf3r...'}
34+
];
35+
36+
it("returns 1 exit code", () => {
37+
return specDetails.failedSpecsDetails(data)
38+
.then((status) => {
39+
chai.assert.equal(status, 1);
40+
expect(status).to.equal(1);
41+
}).catch((status) => {
42+
expect(status).to.equal(1);
43+
});
44+
});
45+
});
46+
});

test/unit/bin/helpers/syncRunner.js

Whitespace-only changes.

0 commit comments

Comments
 (0)