Skip to content

Commit 64dcb89

Browse files
Merge branch 'master' of github.com:browserstack/browserstack-cypress-cli into allocate_parallels_wrt_specs
2 parents a96d7f4 + 7cafe38 commit 64dcb89

23 files changed

+1138
-147
lines changed

bin/commands/runs.js

Lines changed: 15 additions & 6 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);
@@ -57,20 +58,29 @@ module.exports = function run(args) {
5758

5859
// Uploaded zip file
5960
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) {
60-
6161
// Create build
6262
return build.createBuild(bsConfig, zip).then(function (data) {
6363
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
64-
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${config.dashboardUrl}${data.build_id}`;
64+
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
6565
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
6666
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)) {
6767
logger.warn(Constants.userMessages.NO_PARALLELS);
6868
}
6969

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

7281
logger.info(message);
7382
logger.info(dashboardLink);
83+
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
7484
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
7585
return;
7686
}).catch(function (err) {
@@ -82,9 +92,8 @@ module.exports = function run(args) {
8292
// Zip Upload failed
8393
logger.error(err);
8494
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
85-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
86-
}).finally(function () {
8795
fileHelpers.deleteZip();
96+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
8897
});
8998
}).catch(function (err) {
9099
// 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: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
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_CREATED: "Build created",
4-
BUILD_INFO_FAILED: "Failed to get build info.",
5-
BUILD_STOP_FAILED: "Failed to stop build.",
6-
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
7-
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
8-
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
9-
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
10-
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
11-
ZIP_DELETE_FAILED: "Could not delete local file.",
12-
ZIP_DELETED: "Zip file deleted successfully.",
13-
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
14-
FAILED_TO_ZIP: "Failed to zip files.",
15-
VISIT_DASHBOARD: "Visit the Automate dashboard for test reporting:",
16-
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
17-
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",
18-
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_CREATED: "Build created",
14+
BUILD_INFO_FAILED: "Failed to get build info.",
15+
BUILD_STOP_FAILED: "Failed to stop build.",
16+
BUILD_REPORT_MESSAGE: "See the entire build report here:",
17+
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
18+
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
19+
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
20+
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
21+
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
22+
ZIP_DELETE_FAILED: "Could not delete tests.zip successfully.",
23+
ZIP_DELETED: "Deleted tests.zip successfully.",
24+
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
25+
FAILED_TO_ZIP: "Failed to zip files.",
26+
VISIT_DASHBOARD: "Visit the Automate dashboard for real-time test reporting:",
27+
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
28+
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",
29+
NO_NPM_DEPENDENCIES: "No npm dependencies specified - your specs might fail if they need any packages to be installed before running.",
30+
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.",
31+
VALIDATING_CONFIG: "Validating the config",
32+
UPLOADING_TESTS: "Uploading the tests to BrowserStack",
33+
LOCAL_TRUE: "you will now be able to test localhost / private URLs",
34+
LOCAL_FALSE: "you won't be able to test localhost / private URLs",
35+
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.",
36+
FATAL_NETWORK_ERROR: `fatal: unable to access '${config.buildUrl}': Could not resolve host: ${config.rails_host}`,
37+
RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`,
38+
CHECK_DASHBOARD_AT: "Please check the build status at: "
1939
};
2040

2141
const validationMessages = {
@@ -39,44 +59,46 @@ const validationMessages = {
3959
};
4060

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

81103
const messageTypes = {
82104
SUCCESS: "success",
@@ -96,6 +118,7 @@ const specFileTypes = ['js', 'ts', 'feature']
96118
const DEFAULT_CYPRESS_SPEC_PATH = "cypress/integration"
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)