browserstack-cypress-cli
Advanced tools
Comparing version 1.7.1 to 1.8.0
@@ -43,7 +43,13 @@ 'use strict'; | ||
//accept the local from env variable if provided | ||
utils.setLocal(bsConfig); | ||
utils.setLocal(bsConfig, args); | ||
// set Local Mode (on-demand/ always-on) | ||
utils.setLocalMode(bsConfig, args); | ||
//accept the local identifier from env variable if provided | ||
utils.setLocalIdentifier(bsConfig); | ||
utils.setLocalIdentifier(bsConfig, args); | ||
// set Local Config File | ||
utils.setLocalConfigFile(bsConfig, args); | ||
// run test in headed mode | ||
@@ -65,4 +71,8 @@ utils.setHeaded(bsConfig, args); | ||
// Uploaded zip file | ||
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) { | ||
return zipUploader.zipUpload(bsConfig, config.fileName).then(async function (zip) { | ||
// Create build | ||
//setup Local Testing | ||
let bs_local = await utils.setupLocalTesting(bsConfig, args); | ||
return build.createBuild(bsConfig, zip).then(function (data) { | ||
@@ -87,3 +97,7 @@ let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`; | ||
if (args.sync) { | ||
syncRunner.pollBuildStatus(bsConfig, data).then((exitCode) => { | ||
syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => { | ||
// stop the Local instance | ||
await utils.stopLocalBinary(bsConfig, bs_local, args); | ||
// Generate custom report! | ||
@@ -102,13 +116,20 @@ reportGenerator(bsConfig, data.build_id, args, function(){ | ||
return; | ||
}).catch(function (err) { | ||
}).catch(async function (err) { | ||
// Build creation failed | ||
logger.error(err); | ||
// stop the Local instance | ||
await utils.stopLocalBinary(bsConfig, bs_local, args); | ||
utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed'); | ||
}); | ||
}).catch(function (err) { | ||
// Zip Upload failed | ||
// Zip Upload failed | Local Start failed | ||
logger.error(err); | ||
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED); | ||
fileHelpers.deleteZip(); | ||
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed'); | ||
if(err === Constants.userMessages.LOCAL_START_FAILED){ | ||
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.LOCAL_START_FAILED}`, Constants.messageTypes.ERROR, 'local_start_failed'); | ||
} else { | ||
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED); | ||
fileHelpers.deleteZip(); | ||
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed'); | ||
} | ||
}); | ||
@@ -115,0 +136,0 @@ }).catch(function (err) { |
@@ -45,7 +45,34 @@ const logger = require("./logger").winstonLogger, | ||
// Inferred settings | ||
if(bsConfig.connection_settings){ | ||
if (bsConfig.connection_settings.local_mode_inferred) { | ||
obj.local_mode_inferred = bsConfig.connection_settings.local_mode_inferred; | ||
} | ||
if (bsConfig.connection_settings.local_inferred) { | ||
obj.local_inferred = bsConfig.connection_settings.local_inferred; | ||
} | ||
if (bsConfig.connection_settings.sync_inferred) { | ||
obj.sync_inferred = bsConfig.connection_settings.sync_inferred; | ||
logger.info('Setting "sync" mode to enable Local testing.'); | ||
} | ||
} | ||
// Local | ||
obj.local = false; | ||
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) obj.local = true; | ||
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`); | ||
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) { | ||
obj.local = true; | ||
} | ||
obj.localMode = null; | ||
// Local Mode | ||
if (obj.local === true && bsConfig.connection_settings.local_mode) { | ||
obj.localMode = bsConfig.connection_settings.local_mode; | ||
if (bsConfig.connection_settings.user_defined_local_mode_warning) { | ||
logger.warn(Constants.userMessages.INVALID_LOCAL_MODE_WARNING); | ||
} | ||
logger.info(`Local testing set up in ${obj.localMode} mode.`); | ||
} | ||
// Local Identifier | ||
@@ -55,5 +82,7 @@ obj.localIdentifier = null; | ||
obj.localIdentifier = bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier; | ||
logger.log(`Local Identifier is set to: ${obj.localIdentifier}`); | ||
logger.info(`Local testing identifier: ${obj.localIdentifier}`); | ||
} | ||
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`); | ||
// Project name | ||
@@ -99,5 +128,5 @@ obj.project = "project-name"; | ||
if (obj.project) logger.log(`Project name is: ${obj.project}`); | ||
if (obj.project) logger.info(`Project name is: ${obj.project}`); | ||
if (obj.customBuildName) logger.log(`Build name is: ${obj.customBuildName}`); | ||
if (obj.customBuildName) logger.info(`Build name is: ${obj.customBuildName}`); | ||
@@ -138,2 +167,12 @@ if (obj.callbackURL) logger.info(`callback url is : ${obj.callbackURL}`); | ||
// validate local args i.e --local-mode and --local-identifier | ||
if( Utils.searchForOption('--local-identifier') && (Utils.isUndefined(args.localIdentifier) || (!Utils.isUndefined(args.localIdentifier) && !args.localIdentifier.trim()))) reject(Constants.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER); | ||
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); | ||
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); | ||
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); | ||
// validate if config file provided exists or not when cypress_config_file provided | ||
@@ -140,0 +179,0 @@ // validate the cypressProjectDir key otherwise. |
@@ -5,3 +5,4 @@ { | ||
"dashboardUrl": "https://automate.browserstack.com/dashboard/v2/builds/", | ||
"usageReportingUrl": "https://eds.browserstack.com:443/send_event_cy_internal" | ||
"usageReportingUrl": "https://eds.browserstack.com:443/send_event_cy_internal", | ||
"localTestingListUrl": "https://www.browserstack.com/local/v1/list" | ||
} |
@@ -40,3 +40,6 @@ let config = require("./config"); | ||
CHECK_DASHBOARD_AT: "Please check the build status at: ", | ||
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" | ||
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", | ||
LOCAL_START_FAILED: "Local Testing setup failed.", | ||
LOCAL_STOP_FAILED: "Local Binary stop failed.", | ||
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" | ||
}; | ||
@@ -61,3 +64,7 @@ | ||
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", | ||
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists." | ||
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists.", | ||
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", | ||
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", | ||
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", | ||
INVALID_LOCAL_IDENTIFIER: "Invalid value specified for local_identifier. For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference" | ||
}; | ||
@@ -99,2 +106,6 @@ | ||
HEADED: "Run your tests in a headed browser instead of a headless browser", | ||
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", | ||
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', | ||
LOCAL_IDENTIFIER: "Accepted values: String - assign an identifier to your Local process instance", | ||
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" | ||
}, | ||
@@ -101,0 +112,0 @@ COMMON: { |
@@ -234,3 +234,4 @@ 'use strict'; | ||
module.exports = { | ||
send | ||
} | ||
send, | ||
cli_version_and_path, | ||
}; |
@@ -6,2 +6,5 @@ "use strict"; | ||
const glob = require('glob'); | ||
const getmac = require('getmac').default; | ||
const { v4: uuidv4 } = require('uuid'); | ||
const browserstack = require('browserstack-local'); | ||
@@ -15,2 +18,4 @@ const usageReporting = require("./usageReporting"), | ||
const request = require('request'); | ||
exports.validateBstackJson = (bsConfigPath) => { | ||
@@ -38,30 +43,42 @@ return new Promise(function (resolve, reject) { | ||
case Constants.validationMessages.EMPTY_BROWSERSTACK_JSON: | ||
errorCode = "bstack_json_invalid_empty"; | ||
errorCode = 'bstack_json_invalid_empty'; | ||
break; | ||
case Constants.validationMessages.INCORRECT_AUTH_PARAMS: | ||
errorCode = "bstack_json_invalid_missing_keys"; | ||
errorCode = 'bstack_json_invalid_missing_keys'; | ||
break; | ||
case Constants.validationMessages.EMPTY_BROWSER_LIST: | ||
errorCode = "bstack_json_invalid_no_browsers"; | ||
errorCode = 'bstack_json_invalid_no_browsers'; | ||
break; | ||
case Constants.validationMessages.EMPTY_RUN_SETTINGS: | ||
errorCode = "bstack_json_invalid_no_run_settings"; | ||
errorCode = 'bstack_json_invalid_no_run_settings'; | ||
break; | ||
case Constants.validationMessages.EMPTY_CYPRESS_PROJ_DIR: | ||
errorCode = "bstack_json_invalid_no_cypress_proj_dir"; | ||
errorCode = 'bstack_json_invalid_no_cypress_proj_dir'; | ||
break; | ||
case Constants.validationMessages.INVALID_DEFAULT_AUTH_PARAMS: | ||
errorCode = "bstack_json_default_auth_keys"; | ||
errorCode = 'bstack_json_default_auth_keys'; | ||
break; | ||
case Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION: | ||
errorCode = "invalid_parallels_specified"; | ||
errorCode = 'invalid_parallels_specified'; | ||
break; | ||
case Constants.validationMessages.INVALID_LOCAL_IDENTIFIER: | ||
errorCode = 'invalid_local_identifier'; | ||
break; | ||
case Constants.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER: | ||
errorCode = 'invalid_local_identifier'; | ||
break; | ||
case Constants.validationMessages.INVALID_LOCAL_MODE: | ||
errorCode = 'invalid_local_mode'; | ||
break; | ||
case Constants.validationMessages.INVALID_LOCAL_CONFIG_FILE: | ||
errorCode = 'invalid_local_config_file'; | ||
break; | ||
case Constants.validationMessages.LOCAL_NOT_SET: | ||
errorCode = "cypress_json_base_url_no_local"; | ||
errorCode = 'cypress_json_base_url_no_local'; | ||
break; | ||
case Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE: | ||
errorCode = "invalid_directory_structure"; | ||
errorCode = 'invalid_directory_structure'; | ||
break; | ||
case Constants.validationMessages.INVALID_CYPRESS_CONFIG_FILE: | ||
errorCode = "invalid_cypress_config_file"; | ||
errorCode = 'invalid_cypress_config_file'; | ||
break; | ||
@@ -253,3 +270,3 @@ } | ||
exports.getUserAgent = () => { | ||
return `BStack-Cypress-CLI/1.5.1 (${os.arch()}/${os.platform()}/${os.release()})`; | ||
return `BStack-Cypress-CLI/1.8.0 (${os.arch()}/${os.platform()}/${os.release()})`; | ||
}; | ||
@@ -318,16 +335,33 @@ | ||
exports.setLocal = (bsConfig) => { | ||
if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { | ||
exports.setLocal = (bsConfig, args) => { | ||
let localInferred = !(this.searchForOption('--local-mode')); | ||
if (!this.isUndefined(args.local)) { | ||
let local = false; | ||
if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") | ||
if (String(args.local).toLowerCase() === 'true') { | ||
local = true; | ||
bsConfig["connection_settings"]["local"] = local; | ||
} | ||
bsConfig['connection_settings']['local'] = local; | ||
} else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { | ||
let local = false; | ||
if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === 'true') { | ||
local = true; | ||
} | ||
bsConfig['connection_settings']['local'] = local; | ||
logger.info( | ||
"Reading local setting from the environment variable BROWSERSTACK_LOCAL" | ||
'Reading local setting from the environment variable BROWSERSTACK_LOCAL' | ||
); | ||
} else if ( | ||
this.isUndefined(bsConfig['connection_settings']['local']) && | ||
( !this.isUndefined(args.localMode) || !this.isUndefined(bsConfig['connection_settings']['local_mode']) ) | ||
) { | ||
bsConfig['connection_settings']['local'] = true; | ||
bsConfig.connection_settings.local_inferred = localInferred; | ||
} | ||
}; | ||
exports.setLocalIdentifier = (bsConfig) => { | ||
if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) { | ||
exports.setLocalIdentifier = (bsConfig, args) => { | ||
if (!this.isUndefined(args.localIdentifier)){ | ||
bsConfig["connection_settings"]["local_identifier"] = args.localIdentifier; | ||
bsConfig['connection_settings']['local_mode'] = "always-on"; | ||
} else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) { | ||
bsConfig["connection_settings"]["local_identifier"] = | ||
@@ -338,5 +372,191 @@ process.env.BROWSERSTACK_LOCAL_IDENTIFIER; | ||
); | ||
bsConfig['connection_settings']['local_mode'] = 'always-on'; | ||
} else if ( | ||
bsConfig['connection_settings']['local'] && | ||
!this.isUndefined(bsConfig["connection_settings"]["local_identifier"]) | ||
){ | ||
bsConfig['connection_settings']['local_mode'] = 'always-on'; | ||
} else if ( | ||
bsConfig['connection_settings']['local'] && | ||
this.isUndefined(bsConfig["connection_settings"]["local_identifier"]) | ||
){ | ||
bsConfig["connection_settings"]["local_identifier"] = this.generateLocalIdentifier(bsConfig['connection_settings']['local_mode']); | ||
} | ||
}; | ||
exports.setLocalMode = (bsConfig, args) => { | ||
if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ | ||
let local_mode = 'on-demand'; | ||
let localModeUndefined= this.isUndefined(bsConfig["connection_settings"]["local_mode"]); | ||
if (!this.isUndefined(args.localMode)) { | ||
if(String(args.localMode) === "always-on"){ | ||
local_mode = 'always-on'; | ||
} | ||
} else if (!localModeUndefined && !["always-on", "on-demand"].includes(bsConfig['connection_settings']['local_mode'])) { | ||
bsConfig.connection_settings.user_defined_local_mode_warning = bsConfig['connection_settings']['local_mode']; | ||
} else if ( | ||
!this.isUndefined(bsConfig['connection_settings']['local_mode']) && | ||
String(bsConfig['connection_settings']['local_mode']).toLowerCase() === | ||
'always-on' | ||
) { | ||
local_mode = 'always-on'; | ||
} | ||
bsConfig['connection_settings']['local_mode'] = local_mode; | ||
if (this.isUndefined(args.sync) || !args.sync ){ | ||
bsConfig['connection_settings']['sync_inferred'] = true; | ||
} | ||
args.sync = true; | ||
let localModeInferred = !(this.searchForOption('--local-mode')); | ||
if (localModeInferred && localModeUndefined) { | ||
bsConfig.connection_settings.local_mode_inferred = local_mode; | ||
} | ||
} | ||
}; | ||
exports.setupLocalTesting = (bsConfig, args) => { | ||
return new Promise(async (resolve, reject) => { | ||
if( bsConfig['connection_settings'] && bsConfig['connection_settings']['local'] && String(bsConfig['connection_settings']['local']) === "true" ){ | ||
let localIdentifierRunning = await this.checkLocalIdentifierRunning( | ||
bsConfig, bsConfig['connection_settings']['local_identifier'] | ||
); | ||
if (!localIdentifierRunning){ | ||
var bs_local = this.getLocalBinary(); | ||
var bs_local_args = this.setLocalArgs(bsConfig, args); | ||
let that = this; | ||
logger.info('Setting up Local testing...'); | ||
bs_local.start(bs_local_args, function (localStartError) { | ||
if (that.isUndefined(localStartError)) { | ||
resolve(bs_local); | ||
} else { | ||
let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, | ||
errorCode = "local_start_error"; | ||
that.sendUsageReport( | ||
bsConfig, | ||
args, | ||
message, | ||
Constants.messageTypes.ERROR, | ||
errorCode | ||
); | ||
reject(Constants.userMessages.LOCAL_START_FAILED); | ||
} | ||
}); | ||
} else { | ||
resolve(); | ||
} | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
}; | ||
exports.stopLocalBinary = (bsConfig, bs_local, args) => { | ||
return new Promise(async (resolve, reject) => { | ||
if(bsConfig['connection_settings'] && bsConfig['connection_settings']['local']){ | ||
let localIdentifierRunning = await this.checkLocalIdentifierRunning(bsConfig,bsConfig["connection_settings"]["local_identifier"]); | ||
if(!localIdentifierRunning){ | ||
let message = `Local Binary not running.`, | ||
errorCode = 'local_identifier_error'; | ||
this.sendUsageReport( | ||
bsConfig, | ||
args, | ||
message, | ||
Constants.messageTypes.ERROR, | ||
errorCode | ||
); | ||
} | ||
} | ||
if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings'] && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { | ||
let that = this; | ||
bs_local.stop(function (localStopError) { | ||
if (that.isUndefined(localStopError)) { | ||
resolve(); | ||
} else { | ||
let message = `name: ${localStopError.name}, message: ${localStopError.message}, extra: ${localStopError.extra}`, | ||
errorCode = 'local_stop_error'; | ||
that.sendUsageReport( | ||
bsConfig, | ||
args, | ||
message, | ||
Constants.messageTypes.ERROR, | ||
errorCode | ||
); | ||
resolve(Constants.userMessages.LOCAL_STOP_FAILED); | ||
} | ||
}); | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
}; | ||
exports.getLocalBinary = () => { | ||
return new browserstack.Local(); | ||
}; | ||
exports.setLocalArgs = (bsConfig, args) => { | ||
let local_args = {} | ||
local_args['key'] = bsConfig['auth']['access_key']; | ||
local_args['localIdentifier'] = bsConfig["connection_settings"]["local_identifier"]; | ||
local_args['daemon'] = true; | ||
local_args['enable-logging-for-api'] = true | ||
local_args['source'] = `cypress:${usageReporting.cli_version_and_path(bsConfig).version}`; | ||
if(!this.isUndefined(bsConfig["connection_settings"]["local_config_file"])){ | ||
local_args['config-file'] = path.resolve(bsConfig["connection_settings"]["local_config_file"]); | ||
} | ||
return local_args; | ||
}; | ||
exports.generateLocalIdentifier = (mode) => { | ||
let local_identifier = undefined; | ||
if(mode == "always-on"){ | ||
local_identifier = getmac(); | ||
} else { | ||
local_identifier = uuidv4(); | ||
} | ||
return Buffer.from(local_identifier).toString("base64"); | ||
}; | ||
exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { | ||
let options = { | ||
url: `${config.localTestingListUrl}?auth_token=${bsConfig.auth.access_key}&state=running`, | ||
auth: { | ||
user: bsConfig.auth.username, | ||
password: bsConfig.auth.access_key, | ||
}, | ||
headers: { | ||
'User-Agent': this.getUserAgent(), | ||
}, | ||
}; | ||
let that = this; | ||
return new Promise ( function(resolve, reject) { | ||
request.get(options, function (err, resp, body) { | ||
if(err){ | ||
reject(err); | ||
} | ||
let response = JSON.parse(body); | ||
let localInstances = []; | ||
if(!that.isUndefined(response['instances'])){ | ||
localInstances = response['instances']; | ||
} | ||
let localIdentifiers = []; | ||
localInstances.forEach(function(instance){ | ||
localIdentifiers.push(instance['localIdentifier']); | ||
}); | ||
resolve(localIdentifiers.includes(localIdentifier)); | ||
}); | ||
}); | ||
}; | ||
exports.setLocalConfigFile = (bsConfig, args) => { | ||
if(!this.isUndefined(args.localConfigFile)){ | ||
bsConfig['connection_settings']['local_config_file'] = args.localConfigFile; | ||
} | ||
}; | ||
exports.setHeaded = (bsConfig, args) => { | ||
@@ -350,8 +570,12 @@ if (!this.isUndefined(args.headed) && args.headed === true) { | ||
let testFolderPath = cypressJson.integrationFolder || Constants.DEFAULT_CYPRESS_SPEC_PATH; | ||
let globSearchPatttern = bsConfig.run_settings.specs || `${testFolderPath}/**/*.+(${Constants.specFileTypes.join("|")})`; | ||
let globSearchPattern = this.sanitizeSpecsPattern(bsConfig.run_settings.specs) || `${testFolderPath}/**/*.+(${Constants.specFileTypes.join("|")})`; | ||
let ignoreFiles = args.exclude || bsConfig.run_settings.exclude; | ||
let files = glob.sync(globSearchPatttern, {cwd: bsConfig.run_settings.cypressProjectDir, matchBase: true, ignore: ignoreFiles}); | ||
let files = glob.sync(globSearchPattern, {cwd: bsConfig.run_settings.cypressProjectDir, matchBase: true, ignore: ignoreFiles}); | ||
return files; | ||
}; | ||
exports.sanitizeSpecsPattern = (pattern) => { | ||
return pattern && pattern.split(",").length > 1 ? "{" + pattern + "}" : pattern; | ||
} | ||
exports.getBrowserCombinations = (bsConfig) => { | ||
@@ -408,2 +632,6 @@ let osBrowserArray = []; | ||
if( err === Constants.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER || err === Constants.validationMessages.INVALID_LOCAL_MODE ){ | ||
return false | ||
} | ||
return invalid | ||
@@ -410,0 +638,0 @@ } |
@@ -40,6 +40,10 @@ 'use strict'; | ||
if (resp.statusCode != 200) { | ||
if (responseData && responseData["error"]) { | ||
if(responseData && responseData["error"]){ | ||
reject(responseData["error"]); | ||
} else { | ||
reject(Constants.userMessages.ZIP_UPLOADER_NOT_REACHABLE); | ||
if(resp.statusCode == 401){ | ||
reject(Constants.validationMessages.INVALID_DEFAULT_AUTH_PARAMS); | ||
} else { | ||
reject(Constants.userMessages.ZIP_UPLOADER_NOT_REACHABLE); | ||
} | ||
} | ||
@@ -46,0 +50,0 @@ } else { |
@@ -208,2 +208,18 @@ #!/usr/bin/env node | ||
type: "boolean" | ||
}, | ||
'local': { | ||
describe: Constants.cliMessages.RUN.LOCAL, | ||
type: "boolean" | ||
}, | ||
'local-identifier': { | ||
describe: Constants.cliMessages.RUN.LOCAL_IDENTIFIER, | ||
type: "string" | ||
}, | ||
'local-mode': { | ||
describe: Constants.cliMessages.RUN.LOCAL_MODE, | ||
type: "string" | ||
}, | ||
'local-config-file': { | ||
describe: Constants.cliMessages.RUN.LOCAL_CONFIG_FILE, | ||
type: "string" | ||
} | ||
@@ -210,0 +226,0 @@ }) |
@@ -68,3 +68,5 @@ module.exports = function () { | ||
"local": false, | ||
"local_identifier": null | ||
"local_identifier": null, | ||
"local_mode": null, | ||
"local_config_file": null | ||
}, | ||
@@ -71,0 +73,0 @@ "disable_usage_reporting": false |
{ | ||
"name": "browserstack-cypress-cli", | ||
"version": "1.7.1", | ||
"version": "1.8.0", | ||
"description": "BrowserStack Cypress CLI for Cypress integration with BrowserStack's remote devices.", | ||
@@ -17,4 +17,6 @@ "main": "index.js", | ||
"async": "^3.2.0", | ||
"browserstack-local": "^1.4.8", | ||
"chalk": "^4.1.0", | ||
"fs-extra": "^8.1.0", | ||
"getmac": "^5.17.0", | ||
"glob": "^7.1.6", | ||
@@ -25,4 +27,5 @@ "mkdirp": "^1.0.3", | ||
"table": "^5.4.6", | ||
"uuid": "^8.3.2", | ||
"winston": "^2.3.1", | ||
"yargs": "^14.2.2" | ||
"yargs": "^14.2.3" | ||
}, | ||
@@ -29,0 +32,0 @@ "repository": { |
@@ -8,3 +8,3 @@ const chai = require("chai"), | ||
testObjects = require("../../support/fixtures/testObjects"); | ||
const { setHeaded } = require("../../../../bin/helpers/utils"); | ||
const { setHeaded, setupLocalTesting, stopLocalBinary, setUserSpecs, setLocalConfigFile } = require("../../../../bin/helpers/utils"); | ||
@@ -95,2 +95,3 @@ const proxyquire = require("proxyquire").noCallThru(); | ||
getConfigPathStub = sandbox.stub(); | ||
setupLocalTestingStub = sandbox.stub(); | ||
setUsageReportingFlagStub = sandbox.stub().returns(undefined); | ||
@@ -107,2 +108,4 @@ sendUsageReportStub = sandbox.stub().callsFake(function () { | ||
setDefaultsStub = sandbox.stub(); | ||
setLocalModeStub = sandbox.stub(); | ||
setLocalConfigFileStub = sandbox.stub(); | ||
}); | ||
@@ -138,6 +141,9 @@ | ||
setDefaults: setDefaultsStub, | ||
isJSONInvalid: isJSONInvalidStub | ||
setupLocalTesting: setupLocalTestingStub, | ||
isJSONInvalid: isJSONInvalidStub, | ||
setLocalMode: setLocalModeStub, | ||
setLocalConfigFile: setLocalConfigFileStub | ||
}, | ||
'../helpers/capabilityHelper': { | ||
validate: capabilityValidatorStub, | ||
validate: capabilityValidatorStub | ||
}, | ||
@@ -147,2 +153,3 @@ }); | ||
validateBstackJsonStub.returns(Promise.resolve(bsConfig)); | ||
setupLocalTestingStub.returns(Promise.resolve("return nothing")); | ||
capabilityValidatorStub.returns(Promise.reject("random-error")); | ||
@@ -157,11 +164,19 @@ | ||
sinon.assert.calledOnce(getConfigPathStub); | ||
sinon.assert.calledOnce(deleteResultsStub); | ||
sinon.assert.calledOnce(validateBstackJsonStub); | ||
sinon.assert.calledOnce(setDefaultsStub); | ||
sinon.assert.calledOnce(setUsernameStub); | ||
sinon.assert.calledOnce(setAccessKeyStub); | ||
sinon.assert.calledOnce(setBuildNameStub); | ||
sinon.assert.calledOnce(setCypressConfigFilenameStub); | ||
sinon.assert.calledOnce(setUserSpecsStub); | ||
sinon.assert.calledOnce(setTestEnvsStub); | ||
sinon.assert.calledOnce(setLocalStub); | ||
sinon.assert.calledOnce(setLocalModeStub); | ||
sinon.assert.calledOnce(setLocalConfigFileStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(capabilityValidatorStub); | ||
sinon.assert.calledOnce(setUsageReportingFlagStub); | ||
sinon.assert.calledOnce(getErrorCodeFromMsgStub); | ||
sinon.assert.calledOnce(setLocalStub); | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(deleteResultsStub); | ||
sinon.assert.calledOnce(setDefaultsStub); | ||
sinon.assert.calledOnce(setUsageReportingFlagStub); | ||
sinon.assert.calledOnceWithExactly( | ||
@@ -201,2 +216,4 @@ sendUsageReportStub, | ||
setLocalStub = sandbox.stub(); | ||
setLocalModeStub = sandbox.stub(); | ||
setupLocalTestingStub = sandbox.stub(); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
@@ -207,2 +224,3 @@ setHeadedStub = sandbox.stub(); | ||
setDefaultsStub = sandbox.stub(); | ||
setLocalConfigFileStub = sandbox.stub(); | ||
}); | ||
@@ -234,2 +252,4 @@ | ||
setLocal: setLocalStub, | ||
setLocalMode: setLocalModeStub, | ||
setupLocalTesting: setupLocalTestingStub, | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
@@ -239,3 +259,4 @@ setHeaded: setHeadedStub, | ||
setDefaults: setDefaultsStub, | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
setLocalConfigFile: setLocalConfigFileStub | ||
}, | ||
@@ -254,2 +275,3 @@ '../helpers/capabilityHelper': { | ||
validateBstackJsonStub.returns(Promise.resolve(bsConfig)); | ||
setupLocalTestingStub.returns(Promise.resolve("nothing")) | ||
capabilityValidatorStub.returns(Promise.resolve(Constants.validationMessages.VALIDATED)); | ||
@@ -265,2 +287,8 @@ archiverStub.returns(Promise.reject("random-error")); | ||
sinon.assert.calledOnce(getConfigPathStub); | ||
sinon.assert.calledOnce(setLocalModeStub); | ||
sinon.assert.calledOnce(setUsernameStub); | ||
sinon.assert.calledOnce(setAccessKeyStub); | ||
sinon.assert.calledOnce(setBuildNameStub); | ||
sinon.assert.calledOnce(setLocalConfigFileStub); | ||
sinon.assert.calledOnce(setCypressConfigFilenameStub); | ||
sinon.assert.calledOnce(getNumberOfSpecFilesStub); | ||
@@ -313,2 +341,4 @@ sinon.assert.calledOnce(setParallelsStub); | ||
setLocalStub = sandbox.stub(); | ||
setLocalModeStub = sandbox.stub(); | ||
setupLocalTestingStub = sandbox.stub(); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
@@ -319,2 +349,3 @@ setHeadedStub = sandbox.stub(); | ||
setDefaultsStub = sandbox.stub(); | ||
setLocalConfigFileStub = sandbox.stub(); | ||
}); | ||
@@ -346,2 +377,4 @@ | ||
setLocal: setLocalStub, | ||
setLocalMode: setLocalModeStub, | ||
setupLocalTesting: setupLocalTestingStub, | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
@@ -351,3 +384,4 @@ setHeaded: setHeadedStub, | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
setDefaults: setDefaultsStub | ||
setDefaults: setDefaultsStub, | ||
setLocalConfigFile: setLocalConfigFileStub | ||
}, | ||
@@ -370,2 +404,3 @@ '../helpers/capabilityHelper': { | ||
capabilityValidatorStub.returns(Promise.resolve(Constants.validationMessages.VALIDATED)); | ||
setupLocalTestingStub.returns(Promise.resolve("nothing")); | ||
archiverStub.returns(Promise.resolve("Zipping completed")); | ||
@@ -381,2 +416,4 @@ zipUploadStub.returns(Promise.reject("random-error")); | ||
sinon.assert.calledOnce(getConfigPathStub); | ||
sinon.assert.calledOnce(setLocalModeStub); | ||
sinon.assert.calledOnce(setLocalConfigFileStub); | ||
sinon.assert.calledOnce(getNumberOfSpecFilesStub); | ||
@@ -433,2 +470,4 @@ sinon.assert.calledOnce(setParallelsStub); | ||
setLocalStub = sandbox.stub(); | ||
setLocalModeStub = sandbox.stub(); | ||
setupLocalTestingStub = sandbox.stub(); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
@@ -439,2 +478,4 @@ setHeadedStub = sandbox.stub(); | ||
setDefaultsStub = sandbox.stub(); | ||
stopLocalBinaryStub = sandbox.stub(); | ||
setLocalConfigFileStub = sandbox.stub(); | ||
}); | ||
@@ -466,2 +507,4 @@ | ||
setLocal: setLocalStub, | ||
setLocalMode: setLocalModeStub, | ||
setupLocalTesting: setupLocalTestingStub, | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
@@ -471,3 +514,5 @@ setHeaded: setHeadedStub, | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
setDefaults: setDefaultsStub | ||
setDefaults: setDefaultsStub, | ||
stopLocalBinary: stopLocalBinaryStub, | ||
setLocalConfigFile: setLocalConfigFileStub | ||
}, | ||
@@ -492,2 +537,3 @@ '../helpers/capabilityHelper': { | ||
validateBstackJsonStub.returns(Promise.resolve(bsConfig)); | ||
setupLocalTestingStub.returns(Promise.resolve("nothing")); | ||
capabilityValidatorStub.returns( | ||
@@ -498,2 +544,3 @@ Promise.resolve(Constants.validationMessages.VALIDATED) | ||
zipUploadStub.returns(Promise.resolve("zip uploaded")); | ||
stopLocalBinaryStub.returns(Promise.resolve("nothing")); | ||
createBuildStub.returns(Promise.reject("random-error")); | ||
@@ -508,2 +555,5 @@ | ||
sinon.assert.calledOnce(getConfigPathStub); | ||
sinon.assert.calledOnce(setLocalConfigFileStub); | ||
sinon.assert.calledOnce(setLocalModeStub); | ||
sinon.assert.calledOnce(setupLocalTestingStub); | ||
sinon.assert.calledOnce(validateBstackJsonStub); | ||
@@ -567,5 +617,8 @@ sinon.assert.calledOnce(capabilityValidatorStub); | ||
setLocalStub = sandbox.stub(); | ||
setLocalModeStub = sandbox.stub(); | ||
setupLocalTestingStub = sandbox.stub(); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
getNumberOfSpecFilesStub = sandbox.stub().returns([]); | ||
setLocalConfigFileStub = sandbox.stub(); | ||
}); | ||
@@ -598,2 +651,4 @@ | ||
setLocal: setLocalStub, | ||
setLocalMode: setLocalModeStub, | ||
setupLocalTesting: setupLocalTestingStub, | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
@@ -605,3 +660,4 @@ setHeaded: setHeadedStub, | ||
isUndefined: isUndefinedStub, | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub | ||
getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
setLocalConfigFile: setLocalConfigFileStub | ||
}, | ||
@@ -629,2 +685,3 @@ '../helpers/capabilityHelper': { | ||
validateBstackJsonStub.returns(Promise.resolve(bsConfig)); | ||
setupLocalTestingStub.returns(Promise.resolve("nothing")); | ||
capabilityValidatorStub.returns( | ||
@@ -645,2 +702,3 @@ Promise.resolve(Constants.validationMessages.VALIDATED) | ||
sinon.assert.calledOnce(validateBstackJsonStub); | ||
sinon.assert.calledOnce(setLocalConfigFileStub); | ||
sinon.assert.calledOnce(capabilityValidatorStub); | ||
@@ -650,2 +708,4 @@ sinon.assert.calledOnce(getNumberOfSpecFilesStub); | ||
sinon.assert.calledOnce(setLocalStub); | ||
sinon.assert.calledOnce(setLocalModeStub); | ||
sinon.assert.calledOnce(setupLocalTestingStub); | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
@@ -652,0 +712,0 @@ sinon.assert.calledOnce(setHeadedStub); |
'use strict'; | ||
const path = require('path'); | ||
var sandbox = require('sinon').createSandbox(); | ||
const request = require('request'); | ||
const chai = require('chai'), | ||
@@ -11,3 +13,4 @@ expect = chai.expect, | ||
fs = require('fs'); | ||
const getmac = require('getmac').default; | ||
const usageReporting = require('../../../../bin/helpers/usageReporting'); | ||
const utils = require('../../../../bin/helpers/utils'), | ||
@@ -18,3 +21,3 @@ constant = require('../../../../bin/helpers/constants'), | ||
syncLogger = require("../../../../bin/helpers/logger").syncCliLogger; | ||
const browserstack = require('browserstack-local'); | ||
chai.use(chaiAsPromised); | ||
@@ -78,2 +81,27 @@ logger.transports['console.info'].silent = true; | ||
).to.eq('bstack_json_path_invalid'); | ||
expect( | ||
utils.getErrorCodeFromMsg( | ||
constant.validationMessages.INVALID_LOCAL_IDENTIFIER | ||
) | ||
).to.eq('invalid_local_identifier'); | ||
expect( | ||
utils.getErrorCodeFromMsg( | ||
constant.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER | ||
) | ||
).to.eq('invalid_local_identifier'); | ||
expect( | ||
utils.getErrorCodeFromMsg( | ||
constant.validationMessages.INVALID_LOCAL_MODE | ||
) | ||
).to.eq('invalid_local_mode'); | ||
expect( | ||
utils.getErrorCodeFromMsg( | ||
constant.validationMessages.INVALID_LOCAL_CONFIG_FILE | ||
) | ||
).to.eq('invalid_local_config_file'); | ||
expect( | ||
utils.getErrorCodeFromMsg( | ||
"Invalid browserstack.json file." | ||
) | ||
).to.eq("bstack_json_invalid"); | ||
}); | ||
@@ -336,3 +364,2 @@ }); | ||
it('should call sendUsageReport', () => { | ||
let sandbox = sinon.createSandbox(); | ||
sendUsageReportStub = sandbox | ||
@@ -345,2 +372,4 @@ .stub(utils, 'sendUsageReport') | ||
sinon.assert.calledOnce(sendUsageReportStub); | ||
sandbox.restore(); | ||
sinon.restore(); | ||
}); | ||
@@ -650,8 +679,19 @@ }); | ||
describe('setLocal', () => { | ||
beforeEach(function () { | ||
afterEach(function () { | ||
sinon.restore(); | ||
delete process.env.BROWSERSTACK_LOCAL; | ||
}); | ||
afterEach(function () { | ||
delete process.env.BROWSERSTACK_LOCAL; | ||
it('bsconfig connection_settings local_inferred as true if serachforOption returns false with args local-mode true', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
} | ||
}; | ||
let args = { | ||
localMode: "always-on" | ||
}; | ||
let searchForOptionStub = sinon.stub(utils,"searchForOption"); | ||
searchForOptionStub.returns(false); | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_inferred).to.be.eq(true); | ||
}); | ||
@@ -665,6 +705,20 @@ | ||
}; | ||
utils.setLocal(bsConfig); | ||
let args = {}; | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local).to.be.eq(true); | ||
}); | ||
it('should change local to true in bsConfig if process.env.BROWSERSTACK_LOCAL is set to true', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: false, | ||
}, | ||
}; | ||
let args = { | ||
}; | ||
process.env.BROWSERSTACK_LOCAL = true; | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local).to.be.eq(true); | ||
}); | ||
it('should change local to false in bsConfig if process.env.BROWSERSTACK_LOCAL is set to false', () => { | ||
@@ -676,4 +730,5 @@ let bsConfig = { | ||
}; | ||
let args = {}; | ||
process.env.BROWSERSTACK_LOCAL = false; | ||
utils.setLocal(bsConfig); | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local).to.be.eq(false); | ||
@@ -688,13 +743,16 @@ }); | ||
}; | ||
let args = {}; | ||
process.env.BROWSERSTACK_LOCAL = true; | ||
utils.setLocal(bsConfig); | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local).to.be.eq(true); | ||
}); | ||
it('should set local to true in bsConfig if process.env.BROWSERSTACK_LOCAL is set to true & local is not set in bsConfig', () => { | ||
it('should set local to true in bsConfig if args is set to true & local is not set in bsConfig', () => { | ||
let bsConfig = { | ||
connection_settings: {}, | ||
}; | ||
process.env.BROWSERSTACK_LOCAL = true; | ||
utils.setLocal(bsConfig); | ||
let args = { | ||
local: true | ||
} | ||
utils.setLocal(bsConfig,args); | ||
expect(bsConfig.connection_settings.local).to.be.eq(true); | ||
@@ -704,2 +762,325 @@ }); | ||
describe('setLocalMode', () => { | ||
afterEach(() =>{ | ||
sinon.restore(); | ||
}) | ||
it('if bsconfig local is true and args localMode is always-on then local_mode should be always-on' , () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true, | ||
local_mode: "on-demand" | ||
}, | ||
}; | ||
let args = { | ||
localMode: "always-on" | ||
}; | ||
utils.setLocalMode(bsConfig,args); | ||
expect(bsConfig['connection_settings']['local_mode']).to.be.eq("always-on"); | ||
}); | ||
it('if bsconfig local mode is not always-on then local_mode should be on-demand', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true, | ||
}, | ||
}; | ||
let args = {}; | ||
utils.setLocalMode(bsConfig,args); | ||
expect(bsConfig['connection_settings']['local_mode']).to.be.eq("on-demand"); | ||
}); | ||
it('setLocalMode should end up setting args.sync and sync_inferred as true', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true | ||
}, | ||
}; | ||
let args = { | ||
localMode: "always-on" | ||
} | ||
utils.setLocalMode(bsConfig,args); | ||
expect(args.sync).to.be.eq(true); | ||
expect(bsConfig.connection_settings.sync_inferred).to.be.eq(true); | ||
}); | ||
it('if local_mode is not provided then the bsConfig local_mode_inferred changes to local_mode', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true | ||
}, | ||
}; | ||
let args = { | ||
} | ||
let searchForOptionStub = sinon.stub(utils,"searchForOption"); | ||
searchForOptionStub.returns(false); | ||
utils.setLocalMode(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_mode_inferred).to.be.eq("on-demand"); | ||
}); | ||
it('if local_mode is provided then the bsConfig local_mode_inferred remains unchanged', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true, | ||
local_mode: "always-on" | ||
}, | ||
}; | ||
let args = { | ||
} | ||
let searchForOptionStub = sinon.stub(utils,"searchForOption"); | ||
searchForOptionStub.returns(true); | ||
utils.setLocalMode(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_mode_inferred).to.be.undefined; | ||
}); | ||
}); | ||
describe('setupLocalTesting' ,() => { | ||
beforeEach(function () { | ||
sinon.restore(); | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sinon.restore(); | ||
sandbox.restore(); | ||
}); | ||
it('if local is true and localIdentifier is not running and start error is raised', () => { | ||
let bsConfig = { | ||
auth: { | ||
access_key: "xyz" | ||
}, | ||
connection_settings: { | ||
local: true, | ||
local_identifier: "xyz" | ||
}, | ||
}; | ||
let args = {}; | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); | ||
let setLocalArgsStub = sinon.stub(utils,"setLocalArgs"); | ||
setLocalArgsStub.returns({}); | ||
let localBinaryStartStub = sandbox.stub().yields( | ||
'Key is required to start local testing!' | ||
); | ||
let getLocalBinaryStub = sandbox.stub(utils, 'getLocalBinary').returns({ | ||
start: localBinaryStartStub | ||
}); | ||
let sendUsageReportStub = sandbox | ||
.stub(utils, 'sendUsageReport') | ||
.callsFake(function () { | ||
return 'end'; | ||
}); | ||
utils.setupLocalTesting(bsConfig,args).catch((error) => { | ||
expect(error).to.eq(constant.userMessages.LOCAL_START_FAILED); | ||
sinon.assert.calledOnce(sendUsageReportStub); | ||
sinon.assert.calledOnce(getLocalBinaryStub); | ||
}); | ||
}); | ||
it('if local is true and localIdentifier is not running and start error is not raised', () => { | ||
let bsConfig = { | ||
auth: { | ||
access_key: 'xyz', | ||
}, | ||
connection_settings: { | ||
local: true, | ||
local_identifier: 'xyz', | ||
}, | ||
}; | ||
let args = {}; | ||
let localArgs = { | ||
key: 'abc', | ||
localIdentifier: 'abc', | ||
daemon: true, | ||
}; | ||
let checkLocalIdentifierRunningStub = sinon.stub( | ||
utils, | ||
'checkLocalIdentifierRunning' | ||
); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); | ||
let setLocalArgsStub = sinon.stub(utils, 'setLocalArgs'); | ||
setLocalArgsStub.returns(localArgs); | ||
let localBinaryStartStub = sandbox.stub().yields(undefined); | ||
let getLocalBinaryStub = sandbox.stub(utils, 'getLocalBinary').returns({ | ||
start: localBinaryStartStub, | ||
}); | ||
let sendUsageReportStub = sandbox | ||
.stub(utils, 'sendUsageReport') | ||
.callsFake(function () { | ||
return 'end'; | ||
}); | ||
utils.setupLocalTesting(bsConfig, args).catch((result) => { | ||
expect(result).to.eq(undefined); | ||
sinon.assert.calledOnce(getLocalBinaryStub); | ||
}); | ||
}); | ||
it('if bsconfig local is true then promise should return a browserstack local object', () => { | ||
let bsConfig = { | ||
auth: { | ||
access_key: "xyz" | ||
}, | ||
connection_settings: { | ||
local: true, | ||
local_identifier: "xyz" | ||
}, | ||
}; | ||
let args = {}; | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); | ||
return utils.setupLocalTesting(bsConfig,args).then((result) => { | ||
expect(result).to.be.eq(undefined); | ||
}); | ||
}); | ||
}); | ||
describe('setLocalArgs', () => { | ||
it('setting up local args and returning a local_args hash', () => { | ||
let bsConfig = { | ||
auth: { | ||
access_key: "xyz" | ||
}, | ||
connection_settings: { | ||
local: true, | ||
local_identifier: "on-demand", | ||
local_config_file: "./local.yml" | ||
}, | ||
}; | ||
let args = {}; | ||
let cliVersionPathStub = sinon.stub(usageReporting, "cli_version_and_path").withArgs(bsConfig); | ||
cliVersionPathStub.returns("abc"); | ||
let local_args = utils.setLocalArgs(bsConfig, args); | ||
expect(local_args["key"]).to.be.eq(bsConfig['auth']['access_key']); | ||
expect(local_args["localIdentifier"]).to.be.eq(bsConfig["connection_settings"]["local_identifier"]); | ||
expect(local_args["daemon"]).to.be.eq(true); | ||
expect(local_args["enable-logging-for-api"]).to.be.eq(true); | ||
expect(local_args['config-file']).to.be.eq(path.resolve('./local.yml')); | ||
sinon.restore(); | ||
}); | ||
}); | ||
describe('stopLocalBinary' , () => { | ||
afterEach(function () { | ||
sinon.restore(); | ||
sandbox.restore(); | ||
}); | ||
it('stopLocalBinary promise gets resolve with undefined' ,() => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true | ||
} | ||
}; | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); | ||
let sendUsageReportStub = sandbox | ||
.stub(utils, 'sendUsageReport') | ||
.callsFake(function () { | ||
return 'end'; | ||
}); | ||
return utils.stopLocalBinary(bsConfig).then((result) => { | ||
expect(result).to.be.eq(undefined); | ||
sinon.assert.calledOnce(sendUsageReportStub); | ||
}); | ||
}); | ||
it('stopLocalBinary promise resolves with undefined if the bs_local isRunning is false' ,() => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_mode: "on-demand" | ||
} | ||
}; | ||
let isRunningStub = sandbox.stub().returns(false); | ||
let bs_local = { | ||
isRunning: isRunningStub, | ||
}; | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); | ||
return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { | ||
expect(result).to.be.eq(undefined); | ||
}); | ||
}); | ||
it('if the bs_local isRunning is true and local_mode is always-on, then gets resolve with undefined' ,() => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_mode: "always-on" | ||
} | ||
}; | ||
let isRunningStub = sandbox.stub().returns(true); | ||
let bs_local = { | ||
isRunning: isRunningStub, | ||
} | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); | ||
return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { | ||
expect(result).to.be.eq(undefined); | ||
}); | ||
}); | ||
it('if the bs_local isRunning is true and local_mode is not always-on and there is no stop error, then gets resolve with undefined' ,() => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_mode: "on-demand" | ||
} | ||
}; | ||
let isRunningStub = sandbox.stub().returns(true); | ||
let stopStub = sandbox.stub().yields(undefined); | ||
let bs_local = { | ||
isRunning: isRunningStub, | ||
stop: stopStub | ||
} | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); | ||
return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { | ||
expect(result).to.be.eq(undefined); | ||
}); | ||
}); | ||
it('if the bs_local isRunning is true and local_mode is not always-on and there is stop error, then gets resolve with stop error' ,() => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_mode: "on-demand" | ||
} | ||
}; | ||
let isRunningStub = sandbox.stub().returns(true); | ||
let error = new Error('Local Stop Error'); | ||
let stopStub = sandbox.stub().yields(error); | ||
let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); | ||
checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); | ||
let bs_local = { | ||
isRunning: isRunningStub, | ||
stop: stopStub | ||
} | ||
let sendUsageReportStub = sandbox | ||
.stub(utils, 'sendUsageReport') | ||
.callsFake(function () { | ||
return 'end'; | ||
}); | ||
return utils.stopLocalBinary(bsConfig, bs_local, {}).then((result) => { | ||
expect(result).to.be.eq(constant.userMessages.LOCAL_STOP_FAILED); | ||
sinon.assert.calledOnce(sendUsageReportStub); | ||
sinon.assert.calledOnce(stopStub); | ||
}); | ||
}); | ||
}); | ||
describe('generateLocalIdentifier', () => { | ||
it('if the mode is always-on it returns getmac() as local-identifier', () => { | ||
expect(utils.generateLocalIdentifier("always-on")).to.be.eq(Buffer.from(getmac()).toString("base64")); | ||
}); | ||
it('if the mode is not always-on it returns random uuidv4 as local-identifier', () => { | ||
let uuidv41 = utils.generateLocalIdentifier("abc"); | ||
let uuidv42 = utils.generateLocalIdentifier("abc"); | ||
expect(uuidv41 != uuidv42).to.be.eq(true); | ||
}); | ||
}); | ||
describe('setLocalIdentifier', () => { | ||
@@ -713,11 +1094,14 @@ beforeEach(function () { | ||
}); | ||
it('should not change local identifier in bsConfig if process.env.BROWSERSTACK_LOCAL_IDENTIFIER is undefined', () => { | ||
it('should generate local_identifier if args.localIdentifier & process.env.BROWSERSTACK_LOCAL_IDENTIFIER is undefined', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_identifier: 'local_identifier', | ||
local: true | ||
}, | ||
}; | ||
utils.setLocalIdentifier(bsConfig); | ||
let args = {}; | ||
let generateLocalIdentifierStub = sinon.stub(utils,"generateLocalIdentifier"); | ||
generateLocalIdentifierStub.returns("abc"); | ||
utils.setLocalIdentifier(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_identifier).to.be.eq( | ||
'local_identifier' | ||
"abc" | ||
); | ||
@@ -732,4 +1116,5 @@ }); | ||
}; | ||
let args = {}; | ||
process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; | ||
utils.setLocalIdentifier(bsConfig); | ||
utils.setLocalIdentifier(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_identifier).to.be.eq( | ||
@@ -744,4 +1129,5 @@ 'local_identifier' | ||
}; | ||
let args = {}; | ||
process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; | ||
utils.setLocalIdentifier(bsConfig); | ||
utils.setLocalIdentifier(bsConfig,args); | ||
expect(bsConfig.connection_settings.local_identifier).to.be.eq( | ||
@@ -751,2 +1137,30 @@ 'local_identifier' | ||
}); | ||
it('if args localIdentifier is defined then it gets assigned to bsConfig connection_settings local_identifier' , () => { | ||
let bsConfig = { | ||
local: true, | ||
connection_settings: { | ||
local_identifier: "abc" | ||
} | ||
}; | ||
let args = { | ||
localIdentifier: "xyz" | ||
}; | ||
utils.setLocalIdentifier(bsConfig, args); | ||
expect(bsConfig.connection_settings.local_identifier).to.be.eq("xyz"); | ||
expect(bsConfig.connection_settings.local_mode).to.be.eq('always-on'); | ||
}); | ||
it('if localIdentifier is defined then local_mode is set to always-on' , () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local: true, | ||
local_identifier: 'abc', | ||
}, | ||
}; | ||
let args = {} | ||
utils.setLocalIdentifier(bsConfig, args); | ||
expect(bsConfig.connection_settings.local_identifier).to.be.eq("abc"); | ||
expect(bsConfig['connection_settings']['local_mode']).to.be.eq('always-on'); | ||
}); | ||
}); | ||
@@ -923,2 +1337,6 @@ | ||
afterEach(function(){ | ||
sinon.restore(); | ||
}); | ||
it('has user provided ccf flag', () => { | ||
@@ -1107,2 +1525,17 @@ ccfBool = true; | ||
describe('sanitizeSpecsPattern', () => { | ||
it('should wrap pattern around {} when input is csv', () => { | ||
expect(utils.sanitizeSpecsPattern("pattern1,pattern2")).to.eq("{pattern1,pattern2}"); | ||
}); | ||
it('should not wrap pattern around {} when input is single glob pattern', () => { | ||
expect(utils.sanitizeSpecsPattern("pattern3")).to.eq("pattern3"); | ||
}); | ||
it('should return undefined when --spec is undefined', () => { | ||
expect(utils.sanitizeSpecsPattern(undefined)).to.eq(undefined); | ||
}); | ||
}); | ||
describe('getBrowserCombinations', () => { | ||
@@ -1208,2 +1641,12 @@ | ||
}); | ||
it('JSON is invalid if local identifier is invalid', () =>{ | ||
let error = constant.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER; | ||
expect(utils.isJSONInvalid(error,{})).to.eq(false); | ||
}); | ||
it('JSON is invalid if local mode is invalid', () =>{ | ||
let error = constant.validationMessages.INVALID_LOCAL_MODE; | ||
expect(utils.isJSONInvalid(error,{})).to.eq(false); | ||
}); | ||
}) | ||
@@ -1222,2 +1665,97 @@ | ||
}); | ||
describe('#checkLocalIdentifierRunning', () => { | ||
afterEach(() =>{ | ||
sinon.restore(); | ||
}); | ||
it('if the bsConfig localIdentifier is not present within the response body then function should resolve with false' , () => { | ||
const responseObject = { | ||
statusCode: 200, | ||
headers: { | ||
'content-type': 'application/json' | ||
} | ||
}; | ||
const responseBody = { | ||
status: 'success', | ||
instances: [ | ||
{ | ||
localIdentifier: 'abcdef', | ||
}, | ||
{ | ||
localIdentifier: 'ghij', | ||
}, | ||
{ | ||
localIdentifier: 'lmno', | ||
} | ||
] | ||
}; | ||
sinon.stub(request, 'get') | ||
.yields(undefined, responseObject, JSON.stringify(responseBody)); | ||
let bsConfig = { | ||
auth: { | ||
access_key: "abcd", | ||
username: "abcd" | ||
} | ||
}; | ||
let localIdentifier = "abcd"; | ||
return utils.checkLocalIdentifierRunning(bsConfig, localIdentifier).then((result) => { | ||
expect(result).to.be.eq(false); | ||
}); | ||
}); | ||
it('if the bsConfig localIdentifier if present within the response body then the function should resolve with true' , () => { | ||
const responseObject = { | ||
statusCode: 200, | ||
headers: { | ||
'content-type': 'application/json' | ||
} | ||
}; | ||
const responseBody = { | ||
status: 'success', | ||
instances: [ | ||
{ | ||
localIdentifier: 'abcdef', | ||
}, | ||
{ | ||
localIdentifier: 'ghij', | ||
}, | ||
{ | ||
localIdentifier: 'lmno', | ||
} | ||
] | ||
}; | ||
sinon.stub(request, 'get') | ||
.yields(undefined, responseObject, JSON.stringify(responseBody)); | ||
let bsConfig = { | ||
auth: { | ||
access_key: "abcd", | ||
username: "abcd" | ||
} | ||
}; | ||
let localIdentifier = "lmno"; | ||
return utils.checkLocalIdentifierRunning(bsConfig, localIdentifier).then((result) => { | ||
expect(result).to.be.eq(true); | ||
}); | ||
}); | ||
}); | ||
describe('setLocalConfigFile', () => { | ||
it('the args localConfigfile should be assigned to bsconfig connection_settigs local_config_file', () => { | ||
let bsConfig = { | ||
connection_settings: { | ||
local_config_file: "efgh" | ||
} | ||
}; | ||
let args = { | ||
localConfigFile: "abcd" | ||
}; | ||
utils.setLocalConfigFile(bsConfig, args); | ||
expect(args.localConfigFile).to.be.eql(bsConfig.connection_settings.local_config_file); | ||
}); | ||
}); | ||
}); |
@@ -58,3 +58,3 @@ const chai = require("chai"), | ||
it("reject with error (if error present in response) if statusCode != 200", () => { | ||
it("reject with error (if error present in response) if statusCode == 401", () => { | ||
let error = "non 200 code"; | ||
@@ -86,3 +86,3 @@ | ||
it("reject with message if statusCode != 200 and error not in response", () => { | ||
it("reject with message if statusCode == 401 and error not in response", () => { | ||
let requestStub = sandbox | ||
@@ -114,2 +114,61 @@ .stub(request, "post") | ||
error, | ||
Constants.validationMessages.INVALID_DEFAULT_AUTH_PARAMS | ||
); | ||
}); | ||
}); | ||
it("reject with error (if error present in response) if statusCode != 200 and statusCode != 401", () => { | ||
let error = "non 200 and non 401 code"; | ||
let requestStub = sandbox | ||
.stub(request, "post") | ||
.yields(null, { statusCode: 404 }, JSON.stringify({ error: error })); | ||
const zipUploader = proxyquire("../../../../bin/helpers/zipUpload", { | ||
"./utils": { | ||
getUserAgent: getUserAgentStub, | ||
}, | ||
request: { post: requestStub }, | ||
}); | ||
return zipUploader | ||
.zipUpload(bsConfig, "./random_file_path") | ||
.then(function (data) { | ||
chai.assert.fail("Promise error"); | ||
}) | ||
.catch((error) => { | ||
sinon.assert.calledOnce(requestStub); | ||
sinon.assert.calledOnce(getUserAgentStub); | ||
sinon.assert.calledOnce(createReadStreamStub); | ||
chai.assert.equal(error, "non 200 and non 401 code"); | ||
}); | ||
}); | ||
it("reject with message if statusCode != 200 and statusCode != 401 and error not in response", () => { | ||
let requestStub = sandbox | ||
.stub(request, "post") | ||
.yields( | ||
null, | ||
{ statusCode: 404 }, | ||
JSON.stringify({ message: "random message" }) | ||
); | ||
const zipUploader = proxyquire("../../../../bin/helpers/zipUpload", { | ||
"./utils": { | ||
getUserAgent: getUserAgentStub, | ||
}, | ||
request: { post: requestStub }, | ||
}); | ||
return zipUploader | ||
.zipUpload(bsConfig, "./random_file_path") | ||
.then(function (data) { | ||
chai.assert.fail("Promise error"); | ||
}) | ||
.catch((error) => { | ||
sinon.assert.calledOnce(requestStub); | ||
sinon.assert.calledOnce(getUserAgentStub); | ||
sinon.assert.calledOnce(createReadStreamStub); | ||
chai.assert.equal( | ||
error, | ||
Constants.userMessages.ZIP_UPLOADER_NOT_REACHABLE | ||
@@ -116,0 +175,0 @@ ); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
326467
8388
91
14
+ Addedbrowserstack-local@^1.4.8
+ Addedgetmac@^5.17.0
+ Addeduuid@^8.3.2
+ Addedagent-base@6.0.2(transitive)
+ Addedbrowserstack-local@1.5.5(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addedgetmac@5.21.0(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedis-running@2.1.0(transitive)
+ Addedms@2.1.3(transitive)
+ Addedrimraf@2.5.4(transitive)
+ Addedtemp-fs@0.9.9(transitive)
+ Addeduuid@8.3.2(transitive)
Updatedyargs@^14.2.3