Skip to content

Commit ff9be4d

Browse files
karanshah-browserstacksuryartroshan04
authored
Improve Local Testing experience (#114)
* Added local_mode and cli args. Calculate local_identifier based on local_mode. * Adding Local Binary start and stop logic * Adding demand message for local-identifier and local-mode options * Adding log messages for sync and local mode * upgrading yargs and putting requiredArgs * passed already failing 12 cases * added new test cases for the modified code * added new test cases and passed already failing test cases * removed unwanted files * Checking local identifier running in always on mode * local inferred, local mode inferred, sync inferred. - Adding checks and params for local, local mode, and sync inferred. * passed all failing tests and added new specs * Adding local start and stop error * Updated validation messages for local cli * Send the value of local_mode not the true/false * Bug fixes for callback stop and start binary * Removing bshost. * Adding local_config_file for passing configuration for local binary * Updating inferred event logic - If the user passed anything explicitly, then it is not inferred. - This is to understand which of the "auto-fallback" flows does CLI fall in. - Inverted the logic of the *_inferred events. * updating user agent to 1.7.2 * written extra specs and passed failing spec * removed unwanted log files * covered new functions under test * Modified local unit tests * Fixing Unit test cases * removed local object creation * Indentation and minor null pointer fixes. * Adding placeholders for local_mode and local_config_file in default json * Local Start fail error. * Fix Local Inferred logic * Fixed local_mode not set to always-on when local_identifier is supplied in browserstack.json * Send local_identifier_error when local_identifier not running in stopBinary * Local mode and id validation * Added test cases for local testing bug fixes * Warning message in case of local_mode is invalid * Updated message for invalid local config file * Fixed cli args precendence on-demand bug * Updating version to 1.8.0 Co-authored-by: Surya Tripathi <raj.surya19@gmail.com> Co-authored-by: roshan <roshannikam04@gmail.com>
1 parent 69da94e commit ff9be4d

File tree

11 files changed

+970
-69
lines changed

11 files changed

+970
-69
lines changed

bin/commands/runs.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,16 @@ module.exports = function run(args) {
4040
utils.setTestEnvs(bsConfig, args);
4141

4242
//accept the local from env variable if provided
43-
utils.setLocal(bsConfig);
43+
utils.setLocal(bsConfig, args);
44+
45+
// set Local Mode (on-demand/ always-on)
46+
utils.setLocalMode(bsConfig, args);
4447

4548
//accept the local identifier from env variable if provided
46-
utils.setLocalIdentifier(bsConfig);
49+
utils.setLocalIdentifier(bsConfig, args);
50+
51+
// set Local Config File
52+
utils.setLocalConfigFile(bsConfig, args);
4753

4854
// run test in headed mode
4955
utils.setHeaded(bsConfig, args);
@@ -61,8 +67,12 @@ module.exports = function run(args) {
6167
return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude).then(function (data) {
6268

6369
// Uploaded zip file
64-
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) {
70+
return zipUploader.zipUpload(bsConfig, config.fileName).then(async function (zip) {
6571
// Create build
72+
73+
//setup Local Testing
74+
let bs_local = await utils.setupLocalTesting(bsConfig, args);
75+
6676
return build.createBuild(bsConfig, zip).then(function (data) {
6777
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
6878
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
@@ -82,7 +92,11 @@ module.exports = function run(args) {
8292
}
8393

8494
if (args.sync) {
85-
syncRunner.pollBuildStatus(bsConfig, data).then((exitCode) => {
95+
syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => {
96+
97+
// stop the Local instance
98+
await utils.stopLocalBinary(bsConfig, bs_local, args);
99+
86100
// Generate custom report!
87101
reportGenerator(bsConfig, data.build_id, args, function(){
88102
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
@@ -96,17 +110,24 @@ module.exports = function run(args) {
96110
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
97111
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
98112
return;
99-
}).catch(function (err) {
113+
}).catch(async function (err) {
100114
// Build creation failed
101115
logger.error(err);
116+
// stop the Local instance
117+
await utils.stopLocalBinary(bsConfig, bs_local, args);
118+
102119
utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed');
103120
});
104121
}).catch(function (err) {
105-
// Zip Upload failed
122+
// Zip Upload failed | Local Start failed
106123
logger.error(err);
107-
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
108-
fileHelpers.deleteZip();
109-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
124+
if(err === Constants.userMessages.LOCAL_START_FAILED){
125+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.LOCAL_START_FAILED}`, Constants.messageTypes.ERROR, 'local_start_failed');
126+
} else {
127+
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
128+
fileHelpers.deleteZip();
129+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
130+
}
110131
});
111132
}).catch(function (err) {
112133
// Zipping failed

bin/helpers/capabilityHelper.js

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,47 @@ const caps = (bsConfig, zip) => {
4242
reject("Test suite is empty");
4343
}
4444

45+
// Inferred settings
46+
if(bsConfig.connection_settings){
47+
if (bsConfig.connection_settings.local_mode_inferred) {
48+
obj.local_mode_inferred = bsConfig.connection_settings.local_mode_inferred;
49+
}
50+
51+
if (bsConfig.connection_settings.local_inferred) {
52+
obj.local_inferred = bsConfig.connection_settings.local_inferred;
53+
}
54+
55+
if (bsConfig.connection_settings.sync_inferred) {
56+
obj.sync_inferred = bsConfig.connection_settings.sync_inferred;
57+
logger.info('Setting "sync" mode to enable Local testing.');
58+
}
59+
}
60+
4561
// Local
4662
obj.local = false;
47-
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) obj.local = true;
48-
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`);
63+
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) {
64+
obj.local = true;
65+
}
66+
67+
obj.localMode = null;
68+
// Local Mode
69+
if (obj.local === true && bsConfig.connection_settings.local_mode) {
70+
obj.localMode = bsConfig.connection_settings.local_mode;
71+
if (bsConfig.connection_settings.user_defined_local_mode_warning) {
72+
logger.warn(Constants.userMessages.INVALID_LOCAL_MODE_WARNING);
73+
}
74+
logger.info(`Local testing set up in ${obj.localMode} mode.`);
75+
}
4976

5077
// Local Identifier
5178
obj.localIdentifier = null;
5279
if (obj.local === true && (bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier)) {
5380
obj.localIdentifier = bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier;
54-
logger.log(`Local Identifier is set to: ${obj.localIdentifier}`);
81+
logger.info(`Local testing identifier: ${obj.localIdentifier}`);
5582
}
5683

84+
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`);
85+
5786
// Project name
5887
obj.project = "project-name";
5988
// Build name
@@ -94,9 +123,9 @@ const caps = (bsConfig, zip) => {
94123

95124
if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined
96125

97-
if (obj.project) logger.log(`Project name is: ${obj.project}`);
126+
if (obj.project) logger.info(`Project name is: ${obj.project}`);
98127

99-
if (obj.customBuildName) logger.log(`Build name is: ${obj.customBuildName}`);
128+
if (obj.customBuildName) logger.info(`Build name is: ${obj.customBuildName}`);
100129

101130
if (obj.callbackURL) logger.info(`callback url is : ${obj.callbackURL}`);
102131

@@ -132,6 +161,16 @@ const validate = (bsConfig, args) => {
132161
// if parallels specified via arguments validate only arguments
133162
if (!Utils.isUndefined(args) && !Utils.isUndefined(args.parallels) && !Utils.isParallelValid(args.parallels)) reject(Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION);
134163

164+
// validate local args i.e --local-mode and --local-identifier
165+
166+
if( Utils.searchForOption('--local-identifier') && (Utils.isUndefined(args.localIdentifier) || (!Utils.isUndefined(args.localIdentifier) && !args.localIdentifier.trim()))) reject(Constants.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER);
167+
168+
if( Utils.getLocalFlag(bsConfig.connection_settings) && (Utils.isUndefined(bsConfig["connection_settings"]["local_identifier"]) || ( !Utils.isUndefined(bsConfig["connection_settings"]["local_identifier"]) && !bsConfig["connection_settings"]["local_identifier"].trim()))) reject(Constants.validationMessages.INVALID_LOCAL_IDENTIFIER);
169+
170+
if( Utils.searchForOption('--local-mode') && ( Utils.isUndefined(args.localMode) || (!Utils.isUndefined(args.localMode) && !["always-on","on-demand"].includes(args.localMode)))) reject(Constants.validationMessages.INVALID_LOCAL_MODE);
171+
172+
if( Utils.searchForOption('--local-config-file') && ( Utils.isUndefined(args.localConfigFile) || (!Utils.isUndefined(args.localConfigFile) && !fs.existsSync(args.localConfigFile)))) reject(Constants.validationMessages.INVALID_LOCAL_CONFIG_FILE);
173+
135174
// validate if config file provided exists or not when cypress_config_file provided
136175
// validate the cypressProjectDir key otherwise.
137176
let cypressConfigFilePath = bsConfig.run_settings.cypressConfigFilePath;

bin/helpers/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"uploadUrl": "https://api-cloud.browserstack.com/automate-frameworks/cypress/upload",
33
"rails_host": "https://api.browserstack.com",
44
"dashboardUrl": "https://automate.browserstack.com/dashboard/v2/builds/",
5-
"usageReportingUrl": "https://eds.browserstack.com:443/send_event_cy_internal"
5+
"usageReportingUrl": "https://eds.browserstack.com:443/send_event_cy_internal",
6+
"localTestingListUrl": "https://www.browserstack.com/local/v1/list"
67
}

bin/helpers/constants.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ const userMessages = {
3737
FATAL_NETWORK_ERROR: `fatal: unable to access '${config.buildUrl}': Could not resolve host: ${config.rails_host}`,
3838
RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`,
3939
CHECK_DASHBOARD_AT: "Please check the build status at: ",
40-
CYPRESS_VERSION_CHANGED: "Your build will run using Cypress <actualVersion> instead of Cypress <preferredVersion>. Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions"
40+
CYPRESS_VERSION_CHANGED: "Your build will run using Cypress <actualVersion> instead of Cypress <preferredVersion>. Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions",
41+
LOCAL_START_FAILED: "Local Testing setup failed.",
42+
LOCAL_STOP_FAILED: "Local Binary stop failed.",
43+
INVALID_LOCAL_MODE_WARNING: "Invalid value specified for local_mode. local_mode: (\"always-on\" | \"on-demand\"). For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference"
4144
};
4245

4346
const validationMessages = {
@@ -57,7 +60,11 @@ const validationMessages = {
5760
INVALID_CYPRESS_JSON: "cypress.json is not a valid json",
5861
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",
5962
LOCAL_NOT_SET: "To test <baseUrlValue> on BrowserStack, you will have to set up Local testing. Read more here: https://www.browserstack.com/docs/automate/cypress/local-testing",
60-
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists."
63+
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists.",
64+
INVALID_CLI_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. \n--local-identifier <String>.\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference",
65+
INVALID_LOCAL_MODE: "When using --local-mode, a value needs to be supplied. \n--local-mode (\"always-on\" | \"on-demand\").\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference",
66+
INVALID_LOCAL_CONFIG_FILE: "Using --local-config-file requires an input of the form /path/to/config-file.yml.\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference",
67+
INVALID_LOCAL_IDENTIFIER: "Invalid value specified for local_identifier. For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference"
6168
};
6269

6370
const cliMessages = {
@@ -94,6 +101,10 @@ const cliMessages = {
94101
SYNC_DESCRIPTION: "Makes the run command in sync",
95102
BUILD_REPORT_MESSAGE: "See the entire build report here",
96103
HEADED: "Run your tests in a headed browser instead of a headless browser",
104+
LOCAL: "Accepted values: (true | false) - create a local testing connection to let you test staging and localhost websites, or sites behind proxies; learn more at browserstack.com/local-testing",
105+
LOCAL_MODE: 'Accepted values: ("always-on" | "on-demand") - if you choose to keep the binary "always-on", it will speed up your tests by keeping the Local connection warmed up in the background; otherwise, you can choose to have it spawn and killed for every build',
106+
LOCAL_IDENTIFIER: "Accepted values: String - assign an identifier to your Local process instance",
107+
LOCAL_CONFIG_FILE: "Accepted values: String - path to local config-file to your Local process instance. Learn more at https://www.browserstack.com/local-testing/binary-params"
97108
},
98109
COMMON: {
99110
DISABLE_USAGE_REPORTING: "Disable usage reporting",

bin/helpers/usageReporting.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,5 +231,6 @@ function send(args) {
231231
}
232232

233233
module.exports = {
234-
send
235-
}
234+
send,
235+
cli_version_and_path,
236+
};

0 commit comments

Comments
 (0)