Skip to content

Commit ef9d6ec

Browse files
committed
Merge branch 'master' into custom-reporter
2 parents 35d0f65 + 7cafe38 commit ef9d6ec

23 files changed

+1143
-150
lines changed

bin/commands/runs.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const archiver = require("../helpers/archiver"),
77
capabilityHelper = require("../helpers/capabilityHelper"),
88
Constants = require("../helpers/constants"),
99
utils = require("../helpers/utils"),
10-
fileHelpers = require("../helpers/fileHelpers");
10+
fileHelpers = require("../helpers/fileHelpers"),
11+
syncRunner = require("../helpers/syncRunner");
1112

1213
module.exports = function run(args) {
1314
let bsConfigPath = utils.getConfigPath(args.cf);
@@ -45,7 +46,6 @@ module.exports = function run(args) {
4546

4647
// Validate browserstack.json values and parallels specified via arguments
4748
return capabilityHelper.validate(bsConfig, args).then(function (validated) {
48-
logger.info(validated);
4949

5050
// accept the number of parallels
5151
utils.setParallels(bsConfig, args);
@@ -55,20 +55,29 @@ module.exports = function run(args) {
5555

5656
// Uploaded zip file
5757
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) {
58-
5958
// Create build
6059
return build.createBuild(bsConfig, zip).then(function (data) {
6160
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
62-
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${config.dashboardUrl}${data.build_id}`;
61+
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
6362
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
6463
if ((utils.isUndefined(bsConfig.run_settings.parallels) && utils.isUndefined(args.parallels)) || (!utils.isUndefined(bsConfig.run_settings.parallels) && bsConfig.run_settings.parallels == Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE)) {
6564
logger.warn(Constants.userMessages.NO_PARALLELS);
6665
}
6766

68-
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
67+
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) {
68+
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
69+
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES_READ_MORE);
70+
}
71+
if (args.sync) {
72+
syncRunner.pollBuildStatus(bsConfig, data).then((exitCode) => {
73+
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
74+
utils.handleSyncExit(exitCode, data.dashboard_url)
75+
});
76+
}
6977

7078
logger.info(message);
7179
logger.info(dashboardLink);
80+
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
7281
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
7382
return;
7483
}).catch(function (err) {
@@ -80,9 +89,8 @@ module.exports = function run(args) {
8089
// Zip Upload failed
8190
logger.error(err);
8291
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
83-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
84-
}).finally(function () {
8592
fileHelpers.deleteZip();
93+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
8694
});
8795
}).catch(function (err) {
8896
// Zipping failed

bin/helpers/archiver.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const archiveSpecs = (runSettings, filePath, excludeFiles) => {
1313

1414
var cypressFolderPath = path.dirname(runSettings.cypressConfigFilePath);
1515

16+
logger.info(`Creating tests.zip with files in ${cypressFolderPath}`);
17+
1618
var archive = archiver('zip', {
1719
zlib: { level: 9 } // Sets the compression level.
1820
});

bin/helpers/capabilityHelper.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,32 @@ const caps = (bsConfig, zip) => {
2020

2121
// Browser list
2222
let osBrowserArray = [];
23+
let browsersList = [];
2324
if (bsConfig.browsers) {
2425
bsConfig.browsers.forEach((element) => {
2526
osBrowser = element.os + "-" + element.browser;
27+
osAndBrowser = element.os + " / " + Utils.capitalizeFirstLetter(element.browser);
2628
element.versions.forEach((version) => {
2729
osBrowserArray.push(osBrowser + version);
30+
browsersList.push(`${osAndBrowser} (${version})`);
2831
});
2932
});
3033
}
3134
obj.devices = osBrowserArray;
3235
if (obj.devices.length == 0) reject(Constants.validationMessages.EMPTY_BROWSER_LIST);
33-
logger.info(`Browser list: ${osBrowserArray.toString()}`);
36+
logger.info(`Browsers list: ${browsersList.join(", ")}`);
3437

3538
// Test suite
3639
if (zip.zip_url && zip.zip_url.split("://")[1].length !== 0) {
3740
obj.test_suite = zip.zip_url.split("://")[1];
3841
} else {
3942
reject("Test suite is empty");
4043
}
41-
logger.info(`Test suite: bs://${obj.test_suite}`);
4244

4345
// Local
4446
obj.local = false;
4547
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) obj.local = true;
46-
logger.info(`Local is set to: ${obj.local}`);
48+
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`);
4749

4850
// Local Identifier
4951
obj.localIdentifier = null;
@@ -100,6 +102,7 @@ const caps = (bsConfig, zip) => {
100102

101103
const validate = (bsConfig, args) => {
102104
return new Promise(function (resolve, reject) {
105+
logger.info(Constants.userMessages.VALIDATING_CONFIG);
103106
if (!bsConfig) reject(Constants.validationMessages.EMPTY_BROWSERSTACK_JSON);
104107

105108
if (!bsConfig.auth) reject(Constants.validationMessages.INCORRECT_AUTH_PARAMS);

bin/helpers/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ config.cypress_v1 = `${config.rails_host}/automate/cypress/v1`;
1616
config.buildUrl = `${config.cypress_v1}/builds/`;
1717
config.buildStopUrl = `${config.cypress_v1}/builds/stop/`;
1818
config.fileName = "tests.zip";
19+
config.retries = 5;
20+
config.networkErrorExitCode = 2;
1921

2022
module.exports = config;

bin/helpers/constants.js

Lines changed: 82 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,42 @@
1+
let config = require("./config");
2+
3+
const syncCLI = {
4+
FAILED_SPEC_DETAILS_COL_HEADER: ['Spec', 'Status', 'Browser', 'BrowserStack Session ID'],
5+
LOGS: {
6+
INIT_LOG: "All tests:"
7+
},
8+
INITIAL_DELAY_MULTIPLIER: 10
9+
};
10+
111
const userMessages = {
2-
BUILD_FAILED: "Build creation failed.",
3-
BUILD_GENERATE_REPORT_FAILED: "Generating report for the build <build-id> failed.",
4-
BUILD_CREATED: "Build created",
5-
BUILD_INFO_FAILED: "Failed to get build info.",
6-
BUILD_STOP_FAILED: "Failed to stop build.",
7-
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
8-
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
9-
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
10-
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
11-
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
12-
ZIP_DELETE_FAILED: "Could not delete local file.",
13-
ZIP_DELETED: "Zip file deleted successfully.",
14-
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
15-
FAILED_TO_ZIP: "Failed to zip files.",
16-
VISIT_DASHBOARD: "Visit the Automate dashboard for test reporting:",
17-
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
18-
NO_PARALLELS: "Your tests will run sequentially. Read more about running your tests in parallel here: https://www.browserstack.com/docs/automate/cypress/run-tests-in-parallel",
19-
NO_NPM_DEPENDENCIES: "No npm dependencies specified. Read more here: https://www.browserstack.com/docs/automate/cypress/npm-packages. You can suppress this warning by using --disable-npm-warning flag."
12+
BUILD_FAILED: "Build creation failed.",
13+
BUILD_GENERATE_REPORT_FAILED: "Generating report for the build <build-id> failed.",
14+
BUILD_CREATED: "Build created",
15+
BUILD_INFO_FAILED: "Failed to get build info.",
16+
BUILD_STOP_FAILED: "Failed to stop build.",
17+
BUILD_REPORT_MESSAGE: "See the entire build report here:",
18+
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
19+
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
20+
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
21+
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
22+
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
23+
ZIP_DELETE_FAILED: "Could not delete tests.zip successfully.",
24+
ZIP_DELETED: "Deleted tests.zip successfully.",
25+
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
26+
FAILED_TO_ZIP: "Failed to zip files.",
27+
VISIT_DASHBOARD: "Visit the Automate dashboard for real-time test reporting:",
28+
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
29+
NO_PARALLELS: "Your specs will run sequentially on a single machine. Read more about running your specs in parallel here: https://www.browserstack.com/docs/automate/cypress/run-tests-in-parallel",
30+
NO_NPM_DEPENDENCIES: "No npm dependencies specified - your specs might fail if they need any packages to be installed before running.",
31+
NO_NPM_DEPENDENCIES_READ_MORE: "Read more about npm dependencies here: https://www.browserstack.com/docs/automate/cypress/npm-packages. You can suppress this warning by using --disable-npm-warning flag.",
32+
VALIDATING_CONFIG: "Validating the config",
33+
UPLOADING_TESTS: "Uploading the tests to BrowserStack",
34+
LOCAL_TRUE: "you will now be able to test localhost / private URLs",
35+
LOCAL_FALSE: "you won't be able to test localhost / private URLs",
36+
EXIT_SYNC_CLI_MESSAGE: "Exiting the CLI, but your build is still running. You can use the --sync option to keep getting test updates. You can also use the build-info <build-id> command now.",
37+
FATAL_NETWORK_ERROR: `fatal: unable to access '${config.buildUrl}': Could not resolve host: ${config.rails_host}`,
38+
RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`,
39+
CHECK_DASHBOARD_AT: "Please check the build status at: "
2040
};
2141

2242
const validationMessages = {
@@ -40,47 +60,49 @@ const validationMessages = {
4060
};
4161

4262
const cliMessages = {
43-
VERSION: {
44-
INFO: "shows version information",
45-
HELP: "Specify --help for available options",
46-
DEMAND: "Requires init, run or poll argument"
47-
},
48-
INIT: {
49-
INFO: "create a browserstack.json file in the folder specified with the default configuration options.",
50-
DESC: "Init in a specified folder"
51-
},
52-
BUILD: {
53-
INFO: "Check status of your build.",
54-
STOP: "Stop your build.",
55-
DEMAND: "Requires a build id.",
56-
DESC: "Path to BrowserStack config",
57-
CONFIG_DEMAND: "config file is required",
58-
INFO_MESSAGE: "Getting information for buildId ",
59-
STOP_MESSAGE: "Stopping build with given buildId "
60-
},
61-
RUN: {
62-
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
63-
INFO: "Run your tests on BrowserStack.",
64-
DESC: "Path to BrowserStack config",
65-
CYPRESS_DESC: "Path to Cypress config file",
66-
CONFIG_DEMAND: "config file is required",
67-
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
68-
BUILD_NAME: "The build name you want to use to name your test runs",
69-
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
70-
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
71-
SPECS_DESCRIPTION: 'Specify the spec files to run',
72-
ENV_DESCRIPTION: "Specify the environment variables for your spec files"
73-
},
74-
COMMON: {
75-
DISABLE_USAGE_REPORTING: "Disable usage reporting",
76-
USERNAME: "Your BrowserStack username",
77-
ACCESS_KEY: "Your BrowserStack access key",
78-
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty"
79-
},
80-
GENERATE_REPORT: {
81-
INFO: "Generates the build report"
82-
}
83-
}
63+
VERSION: {
64+
INFO: "shows version information",
65+
HELP: "Specify --help for available options",
66+
DEMAND: "Requires init, run or poll argument",
67+
},
68+
INIT: {
69+
INFO: "create a browserstack.json file in the folder specified with the default configuration options.",
70+
DESC: "Init in a specified folder",
71+
},
72+
BUILD: {
73+
INFO: "Check status of your build.",
74+
STOP: "Stop your build.",
75+
DEMAND: "Requires a build id.",
76+
DESC: "Path to BrowserStack config",
77+
CONFIG_DEMAND: "config file is required",
78+
INFO_MESSAGE: "Getting information for buildId ",
79+
STOP_MESSAGE: "Stopping build with given buildId ",
80+
},
81+
RUN: {
82+
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
83+
INFO: "Run your tests on BrowserStack.",
84+
DESC: "Path to BrowserStack config",
85+
CYPRESS_DESC: "Path to Cypress config file",
86+
CONFIG_DEMAND: "config file is required",
87+
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
88+
BUILD_NAME: "The build name you want to use to name your test runs",
89+
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
90+
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
91+
SPECS_DESCRIPTION: "Specify the spec files to run",
92+
ENV_DESCRIPTION: "Specify the environment variables for your spec files",
93+
SYNC_DESCRIPTION: "Makes the run command in sync",
94+
BUILD_REPORT_MESSAGE: "See the entire build report here",
95+
},
96+
COMMON: {
97+
DISABLE_USAGE_REPORTING: "Disable usage reporting",
98+
USERNAME: "Your BrowserStack username",
99+
ACCESS_KEY: "Your BrowserStack access key",
100+
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty",
101+
},
102+
GENERATE_REPORT: {
103+
INFO: "Generates the build report"
104+
},
105+
};
84106

85107
const messageTypes = {
86108
SUCCESS: "success",
@@ -96,6 +118,7 @@ const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf
96118
const filesToIgnoreWhileUploading = ['**/node_modules/**', 'node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json']
97119

98120
module.exports = Object.freeze({
121+
syncCLI,
99122
userMessages,
100123
cliMessages,
101124
validationMessages,

bin/helpers/fileHelpers.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
const fs = require('fs-extra'),
33
path = require('path');
44

5-
const logger = require("./logger").winstonLogger,
6-
Constants = require("../helpers/constants"),
7-
config = require("../helpers/config");
5+
const logger = require('./logger').winstonLogger,
6+
Constants = require('../helpers/constants'),
7+
config = require('../helpers/config');
88

9-
exports.write = function(f, message, args, cb) {
9+
exports.write = function (f, message, args, cb) {
1010
message = message || 'Creating';
11-
fs.writeFile(f.path, f.file, function() {
12-
logger.info(message + " file: " + f.path);
13-
cb && cb(args)
11+
fs.writeFile(f.path, f.file, function () {
12+
logger.info(message + ' file: ' + f.path);
13+
cb && cb(args);
1414
});
15-
}
15+
};
1616

1717
exports.fileExists = function (filePath, cb) {
1818
fs.access(filePath, fs.F_OK, (err) => {
@@ -25,21 +25,20 @@ exports.fileExists = function (filePath, cb) {
2525
};
2626

2727
exports.deleteZip = () => {
28-
return fs.unlink(config.fileName, function (err) {
29-
if (err) {
30-
logger.info(Constants.userMessages.ZIP_DELETE_FAILED);
31-
return 1;
32-
} else {
33-
logger.info(Constants.userMessages.ZIP_DELETED);
34-
return 0;
35-
}
36-
});
37-
}
28+
try {
29+
fs.unlinkSync(config.fileName);
30+
logger.info(Constants.userMessages.ZIP_DELETED);
31+
return 0;
32+
} catch (err) {
33+
logger.info(Constants.userMessages.ZIP_DELETE_FAILED);
34+
return 1;
35+
}
36+
};
3837

3938
exports.dirExists = function (filePath, cb) {
4039
let exists = false;
4140
if (fs.existsSync(path.dirname(filePath), cb)) {
4241
exists = true;
4342
}
4443
cb && cb(exists);
45-
}
44+
};

bin/helpers/logger.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ const winstonLoggerParams = {
2121
],
2222
};
2323

24+
const winstonSyncCliLoggerParams = {
25+
transports: [
26+
new (winston.transports.Console)({
27+
formatter: (options) => {
28+
return (options.message ? options.message : '');
29+
}
30+
}),
31+
]
32+
}
33+
2434
const winstonFileLoggerParams = {
2535
transports: [
2636
new winston.transports.File({
@@ -31,3 +41,4 @@ const winstonFileLoggerParams = {
3141

3242
exports.winstonLogger = new winston.Logger(winstonLoggerParams);
3343
exports.fileLogger = new winston.Logger(winstonFileLoggerParams);
44+
exports.syncCliLogger = new winston.Logger(winstonSyncCliLoggerParams);

0 commit comments

Comments
 (0)