Skip to content

Commit 3929880

Browse files
committed
Merge branch 'master' of github.com:browserstack/browserstack-cypress-cli into CYP_383_config
2 parents 9c198c4 + 2b7b833 commit 3929880

File tree

12 files changed

+1157
-93
lines changed

12 files changed

+1157
-93
lines changed

bin/commands/runs.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,33 @@ const archiver = require("../helpers/archiver"),
1111

1212
module.exports = function run(args) {
1313
let bsConfigPath = utils.getConfigPath(args.cf);
14+
//Delete build_results.txt from log folder if already present.
15+
utils.deleteResults();
1416

1517
return utils.validateBstackJson(bsConfigPath).then(function (bsConfig) {
1618
utils.setUsageReportingFlag(bsConfig, args.disableUsageReporting);
1719

18-
// accept the username from command line if provided
20+
// accept the username from command line or env variable if provided
1921
utils.setUsername(bsConfig, args);
2022

21-
// accept the access key from command line if provided
23+
// accept the access key from command line or env variable if provided
2224
utils.setAccessKey(bsConfig, args);
2325

2426
// accept the build name from command line if provided
2527
utils.setBuildName(bsConfig, args);
2628

29+
// accept the specs list from command line if provided
30+
utils.setUserSpecs(bsConfig, args);
31+
32+
// accept the env list from command line and set it
33+
utils.setTestEnvs(bsConfig, args);
34+
35+
//accept the local from env variable if provided
36+
utils.setLocal(bsConfig);
37+
38+
//accept the local identifier from env variable if provided
39+
utils.setLocalIdentifier(bsConfig);
40+
2741
// Validate browserstack.json values and parallels specified via arguments
2842
return capabilityHelper.validate(bsConfig, args).then(function (validated) {
2943
logger.info(validated);
@@ -32,7 +46,7 @@ module.exports = function run(args) {
3246
utils.setParallels(bsConfig, args);
3347

3448
// Archive the spec files
35-
return archiver.archive(bsConfig.run_settings, config.fileName).then(function (data) {
49+
return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude).then(function (data) {
3650

3751
// Uploaded zip file
3852
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) {
@@ -41,6 +55,13 @@ module.exports = function run(args) {
4155
return build.createBuild(bsConfig, zip).then(function (data) {
4256
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
4357
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${config.dashboardUrl}${data.build_id}`;
58+
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
59+
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)) {
60+
logger.warn(Constants.userMessages.NO_PARALLELS);
61+
}
62+
63+
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
64+
4465
logger.info(message);
4566
logger.info(dashboardLink);
4667
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);

bin/helpers/archiver.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
const fs = require("fs");
33

44
const archiver = require("archiver"),
5-
logger = require("./logger").winstonLogger;
5+
Constants = require('../helpers/constants'),
6+
logger = require("./logger").winstonLogger,
7+
utils = require('../helpers/utils');
68

7-
const archiveSpecs = (runSettings, filePath) => {
9+
const archiveSpecs = (runSettings, filePath, excludeFiles) => {
810
return new Promise(function (resolve, reject) {
911
var output = fs.createWriteStream(filePath);
1012

@@ -36,9 +38,10 @@ const archiveSpecs = (runSettings, filePath) => {
3638

3739
archive.pipe(output);
3840

39-
let allowedFileTypes = [ 'js', 'json', 'txt', 'ts', 'feature', 'features' ];
40-
allowedFileTypes.forEach(fileType => {
41-
archive.glob(`**/*.${fileType}`, { cwd: cypressFolderPath, matchBase: true, ignore: ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json'] });
41+
let ignoreFiles = getFilesToIgnore(runSettings, excludeFiles);
42+
43+
Constants.allowedFileTypes.forEach(fileType => {
44+
archive.glob(`**/*.${fileType}`, { cwd: cypressFolderPath, matchBase: true, ignore: ignoreFiles });
4245
});
4346

4447
let packageJSON = {};
@@ -60,4 +63,21 @@ const archiveSpecs = (runSettings, filePath) => {
6063
});
6164
}
6265

66+
const getFilesToIgnore = (runSettings, excludeFiles) => {
67+
let ignoreFiles = Constants.filesToIgnoreWhileUploading;
68+
69+
// exclude files asked by the user
70+
// args will take precedence over config file
71+
if (!utils.isUndefined(excludeFiles)) {
72+
let excludePatterns = utils.fixCommaSeparatedString(excludeFiles).split(',');
73+
ignoreFiles = ignoreFiles.concat(excludePatterns);
74+
logger.info(`Excluding files matching: ${JSON.stringify(excludePatterns)}`);
75+
} else if (!utils.isUndefined(runSettings.exclude) && runSettings.exclude.length) {
76+
ignoreFiles = ignoreFiles.concat(runSettings.exclude);
77+
logger.info(`Excluding files matching: ${JSON.stringify(runSettings.exclude)}`);
78+
}
79+
80+
return ignoreFiles;
81+
}
82+
6383
exports.archive = archiveSpecs

bin/helpers/capabilityHelper.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ const caps = (bsConfig, zip) => {
4747

4848
// Local Identifier
4949
obj.localIdentifier = null;
50-
if (obj.local === true && (bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier))
51-
{
50+
if (obj.local === true && (bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier)) {
5251
obj.localIdentifier = bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier;
5352
logger.log(`Local Identifier is set to: ${obj.localIdentifier}`);
5453
}
@@ -68,8 +67,18 @@ const caps = (bsConfig, zip) => {
6867
obj.callbackURL = bsConfig.run_settings.callback_url;
6968
obj.projectNotifyURL = bsConfig.run_settings.project_notify_URL;
7069
obj.parallels = bsConfig.run_settings.parallels;
70+
71+
if (!Utils.isUndefined(bsConfig.run_settings.specs)){
72+
obj.specs = bsConfig.run_settings.specs;
73+
}
74+
75+
if (!Utils.isUndefined(bsConfig.run_settings.env)){
76+
obj.env = bsConfig.run_settings.env;
77+
}
7178
}
7279

80+
if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined
81+
7382
if (obj.project) logger.log(`Project name is: ${obj.project}`);
7483

7584
if (obj.customBuildName) logger.log(`Build name is: ${obj.customBuildName}`);
@@ -86,16 +95,18 @@ const caps = (bsConfig, zip) => {
8695
}
8796

8897
const validate = (bsConfig, args) => {
89-
return new Promise(function(resolve, reject){
98+
return new Promise(function (resolve, reject) {
9099
if (!bsConfig) reject(Constants.validationMessages.EMPTY_BROWSERSTACK_JSON);
91100

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

103+
if( bsConfig.auth.username == "<Your BrowserStack username>" || bsConfig.auth.access_key == "<Your BrowserStack access key>" ) reject(Constants.validationMessages.INVALID_DEFAULT_AUTH_PARAMS);
104+
94105
if (!bsConfig.browsers || bsConfig.browsers.length === 0) reject(Constants.validationMessages.EMPTY_BROWSER_LIST);
95106

96107
if (!bsConfig.run_settings) reject(Constants.validationMessages.EMPTY_RUN_SETTINGS);
97108

98-
if (!bsConfig.run_settings.cypress_proj_dir) reject(Constants.validationMessages.EMPTY_SPEC_FILES);
109+
if (!bsConfig.run_settings.cypress_proj_dir) reject(Constants.validationMessages.EMPTY_CYPRESS_PROJ_DIR);
99110

100111
// validate parallels specified in browserstack.json if parallels are not specified via arguments
101112
if (!Utils.isUndefined(args) && Utils.isUndefined(args.parallels) && !Utils.isParallelValid(bsConfig.run_settings.parallels)) reject(Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION);
@@ -105,10 +116,16 @@ const validate = (bsConfig, args) => {
105116

106117
if (!fs.existsSync(path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json'))) reject(Constants.validationMessages.CYPRESS_JSON_NOT_FOUND + bsConfig.run_settings.cypress_proj_dir);
107118

108-
try{
109-
let cypressJson = fs.readFileSync(path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json'))
110-
JSON.parse(cypressJson)
111-
}catch(error){
119+
try {
120+
let cypressJson = fs.readFileSync(path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json'));
121+
cypressJson = JSON.parse(cypressJson);
122+
// Cypress Json Base Url & Local true check
123+
if (!Utils.isUndefined(cypressJson.baseUrl) && cypressJson.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET);
124+
125+
// Detect if the user is not using the right directory structure, and throw an error
126+
if (!Utils.isUndefined(cypressJson.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypress_proj_dir,cypressJson.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE);
127+
128+
} catch (error) {
112129
reject(Constants.validationMessages.INVALID_CYPRESS_JSON)
113130
}
114131

bin/helpers/constants.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ const userMessages = {
1313
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
1414
FAILED_TO_ZIP: "Failed to zip files.",
1515
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."
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."
1719
};
1820

1921
const validationMessages = {
@@ -22,14 +24,17 @@ const validationMessages = {
2224
EMPTY_TEST_SUITE: "Test suite is empty",
2325
EMPTY_BROWSERSTACK_JSON: "Empty browserstack.json",
2426
EMPTY_RUN_SETTINGS: "Empty run settings",
25-
EMPTY_SPEC_FILES: "No spec files specified in run_settings",
27+
EMPTY_CYPRESS_PROJ_DIR: "cypress_proj_dir is not set in run_settings. See https://www.browserstack.com/docs/automate/cypress/sample-tutorial to learn more.",
2628
VALIDATED: "browserstack.json file is validated",
2729
NOT_VALID: "browerstack.json is not valid",
2830
NOT_VALID_JSON: "browerstack.json is not a valid json",
2931
INVALID_EXTENSION: "Invalid files, please remove these files and try again.",
3032
INVALID_PARALLELS_CONFIGURATION: "Invalid value specified for parallels to use. Maximum parallels to use should be a number greater than 0.",
3133
CYPRESS_JSON_NOT_FOUND: "cypress.json file is not found at cypress_proj_dir path ",
32-
INVALID_CYPRESS_JSON: "cypress.json is not a valid json"
34+
INVALID_CYPRESS_JSON: "cypress.json is not a valid json",
35+
INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication",
36+
LOCAL_NOT_SET: "To test <baseUrl value> on BrowserStack, you will have to set up Local testing. Read more here: https://www.browserstack.com/docs/automate/cypress/local-testing",
37+
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists."
3338
};
3439

3540
const cliMessages = {
@@ -56,12 +61,17 @@ const cliMessages = {
5661
INFO: "Run your tests on BrowserStack.",
5762
DESC: "Path to BrowserStack config",
5863
CONFIG_DEMAND: "config file is required",
59-
BUILD_NAME: "The build name you want to use to name your test runs"
64+
BUILD_NAME: "The build name you want to use to name your test runs",
65+
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
66+
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
67+
SPECS_DESCRIPTION: 'Specify the spec files to run',
68+
ENV_DESCRIPTION: "Specify the environment variables for your spec files"
6069
},
6170
COMMON: {
6271
DISABLE_USAGE_REPORTING: "Disable usage reporting",
6372
USERNAME: "Your BrowserStack username",
64-
ACCESS_KEY: "Your BrowserStack access key"
73+
ACCESS_KEY: "Your BrowserStack access key",
74+
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty"
6575
}
6676
}
6777

@@ -74,9 +84,15 @@ const messageTypes = {
7484
NULL: null
7585
}
7686

87+
const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf', 'jpg', 'jpeg', 'png', 'zip'];
88+
89+
const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip']
90+
7791
module.exports = Object.freeze({
7892
userMessages,
7993
cliMessages,
8094
validationMessages,
8195
messageTypes,
96+
allowedFileTypes,
97+
filesToIgnoreWhileUploading
8298
});

0 commit comments

Comments
 (0)