Skip to content

Commit de3ed8e

Browse files
Merge branch 'master' into custom_reporting
2 parents 6210bf1 + f1239f1 commit de3ed8e

File tree

10 files changed

+297
-38
lines changed

10 files changed

+297
-38
lines changed

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
test
2+
results

bin/commands/runs.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,13 @@ module.exports = function run(args) {
120120
}
121121

122122
if (bsConfig.run_settings.cypress_version && bsConfig.run_settings.cypress_version !== data.cypress_version) {
123-
let versionMessage = utils.versionChangedMessage(bsConfig.run_settings.cypress_version, data.cypress_version)
124-
logger.warn(versionMessage);
123+
if (bsConfig.run_settings.cypress_version.toString().match(Constants.LATEST_VERSION_SYNTAX_REGEX)) {
124+
let versionMessage = utils.latestSyntaxToActualVersionMessage(bsConfig.run_settings.cypress_version, data.cypress_version);
125+
logger.info(versionMessage);
126+
} else {
127+
let versionMessage = utils.versionChangedMessage(bsConfig.run_settings.cypress_version, data.cypress_version);
128+
logger.warn(versionMessage);
129+
}
125130
}
126131

127132
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) {

bin/helpers/checkUploaded.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,7 @@ const checkSpecsMd5 = (runSettings, excludeFiles) => {
2222
hashHelper.hashWrapper(options).then(function (data) {
2323
const outputHash = crypto.createHash(Constants.hashingOptions.algo);
2424
outputHash.update(data);
25-
let packageJSON = {};
26-
27-
if (typeof runSettings.package_config_options === 'object') {
28-
Object.assign(packageJSON, runSettings.package_config_options);
29-
}
30-
31-
if (typeof runSettings.npm_dependencies === 'object') {
32-
Object.assign(packageJSON, {
33-
devDependencies: runSettings.npm_dependencies,
34-
});
35-
}
36-
37-
if (Object.keys(packageJSON).length > 0) {
38-
let packageJSONString = JSON.stringify(packageJSON);
39-
outputHash.update(packageJSONString);
40-
}
25+
outputHash.update(checkPackageMd5(runSettings));
4126

4227
if (
4328
runSettings.cypress_config_file &&
@@ -56,6 +41,27 @@ const checkSpecsMd5 = (runSettings, excludeFiles) => {
5641
});
5742
};
5843

44+
const checkPackageMd5 = (runSettings) => {
45+
const outputHash = crypto.createHash(Constants.hashingOptions.algo);
46+
let packageJSON = {};
47+
if (typeof runSettings.package_config_options === 'object') {
48+
Object.assign(packageJSON, runSettings.package_config_options);
49+
}
50+
51+
if (typeof runSettings.npm_dependencies === 'object') {
52+
Object.assign(packageJSON, {
53+
devDependencies: runSettings.npm_dependencies,
54+
});
55+
}
56+
57+
if (Object.keys(packageJSON).length > 0) {
58+
let packageJSONString = JSON.stringify(packageJSON);
59+
outputHash.update(packageJSONString);
60+
}
61+
62+
return outputHash.digest(Constants.hashingOptions.encoding)
63+
};
64+
5965
const checkUploadedMd5 = (bsConfig, args) => {
6066
return new Promise(function (resolve) {
6167
let obj = {
@@ -66,7 +72,8 @@ const checkUploadedMd5 = (bsConfig, args) => {
6672
}
6773
checkSpecsMd5(bsConfig.run_settings, args.exclude).then(function (md5data) {
6874
Object.assign(obj, {md5sum: md5data});
69-
let data = JSON.stringify({ zip_md5sum: md5data });
75+
let package_md5sum = checkPackageMd5(bsConfig.run_settings);
76+
let data = JSON.stringify({ zip_md5sum: md5data, instrument_package_md5sum: package_md5sum});
7077

7178
let options = {
7279
url: config.checkMd5sum,

bin/helpers/constants.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ const userMessages = {
4747
SPEC_LIMIT_WARNING: "You might not see all your results on the dashboard because of high spec count, please consider reducing the number of spec files in this folder.",
4848
DOWNLOAD_BUILD_ARTIFACTS_FAILED: "Downloading build artifacts for the build <build-id> failed for <machine-count> machines.",
4949
ASYNC_DOWNLOADS: "Test artifacts as specified under 'downloads' can be downloaded after the build has completed its run, using 'browserstack-cypress generate-downloads <build-id>'",
50-
DOWNLOAD_BUILD_ARTIFACTS_SUCCESS: "Your build artifact(s) have been successfully downloaded in '<user-path>/build_artifacts/<build-id>' directory"
50+
DOWNLOAD_BUILD_ARTIFACTS_SUCCESS: "Your build artifact(s) have been successfully downloaded in '<user-path>/build_artifacts/<build-id>' directory",
51+
LATEST_SYNTAX_TO_ACTUAL_VERSION_MESSAGE: "Your build will run using Cypress <actualVersion> as you had specified <latestSyntaxVersion>. Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions"
5152
};
5253

5354
const validationMessages = {
@@ -181,6 +182,8 @@ const usageReportingConstants = {
181182
GENERATE_DOWNLOADS: 'generate-downloads called',
182183
}
183184

185+
const LATEST_VERSION_SYNTAX_REGEX = /\d*.latest(.\d*)?/gm
186+
184187
module.exports = Object.freeze({
185188
syncCLI,
186189
userMessages,
@@ -195,5 +198,6 @@ module.exports = Object.freeze({
195198
DEFAULT_CYPRESS_SPEC_PATH,
196199
SPEC_TOTAL_CHAR_LIMIT,
197200
METADATA_CHAR_BUFFER_PER_SPEC,
198-
usageReportingConstants
201+
usageReportingConstants,
202+
LATEST_VERSION_SYNTAX_REGEX
199203
});

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;

bin/helpers/utils.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,12 @@ exports.versionChangedMessage = (preferredVersion, actualVersion) => {
726726
return message
727727
}
728728

729+
exports.latestSyntaxToActualVersionMessage = (latestSyntaxVersion, actualVersion) => {
730+
let message = Constants.userMessages.LATEST_SYNTAX_TO_ACTUAL_VERSION_MESSAGE.replace("<latestSyntaxVersion>", latestSyntaxVersion);
731+
message = message.replace("<actualVersion>", actualVersion);
732+
return message
733+
}
734+
729735
exports.isJSONInvalid = (err, args) => {
730736
let invalid = true
731737

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "browserstack-cypress-cli",
3-
"version": "1.8.1",
3+
"version": "1.9.0",
44
"description": "BrowserStack Cypress CLI for Cypress integration with BrowserStack's remote devices.",
55
"main": "index.js",
66
"scripts": {
@@ -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/checkUploaded.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ describe("checkUploaded", () => {
161161
.then(function (data) {
162162
chai.assert.equal(data, 'random_md5sum')
163163
sinon.assert.calledOnce(hashElementstub);
164-
sinon.assert.calledOnce(digestStub);
165-
sinon.assert.calledOnce(updateStub);
164+
sinon.assert.calledTwice(digestStub);
165+
sinon.assert.calledTwice(updateStub);
166166
})
167167
.catch((error) => {
168168
chai.assert.fail("Promise error");
@@ -188,8 +188,8 @@ describe("checkUploaded", () => {
188188
.then(function (data) {
189189
chai.assert.equal(data, 'random_md5sum')
190190
sinon.assert.calledOnce(hashElementstub);
191-
sinon.assert.calledOnce(digestStub);
192-
sinon.assert.calledThrice(updateStub);
191+
sinon.assert.called(digestStub);
192+
sinon.assert.callCount(updateStub, 4);
193193
})
194194
.catch((error) => {
195195
chai.assert.fail("Promise error");

0 commit comments

Comments
 (0)