Socket
Socket
Sign inDemoInstall

browserstack-cypress-cli

Package Overview
Dependencies
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

browserstack-cypress-cli - npm Package Compare versions

Comparing version 1.7.1 to 1.8.0

39

bin/commands/runs.js

@@ -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 @@ );

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc