From f75c66a7e70065193745b9ac45b1020b8fe2396f Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 19 Feb 2021 18:14:04 +0530 Subject: [PATCH 01/38] Added local_mode and cli args. Calculate local_identifier based on local_mode. --- bin/commands/runs.js | 7 +++-- bin/helpers/constants.js | 3 +++ bin/helpers/utils.js | 57 +++++++++++++++++++++++++++++++++++++--- bin/runner.js | 15 +++++++++++ package.json | 3 +++ 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index d1ec0202..99742cea 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -40,10 +40,13 @@ module.exports = function run(args) { utils.setTestEnvs(bsConfig, args); //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); // run test in headed mode utils.setHeaded(bsConfig, args); diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index d029440b..07b932f7 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -94,6 +94,9 @@ const cliMessages = { SYNC_DESCRIPTION: "Makes the run command in sync", BUILD_REPORT_MESSAGE: "See the entire build report here", 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" }, COMMON: { DISABLE_USAGE_REPORTING: "Disable usage reporting", diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 1925853a..7c11ec66 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -3,6 +3,8 @@ const os = require("os"); const path = require("path"); const fs = require("fs"); const glob = require('glob'); +const getmac = require('getmac'); +const { v4: uuidv4 } = require('uuid'); const usageReporting = require("./usageReporting"), logger = require("./logger").winstonLogger, @@ -10,6 +12,7 @@ const usageReporting = require("./usageReporting"), chalk = require('chalk'), syncCliLogger = require("../helpers/logger").syncCliLogger, config = require("../helpers/config"); +const { demand } = require("yargs"); exports.validateBstackJson = (bsConfigPath) => { return new Promise(function (resolve, reject) { @@ -311,8 +314,16 @@ exports.getLocalFlag = (connectionSettings) => { ); }; -exports.setLocal = (bsConfig) => { - if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { +exports.setLocal = (bsConfig, args) => { + if (!this.isUndefined(args.local)) { + let local = false; + if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) + local = true; + bsConfig["connection_settings"]["local"] = local; + logger.info( + "Setting up Local testing..." + ); + }else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { let local = false; if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") local = true; @@ -323,14 +334,52 @@ exports.setLocal = (bsConfig) => { } }; -exports.setLocalIdentifier = (bsConfig) => { - if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) { +exports.setLocalIdentifier = (bsConfig, args) => { + if (!this.isUndefined(args.local_identifier)){ + bsConfig["connection_settings"]["local_identifier"] = args.local_identifier; + logger.info( + `Local testing identifier: ${bsConfig['connection_settings']['local_identifier']}` + ); + } else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) { bsConfig["connection_settings"]["local_identifier"] = process.env.BROWSERSTACK_LOCAL_IDENTIFIER; logger.info( "Reading local identifier from the environment variable BROWSERSTACK_LOCAL_IDENTIFIER" ); + } 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']); + logger.info( + `Local testing identifier: ${bsConfig['connection_settings']['local_identifier']}` + ); + } +}; + +exports.setLocalMode = (bsConfig, args) => { + if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ + let local_mode = 'on-demand'; + if(!this.isUndefined(args.local_mode) && args.local_mode == "always-on"){ + local_mode = 'always-on'; + } else if ( + !this.isUndefined(bsConfig['connection_settings']['local_mode']) && + bsConfig['connection_settings']['local_mode'].toLowerCase() === "always-on" + ){ + local_mode = 'always-on'; + } + bsConfig['connection_settings']['local_mode'] = local_mode; + } +}; + +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.setHeaded = (bsConfig, args) => { diff --git a/bin/runner.js b/bin/runner.js index 35a5c11b..376e1df3 100755 --- a/bin/runner.js +++ b/bin/runner.js @@ -205,6 +205,21 @@ var argv = yargs default: false, describe: Constants.cliMessages.RUN.HEADED, type: "boolean" + }, + 'local': { + default: true, + describe: Constants.cliMessages.RUN.LOCAL, + type: "boolean" + }, + 'local-identifier': { + describe: Constants.cliMessages.RUN.LOCAL_IDENTIFIER, + default: undefined, + type: "string" + }, + 'local-mode': { + describe: Constants.cliMessages.RUN.LOCAL_MODE, + default: "on-demand", + type: "string" } }) .help('help') diff --git a/package.json b/package.json index 05330af0..15f79cc8 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,16 @@ "dependencies": { "archiver": "^5.2.0", "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", "mkdirp": "^1.0.3", "request": "^2.88.0", "requestretry": "^4.1.0", "table": "^5.4.6", + "uuid": "^8.3.2", "winston": "^2.3.1", "yargs": "^14.2.2" }, From ec8612f5bcb9f543e3395c2e0d6d8f25e0598b95 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 24 Feb 2021 19:42:39 +0530 Subject: [PATCH 02/38] Adding Local Binary start and stop logic --- bin/commands/runs.js | 11 +++++++++-- bin/helpers/utils.js | 45 +++++++++++++++++++++++++++++++++++++++----- bin/runner.js | 1 - 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 99742cea..8cb244bc 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -16,7 +16,7 @@ module.exports = function run(args) { //Delete build_results.txt from log folder if already present. utils.deleteResults(); - return utils.validateBstackJson(bsConfigPath).then(function (bsConfig) { + return utils.validateBstackJson(bsConfigPath).then(async function (bsConfig) { utils.setUsageReportingFlag(bsConfig, args.disableUsageReporting); utils.setDefaults(bsConfig, args); @@ -48,6 +48,9 @@ module.exports = function run(args) { //accept the local identifier from env variable if provided utils.setLocalIdentifier(bsConfig, args); + //setup Local Testing + let bs_local = await utils.setupLocalTesting(bsConfig, args); + // run test in headed mode utils.setHeaded(bsConfig, args); @@ -85,7 +88,11 @@ module.exports = function run(args) { } if (args.sync) { - syncRunner.pollBuildStatus(bsConfig, data).then((exitCode) => { + syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => { + // stop the Local instance + + await utils.stopLocalBinary(bs_local); + // Generate custom report! reportGenerator(bsConfig, data.build_id, args, function(){ utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 7c11ec66..20cba0a2 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -3,8 +3,9 @@ const os = require("os"); const path = require("path"); const fs = require("fs"); const glob = require('glob'); -const getmac = require('getmac'); +const getmac = require('getmac').default; const { v4: uuidv4 } = require('uuid'); +const browserstack = require('browserstack-local'); const usageReporting = require("./usageReporting"), logger = require("./logger").winstonLogger, @@ -12,7 +13,6 @@ const usageReporting = require("./usageReporting"), chalk = require('chalk'), syncCliLogger = require("../helpers/logger").syncCliLogger, config = require("../helpers/config"); -const { demand } = require("yargs"); exports.validateBstackJson = (bsConfigPath) => { return new Promise(function (resolve, reject) { @@ -360,18 +360,53 @@ exports.setLocalIdentifier = (bsConfig, args) => { exports.setLocalMode = (bsConfig, args) => { if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ let local_mode = 'on-demand'; - if(!this.isUndefined(args.local_mode) && args.local_mode == "always-on"){ + if (!this.isUndefined(args.localMode) && args.localMode == 'always-on') { local_mode = 'always-on'; } else if ( !this.isUndefined(bsConfig['connection_settings']['local_mode']) && - bsConfig['connection_settings']['local_mode'].toLowerCase() === "always-on" - ){ + bsConfig['connection_settings']['local_mode'].toLowerCase() === + 'always-on' + ) { local_mode = 'always-on'; } bsConfig['connection_settings']['local_mode'] = local_mode; + args.sync = true; } }; +exports.setupLocalTesting = (bsConfig, args) => { + return new Promise((resolve, reject) => { + if (bsConfig['connection_settings']['local']){ + var bs_local = new browserstack.Local(); + var bs_local_args = this.setLocalArgs(bsConfig, args); + bs_local.start(bs_local_args, function () { + logger.info('Started BrowserStackLocal'); + resolve(bs_local); + }); + }else { + resolve(); + } + }); +}; + +exports.stopLocalBinary = (bs_local) => { + return new Promise((resolve,reject) => { + bs_local.stop(function () { + console.log('Stopped BrowserStackLocal'); + resolve(); + }); + }); +}; + +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 + return local_args; +}; + exports.generateLocalIdentifier = (mode) => { let local_identifier = undefined; if(mode == "always-on"){ diff --git a/bin/runner.js b/bin/runner.js index 376e1df3..58ab511a 100755 --- a/bin/runner.js +++ b/bin/runner.js @@ -207,7 +207,6 @@ var argv = yargs type: "boolean" }, 'local': { - default: true, describe: Constants.cliMessages.RUN.LOCAL, type: "boolean" }, From aada1ba7c9a8024c3a6bf30597a8e62533c8b082 Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Fri, 26 Feb 2021 18:49:12 +0530 Subject: [PATCH 03/38] Adding demand message for local-identifier and local-mode options --- bin/helpers/constants.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 07b932f7..edc4a737 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -96,7 +96,9 @@ const cliMessages = { 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_IDENTIFIER: "Accepted values: String - assign an identifier to your Local process instance", + LOCAL_MODE_DEMAND: '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#run-tests', + LOCAL_IDENTIFIER_DEMAND: 'When using --local-identifier, a value needs to be supplied. \n--local-identifier \nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference#run-tests' }, COMMON: { DISABLE_USAGE_REPORTING: "Disable usage reporting", From b299e0b7ec4452102c9b38c783815c1ebc7c880d Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Fri, 26 Feb 2021 18:49:56 +0530 Subject: [PATCH 04/38] Adding log messages for sync and local mode --- bin/helpers/utils.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 20cba0a2..41345d7c 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -347,7 +347,7 @@ exports.setLocalIdentifier = (bsConfig, args) => { "Reading local identifier from the environment variable BROWSERSTACK_LOCAL_IDENTIFIER" ); } else if ( - bsConfig['connection_settings']['local'] && + bsConfig['connection_settings']['local'] && this.isUndefined(bsConfig["connection_settings"]["local_identifier"]) ){ bsConfig["connection_settings"]["local_identifier"] = this.generateLocalIdentifier(bsConfig['connection_settings']['local_mode']); @@ -369,7 +369,9 @@ exports.setLocalMode = (bsConfig, args) => { ) { local_mode = 'always-on'; } + logger.info(`Local testing set up in ${local_mode} mode.`); bsConfig['connection_settings']['local_mode'] = local_mode; + logger.info('Setting "sync" mode to enable Local testing.'); args.sync = true; } }; @@ -407,7 +409,7 @@ exports.setLocalArgs = (bsConfig, args) => { return local_args; }; -exports.generateLocalIdentifier = (mode) => { +exports.generateLocalIdentifier = (mode) => { let local_identifier = undefined; if(mode == "always-on"){ local_identifier = getmac(); From e87c7be7712de42257a0558b109a47b3ff48fd25 Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Fri, 26 Feb 2021 19:47:27 +0530 Subject: [PATCH 05/38] upgrading yargs and putting requiredArgs --- bin/runner.js | 9 +++++++-- package.json | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/runner.js b/bin/runner.js index 58ab511a..a4645bd2 100755 --- a/bin/runner.js +++ b/bin/runner.js @@ -213,12 +213,17 @@ var argv = yargs 'local-identifier': { describe: Constants.cliMessages.RUN.LOCAL_IDENTIFIER, default: undefined, - type: "string" + type: "string", + requiresArg: true, + // demand: Constants.cliMessages.RUN.LOCAL_IDENTIFIER_DEMAND }, 'local-mode': { describe: Constants.cliMessages.RUN.LOCAL_MODE, default: "on-demand", - type: "string" + type: "string", + requiresArg: true, + choices: ["always-on", "on-demand"], + // demand: Constants.cliMessages.RUN.LOCAL_MODE_DEMAND } }) .help('help') diff --git a/package.json b/package.json index 15f79cc8..d68bcd8c 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "table": "^5.4.6", "uuid": "^8.3.2", "winston": "^2.3.1", - "yargs": "^14.2.2" + "yargs": "^14.2.3" }, "repository": { "type": "git", From e4d84a1a3977e2d0ce53a94a95b01f33f79f7605 Mon Sep 17 00:00:00 2001 From: roshan Date: Sun, 28 Feb 2021 20:35:10 +0530 Subject: [PATCH 06/38] passed already failing 12 cases --- test/unit/bin/commands/runs.js | 45 ++++++++++++++++++++++++++++++---- test/unit/bin/helpers/utils.js | 16 ++++++------ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index f4d4de7a..31aba2c8 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -5,7 +5,7 @@ const chai = require("chai"), const Constants = require("../../../../bin/helpers/constants"), logger = require("../../../../bin/helpers/logger").winstonLogger, testObjects = require("../../support/fixtures/testObjects"); -const { setHeaded } = require("../../../../bin/helpers/utils"); +const { setHeaded, setupLocalTesting } = require("../../../../bin/helpers/utils"); const proxyquire = require("proxyquire").noCallThru(); @@ -91,17 +91,19 @@ describe("runs", () => { setUserSpecsStub = sandbox.stub(); setTestEnvsStub = sandbox.stub(); getConfigPathStub = sandbox.stub(); + setupLocalTestingStub = sandbox.stub(); setUsageReportingFlagStub = sandbox.stub().returns(undefined); sendUsageReportStub = sandbox.stub().callsFake(function () { return "end"; }); getErrorCodeFromMsgStub = sandbox.stub().returns("random-error-code"); - capabilityValidatorStub = sandbox.stub(); + capabilityValidatorStub = sandbox.stub().returns("random-error"); setLocalStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultsStub = sandbox.stub(); + setLocalModeStub = sandbox.stub(); }); afterEach(() => { @@ -132,14 +134,17 @@ describe("runs", () => { setHeaded: setHeadedStub, deleteResults: deleteResultsStub, setDefaults: setDefaultsStub, - isJSONInvalid: isJSONInvalidStub + setupLocalTesting: setupLocalTestingStub, + isJSONInvalid: isJSONInvalidStub, + setLocalMode: setLocalModeStub }, '../helpers/capabilityHelper': { - validate: capabilityValidatorStub, + validate: capabilityValidatorStub }, }); validateBstackJsonStub.returns(Promise.resolve(bsConfig)); + setupLocalTestingStub.returns(Promise.resolve("return nothing")); capabilityValidatorStub.returns(Promise.reject("random-error")); return runs(args) @@ -150,12 +155,14 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(validateBstackJsonStub); + sinon.assert.calledOnce(setupLocalTestingStub); + sinon.assert.calledOnce(setLocalModeStub); + 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.calledOnceWithExactly( @@ -192,6 +199,8 @@ describe("runs", () => { archiverStub = sandbox.stub(); deleteZipStub = sandbox.stub(); setLocalStub = sandbox.stub(); + setLocalModeStub = sandbox.stub(); + setupLocalTestingStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); @@ -223,6 +232,8 @@ describe("runs", () => { setUsageReportingFlag: setUsageReportingFlagStub, getConfigPath: getConfigPathStub, setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, setLocalIdentifier: setLocalIdentifierStub, setHeaded: setHeadedStub, deleteResults: deleteResultsStub, @@ -241,6 +252,7 @@ describe("runs", () => { }); validateBstackJsonStub.returns(Promise.resolve(bsConfig)); + setupLocalTestingStub.returns(Promise.resolve("nothing")) capabilityValidatorStub.returns(Promise.resolve(Constants.validationMessages.VALIDATED)); archiverStub.returns(Promise.reject("random-error")); @@ -251,6 +263,8 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); @@ -298,6 +312,8 @@ describe("runs", () => { zipUploadStub = sandbox.stub(); deleteZipStub = sandbox.stub(); setLocalStub = sandbox.stub(); + setLocalModeStub = sandbox.stub(); + setupLocalTestingStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); @@ -329,6 +345,8 @@ describe("runs", () => { setUsageReportingFlag: setUsageReportingFlagStub, getConfigPath: getConfigPathStub, setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, setLocalIdentifier: setLocalIdentifierStub, setHeaded: setHeadedStub, deleteResults: deleteResultsStub, @@ -351,6 +369,7 @@ describe("runs", () => { validateBstackJsonStub.returns(Promise.resolve(bsConfig)); capabilityValidatorStub.returns(Promise.resolve(Constants.validationMessages.VALIDATED)); + setupLocalTestingStub.returns(Promise.resolve("nothing")); archiverStub.returns(Promise.resolve("Zipping completed")); zipUploadStub.returns(Promise.reject("random-error")); @@ -361,6 +380,8 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); @@ -412,6 +433,8 @@ describe("runs", () => { createBuildStub = sandbox.stub(); deleteZipStub = sandbox.stub(); setLocalStub = sandbox.stub(); + setLocalModeStub = sandbox.stub(); + setupLocalTestingStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); @@ -443,6 +466,8 @@ describe("runs", () => { setUsageReportingFlag: setUsageReportingFlagStub, getConfigPath: getConfigPathStub, setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, setLocalIdentifier: setLocalIdentifierStub, setHeaded: setHeadedStub, deleteResults: deleteResultsStub, @@ -467,6 +492,7 @@ describe("runs", () => { }); validateBstackJsonStub.returns(Promise.resolve(bsConfig)); + setupLocalTestingStub.returns(Promise.resolve("nothing")); capabilityValidatorStub.returns( Promise.resolve(Constants.validationMessages.VALIDATED) ); @@ -481,6 +507,8 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(validateBstackJsonStub); sinon.assert.calledOnce(capabilityValidatorStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); @@ -539,6 +567,8 @@ describe("runs", () => { setDefaultsStub = sandbox.stub(); isUndefinedStub = sandbox.stub(); setLocalStub = sandbox.stub(); + setLocalModeStub = sandbox.stub(); + setupLocalTestingStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); getNumberOfSpecFilesStub = sandbox.stub().returns([]); @@ -569,6 +599,8 @@ describe("runs", () => { setParallels: setParallelsStub, getConfigPath: getConfigPathStub, setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, setLocalIdentifier: setLocalIdentifierStub, setHeaded: setHeadedStub, exportResults: exportResultsStub, @@ -598,6 +630,7 @@ describe("runs", () => { }); validateBstackJsonStub.returns(Promise.resolve(bsConfig)); + setupLocalTestingStub.returns(Promise.resolve("nothing")); capabilityValidatorStub.returns( Promise.resolve(Constants.validationMessages.VALIDATED) ); @@ -617,6 +650,8 @@ describe("runs", () => { sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(setLocalIdentifierStub); sinon.assert.calledOnce(setHeadedStub); sinon.assert.calledOnce(archiverStub); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 2dde99bf..01af2d16 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -19,6 +19,7 @@ chai.use(chaiAsPromised); logger.transports['console.info'].silent = true; describe('utils', () => { + let args = testObjects.runSampleArgs; describe('getErrorCodeFromMsg', () => { it("should return null for errMsg which isn't present in the list", () => { expect(utils.getErrorCodeFromMsg('random_value')).to.be.null; @@ -656,7 +657,8 @@ describe('utils', () => { local: true, }, }; - utils.setLocal(bsConfig); + utils.setLocal(bsConfig,args); + //expect(bsConfig).to.be.eq(undefined); expect(bsConfig.connection_settings.local).to.be.eq(true); }); @@ -667,7 +669,7 @@ describe('utils', () => { }, }; process.env.BROWSERSTACK_LOCAL = false; - utils.setLocal(bsConfig); + utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(false); }); @@ -678,7 +680,7 @@ describe('utils', () => { }, }; process.env.BROWSERSTACK_LOCAL = true; - utils.setLocal(bsConfig); + utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); }); @@ -687,7 +689,7 @@ describe('utils', () => { connection_settings: {}, }; process.env.BROWSERSTACK_LOCAL = true; - utils.setLocal(bsConfig); + utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); }); }); @@ -706,7 +708,7 @@ describe('utils', () => { local_identifier: 'local_identifier', }, }; - utils.setLocalIdentifier(bsConfig); + utils.setLocalIdentifier(bsConfig,args); expect(bsConfig.connection_settings.local_identifier).to.be.eq( 'local_identifier' ); @@ -719,7 +721,7 @@ describe('utils', () => { }, }; process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; - utils.setLocalIdentifier(bsConfig); + utils.setLocalIdentifier(bsConfig,args); expect(bsConfig.connection_settings.local_identifier).to.be.eq( 'local_identifier' ); @@ -730,7 +732,7 @@ describe('utils', () => { connection_settings: {}, }; process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; - utils.setLocalIdentifier(bsConfig); + utils.setLocalIdentifier(bsConfig,args); expect(bsConfig.connection_settings.local_identifier).to.be.eq( 'local_identifier' ); From 695bc19b8f487a80a1d3d8babd7ed789018fe833 Mon Sep 17 00:00:00 2001 From: roshan Date: Mon, 1 Mar 2021 12:24:11 +0530 Subject: [PATCH 07/38] added new test cases for the modified code --- bin/helpers/utils.js | 2 +- browserstack.err | 1 + local.log | 9 +++ test/unit/bin/helpers/utils.js | 125 ++++++++++++++++++++++++++++++++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 browserstack.err create mode 100644 local.log diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 20cba0a2..248e2ac7 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -407,7 +407,7 @@ exports.setLocalArgs = (bsConfig, args) => { return local_args; }; -exports.generateLocalIdentifier = (mode) => { +exports.generateLocalIdentifier = (mode) => { let local_identifier = undefined; if(mode == "always-on"){ local_identifier = getmac(); diff --git a/browserstack.err b/browserstack.err new file mode 100644 index 00000000..a6e14148 --- /dev/null +++ b/browserstack.err @@ -0,0 +1 @@ +[object Object] \ No newline at end of file diff --git a/local.log b/local.log new file mode 100644 index 00000000..a4cb2c0d --- /dev/null +++ b/local.log @@ -0,0 +1,9 @@ + + + +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 +Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 01af2d16..921dce6b 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -17,6 +17,7 @@ const utils = require('../../../../bin/helpers/utils'), chai.use(chaiAsPromised); logger.transports['console.info'].silent = true; +const browserstack = require('browserstack-local'); describe('utils', () => { let args = testObjects.runSampleArgs; @@ -658,7 +659,6 @@ describe('utils', () => { }, }; utils.setLocal(bsConfig,args); - //expect(bsConfig).to.be.eq(undefined); expect(bsConfig.connection_settings.local).to.be.eq(true); }); @@ -694,6 +694,129 @@ describe('utils', () => { }); }); + describe('setLocalMode', () => { + it('if the bsconfig local mode is always-on then local_mode should also be always-on', () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "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, + local_mode: "xyz" + }, + }; + let args1 = testObjects.runSampleArgs; + args1.localMode = "xyz"; + utils.setLocalMode(bsConfig,args1); + expect(bsConfig['connection_settings']['local_mode']).to.be.eq("on-demand"); + }); + + it('setLocalMode should end up setting args.sync as true', () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "xyz" + }, + }; + utils.setLocalMode(bsConfig,args); + expect(args.sync).to.be.eq(true); + }); + }); + + describe( 'setupLocalTesting' ,() => { + it('if bsconfig local is false then promise should resolve with undefined', () => { + let bsConfig = { + connection_settings: { + local: false, + }, + }; + return utils.setupLocalTesting(bsConfig,args).then((result) => { + expect(result).to.be.eq(undefined); + }); + }); + + 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 localObj = new browserstack.Local(); + let bsLocalArgs = utils.setLocalArgs(bsConfig, args); + localObj.start(bsLocalArgs,function() {}); + let flag = true; + return utils.setupLocalTesting(bsConfig,args).then((result) => { + const entries1 = Object.entries(result); + const entries2 = Object.entries(localObj); + for (const [key, value] of entries1) { + var value1 = entries1[key]; + var value2 = entries2[key]; + if(key != "pid" && value1 != value2){ + flag = false; + } + } + expect(flag).to.be.eq(true); + }); + }); + }); + + 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: "xyz" + }, + }; + 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); + }); + }); + + describe('stopLocalBinary' , () => { + it('stopLocalBinary promise gets resolve with undefined' ,() => { + let localObj = new browserstack.Local(); + return utils.stopLocalBinary(localObj).then((result) => { + expect(result).to.be.eq(undefined); + }); + }); + }); + + describe('generateLocalIdentifier', () => { + + it('function never returns the undefined', () => { + expect(utils.generateLocalIdentifier("always-on")).to.not.eq(undefined); + expect(utils.generateLocalIdentifier("abc")).to.not.eq(undefined); + }); + + it('if the mode is always-on it returns getmac() as local-identifier', () => { + expect(utils.generateLocalIdentifier("always-on")).to.be.eq("OGM6ODU6OTA6Nzc6MWU6N2Q="); + }); + 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', () => { beforeEach(function () { delete process.env.BROWSERSTACK_LOCAL_IDENTIFIER; From a56da74926c096db98522f4c88152c877da185ed Mon Sep 17 00:00:00 2001 From: roshan Date: Mon, 1 Mar 2021 12:57:03 +0530 Subject: [PATCH 08/38] added new test cases and passed already failing test cases --- test/unit/bin/commands/runs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index 31aba2c8..9c363bdd 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -97,7 +97,7 @@ describe("runs", () => { return "end"; }); getErrorCodeFromMsgStub = sandbox.stub().returns("random-error-code"); - capabilityValidatorStub = sandbox.stub().returns("random-error"); + capabilityValidatorStub = sandbox.stub(); setLocalStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); From 14e5c501bb2bd4a447212359e3e1d544bbcb51f5 Mon Sep 17 00:00:00 2001 From: roshan Date: Mon, 1 Mar 2021 14:56:27 +0530 Subject: [PATCH 09/38] removed unwanted files --- browserstack.err | 1 - local.log | 9 --------- 2 files changed, 10 deletions(-) delete mode 100644 browserstack.err delete mode 100644 local.log diff --git a/browserstack.err b/browserstack.err deleted file mode 100644 index a6e14148..00000000 --- a/browserstack.err +++ /dev/null @@ -1 +0,0 @@ -[object Object] \ No newline at end of file diff --git a/local.log b/local.log deleted file mode 100644 index a4cb2c0d..00000000 --- a/local.log +++ /dev/null @@ -1,9 +0,0 @@ - - - -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 -Mon Mar 01 2021 12:22:25 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help From 439eebd092478c2e6b0d111da5579879641f77e4 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 1 Mar 2021 20:22:51 +0530 Subject: [PATCH 10/38] Checking local identifier running in always on mode --- bin/commands/runs.js | 20 ++++++++------ bin/helpers/config.json | 3 +- bin/helpers/usageReporting.js | 5 ++-- bin/helpers/utils.js | 52 ++++++++++++++++++++++++++++++----- 4 files changed, 62 insertions(+), 18 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 8cb244bc..980b00ef 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -16,7 +16,7 @@ module.exports = function run(args) { //Delete build_results.txt from log folder if already present. utils.deleteResults(); - return utils.validateBstackJson(bsConfigPath).then(async function (bsConfig) { + return utils.validateBstackJson(bsConfigPath).then(function (bsConfig) { utils.setUsageReportingFlag(bsConfig, args.disableUsageReporting); utils.setDefaults(bsConfig, args); @@ -48,9 +48,6 @@ module.exports = function run(args) { //accept the local identifier from env variable if provided utils.setLocalIdentifier(bsConfig, args); - //setup Local Testing - let bs_local = await utils.setupLocalTesting(bsConfig, args); - // run test in headed mode utils.setHeaded(bsConfig, args); @@ -67,8 +64,12 @@ module.exports = function run(args) { return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude).then(function (data) { // 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) { let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`; let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`; @@ -89,9 +90,9 @@ module.exports = function run(args) { if (args.sync) { syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => { - // stop the Local instance - await utils.stopLocalBinary(bs_local); + // stop the Local instance + await utils.stopLocalBinary(bsConfig, bs_local); // Generate custom report! reportGenerator(bsConfig, data.build_id, args, function(){ @@ -106,9 +107,12 @@ module.exports = function run(args) { if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("",data.build_id)); utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null); return; - }).catch(function (err) { + }).catch(async function (err) { // Build creation failed logger.error(err); + // stop the Local instance + await utils.stopLocalBinary(bsConfig, bs_local); + utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed'); }); }).catch(function (err) { diff --git a/bin/helpers/config.json b/bin/helpers/config.json index dbd6b7a3..447d2b98 100644 --- a/bin/helpers/config.json +++ b/bin/helpers/config.json @@ -2,5 +2,6 @@ "uploadUrl": "https://api-cloud.browserstack.com/automate-frameworks/cypress/upload", "rails_host": "https://api.browserstack.com", "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", + "localTestingUrl": "https://www.browserstack.com/local/v1" } diff --git a/bin/helpers/usageReporting.js b/bin/helpers/usageReporting.js index 174f66f3..2001487e 100644 --- a/bin/helpers/usageReporting.js +++ b/bin/helpers/usageReporting.js @@ -231,5 +231,6 @@ function send(args) { } module.exports = { - send -} + send, + cli_version_and_path, +}; diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 41345d7c..0e225d42 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -14,6 +14,8 @@ const usageReporting = require("./usageReporting"), syncCliLogger = require("../helpers/logger").syncCliLogger, config = require("../helpers/config"); +const request = require('request'); + exports.validateBstackJson = (bsConfigPath) => { return new Promise(function (resolve, reject) { try { @@ -377,26 +379,31 @@ exports.setLocalMode = (bsConfig, args) => { }; exports.setupLocalTesting = (bsConfig, args) => { - return new Promise((resolve, reject) => { - if (bsConfig['connection_settings']['local']){ + return new Promise(async (resolve, reject) => { + let localIdentifierRunning = await this.checkLocalIdentifierRunning( + bsConfig, bsConfig['connection_settings']['local_identifier'] + ); + if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ var bs_local = new browserstack.Local(); var bs_local_args = this.setLocalArgs(bsConfig, args); bs_local.start(bs_local_args, function () { - logger.info('Started BrowserStackLocal'); resolve(bs_local); }); - }else { + } else { resolve(); } }); }; -exports.stopLocalBinary = (bs_local) => { - return new Promise((resolve,reject) => { +exports.stopLocalBinary = (bsConfig, bs_local) => { + return new Promise((resolve, reject) => { + if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { bs_local.stop(function () { - console.log('Stopped BrowserStackLocal'); resolve(); }); + } else { + resolve(); + } }); }; @@ -406,6 +413,7 @@ exports.setLocalArgs = (bsConfig, args) => { 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}`; return local_args; }; @@ -419,6 +427,36 @@ exports.generateLocalIdentifier = (mode) => { return Buffer.from(local_identifier).toString("base64"); }; +exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { + let options = { + url: `${config.localTestingUrl}/list?auth_token=${bsConfig.auth.access_key}&state=running`, + auth: { + user: bsConfig.auth.username, + password: bsConfig.auth.access_key, + }, + headers: { + 'User-Agent': this.getUserAgent(), + }, + }; + + return new Promise ( function(resolve, reject) { + request.get(options, function (err, resp, body) { + if(err){ + reject(err); + } + let response = JSON.parse(body); + let localInstances = response['instances']; + let localIdentifiers = []; + + localInstances.forEach(function(instance){ + localIdentifiers.push(instance['localIdentifier']); + }); + + resolve(localIdentifiers.includes(localIdentifier)); + }); + }); +}; + exports.setHeaded = (bsConfig, args) => { if (!this.isUndefined(args.headed) && args.headed === true) { bsConfig.run_settings.headless = false; From d4eab1157a3a7091b30c1e3c3a40dfefdd609ea9 Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Tue, 2 Mar 2021 15:48:57 +0530 Subject: [PATCH 11/38] local inferred, local mode inferred, sync inferred. - Adding checks and params for local, local mode, and sync inferred. --- bin/commands/runs.js | 3 ++ bin/helpers/capabilityHelper.js | 12 ++++++++ bin/helpers/utils.js | 50 +++++++++++++++++++++++---------- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 980b00ef..facab013 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -48,6 +48,9 @@ module.exports = function run(args) { //accept the local identifier from env variable if provided utils.setLocalIdentifier(bsConfig, args); + // setup sync inferred + utils.setSyncInferred(bsConfig, args); + // run test in headed mode utils.setHeaded(bsConfig, args); diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 5d314bdd..4a29cfbc 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -92,6 +92,18 @@ const caps = (bsConfig, zip) => { } } + 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.sync_inferred) { + obj.sync_inferred = bsConfig.sync_inferred; + } + if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined if (obj.project) logger.log(`Project name is: ${obj.project}`); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 0e225d42..034fd99b 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -317,6 +317,12 @@ exports.getLocalFlag = (connectionSettings) => { }; exports.setLocal = (bsConfig, args) => { + let localInferred = this.searchForOption('--local'); + + if (localInferred) { + bsConfig.connection_settings.local_inferred = localInferred; + } + if (!this.isUndefined(args.local)) { let local = false; if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) @@ -359,7 +365,21 @@ exports.setLocalIdentifier = (bsConfig, args) => { } }; +exports.setSyncInferred = (bsConfig, args) => { + let syncInferred = this.searchForOption('--sync'); + + if (syncInferred) { + bsConfig.sync_inferred = syncInferred; + } +}; + exports.setLocalMode = (bsConfig, args) => { + let localModeInferred = this.searchForOption('--local-mode'); + + if (localModeInferred) { + bsConfig.connection_settings.local_mode_inferred = localModeInferred; + } + if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ let local_mode = 'on-demand'; if (!this.isUndefined(args.localMode) && args.localMode == 'always-on') { @@ -379,20 +399,20 @@ exports.setLocalMode = (bsConfig, args) => { }; exports.setupLocalTesting = (bsConfig, args) => { - return new Promise(async (resolve, reject) => { - let localIdentifierRunning = await this.checkLocalIdentifierRunning( - bsConfig, bsConfig['connection_settings']['local_identifier'] - ); - if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ - var bs_local = new browserstack.Local(); - var bs_local_args = this.setLocalArgs(bsConfig, args); - bs_local.start(bs_local_args, function () { - resolve(bs_local); - }); - } else { - resolve(); - } - }); + return new Promise(async (resolve, reject) => { + let localIdentifierRunning = await this.checkLocalIdentifierRunning( + bsConfig, bsConfig['connection_settings']['local_identifier'] + ); + if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ + var bs_local = new browserstack.Local(); + var bs_local_args = this.setLocalArgs(bsConfig, args); + bs_local.start(bs_local_args, function () { + resolve(bs_local); + }); + } else { + resolve(); + } + }); }; exports.stopLocalBinary = (bsConfig, bs_local) => { @@ -438,7 +458,7 @@ exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { 'User-Agent': this.getUserAgent(), }, }; - + return new Promise ( function(resolve, reject) { request.get(options, function (err, resp, body) { if(err){ From 9696fc592f4d20fd9aa7eadfebf5191d958011a5 Mon Sep 17 00:00:00 2001 From: roshan Date: Tue, 2 Mar 2021 17:57:53 +0530 Subject: [PATCH 12/38] passed all failing tests and added new specs --- test/unit/bin/commands/runs.js | 14 +- test/unit/bin/helpers/utils.js | 232 ++++++++++++++++++++++++++++----- 2 files changed, 211 insertions(+), 35 deletions(-) diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index 9c363bdd..3faef5cf 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -5,7 +5,7 @@ const chai = require("chai"), const Constants = require("../../../../bin/helpers/constants"), logger = require("../../../../bin/helpers/logger").winstonLogger, testObjects = require("../../support/fixtures/testObjects"); -const { setHeaded, setupLocalTesting } = require("../../../../bin/helpers/utils"); +const { setHeaded, setupLocalTesting, stopLocalBinary } = require("../../../../bin/helpers/utils"); const proxyquire = require("proxyquire").noCallThru(); @@ -155,7 +155,6 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(validateBstackJsonStub); - sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(setLocalModeStub); sinon.assert.calledOnce(setHeadedStub); sinon.assert.calledOnce(capabilityValidatorStub); @@ -264,7 +263,10 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(setLocalModeStub); - sinon.assert.calledOnce(setupLocalTestingStub); + sinon.assert.calledOnce(setUsernameStub); + sinon.assert.calledOnce(setAccessKeyStub); + sinon.assert.calledOnce(setBuildNameStub); + sinon.assert.calledOnce(setCypressConfigFilenameStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); @@ -381,7 +383,6 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(setLocalModeStub); - sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); @@ -440,6 +441,7 @@ describe("runs", () => { deleteResultsStub = sandbox.stub(); getNumberOfSpecFilesStub = sandbox.stub().returns([]); setDefaultsStub = sandbox.stub(); + stopLocalBinaryStub = sandbox.stub(); }); afterEach(() => { @@ -472,7 +474,8 @@ describe("runs", () => { setHeaded: setHeadedStub, deleteResults: deleteResultsStub, getNumberOfSpecFiles: getNumberOfSpecFilesStub, - setDefaults: setDefaultsStub + setDefaults: setDefaultsStub, + stopLocalBinary: stopLocalBinaryStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -498,6 +501,7 @@ describe("runs", () => { ); archiverStub.returns(Promise.resolve("Zipping completed")); zipUploadStub.returns(Promise.resolve("zip uploaded")); + stopLocalBinaryStub.returns(Promise.resolve("nothing")); createBuildStub.returns(Promise.reject("random-error")); return runs(args) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 921dce6b..c78118f0 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1,6 +1,9 @@ 'use strict'; const path = require('path'); +const { stub } = require('sinon'); +var sandbox = require('sinon').createSandbox(); +const request = require('request'); const chai = require('chai'), expect = chai.expect, sinon = require('sinon'), @@ -8,19 +11,18 @@ const chai = require('chai'), glob = require('glob'), chalk = require('chalk'), fs = require('fs'); - +const getmac = require('getmac').default; +const usageReporting = require('../../../../bin/helpers/usageReporting'); const utils = require('../../../../bin/helpers/utils'), constant = require('../../../../bin/helpers/constants'), logger = require('../../../../bin/helpers/logger').winstonLogger, testObjects = require('../../support/fixtures/testObjects'), syncLogger = require("../../../../bin/helpers/logger").syncCliLogger; - +const browserstack = require('browserstack-local'); chai.use(chaiAsPromised); logger.transports['console.info'].silent = true; -const browserstack = require('browserstack-local'); describe('utils', () => { - let args = testObjects.runSampleArgs; describe('getErrorCodeFromMsg', () => { it("should return null for errMsg which isn't present in the list", () => { expect(utils.getErrorCodeFromMsg('random_value')).to.be.null; @@ -658,6 +660,9 @@ describe('utils', () => { local: true, }, }; + let args = { + local: true + }; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); }); @@ -668,6 +673,9 @@ describe('utils', () => { local: true, }, }; + let args = { + local: false + }; process.env.BROWSERSTACK_LOCAL = false; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(false); @@ -679,6 +687,9 @@ describe('utils', () => { local: false, }, }; + let args = { + local: true + }; process.env.BROWSERSTACK_LOCAL = true; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); @@ -688,6 +699,9 @@ describe('utils', () => { let bsConfig = { connection_settings: {}, }; + let args = { + local: true + } process.env.BROWSERSTACK_LOCAL = true; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); @@ -695,6 +709,20 @@ describe('utils', () => { }); describe('setLocalMode', () => { + it('if bsconfig local is true and args local is always-on then local_mode should be always-on' , () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "xyz" + }, + }; + let args = { + localMode: "always-on" + }; + utils.setLocalMode(bsConfig,args); + expect(bsConfig['connection_settings']['local_mode']).to.be.eq("always-on"); + }); + it('if the bsconfig local mode is always-on then local_mode should also be always-on', () => { let bsConfig = { connection_settings: { @@ -702,6 +730,9 @@ describe('utils', () => { local_mode: "always-on" }, }; + let args = { + localMode: "xyz" + }; utils.setLocalMode(bsConfig,args); expect(bsConfig['connection_settings']['local_mode']).to.be.eq("always-on"); }); @@ -713,9 +744,10 @@ describe('utils', () => { local_mode: "xyz" }, }; - let args1 = testObjects.runSampleArgs; - args1.localMode = "xyz"; - utils.setLocalMode(bsConfig,args1); + let args = { + localMode: "xyz" + }; + utils.setLocalMode(bsConfig,args); expect(bsConfig['connection_settings']['local_mode']).to.be.eq("on-demand"); }); @@ -726,20 +758,35 @@ describe('utils', () => { local_mode: "xyz" }, }; + let args = { + localMode: "xyz" + } utils.setLocalMode(bsConfig,args); expect(args.sync).to.be.eq(true); }); }); - describe( 'setupLocalTesting' ,() => { + describe('setupLocalTesting' ,() => { + afterEach(function () { + sinon.restore(); + }); it('if bsconfig local is false then promise should resolve with undefined', () => { let bsConfig = { + auth: { + access_key: "xyz" + }, connection_settings: { - local: false, + 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({}); return utils.setupLocalTesting(bsConfig,args).then((result) => { - expect(result).to.be.eq(undefined); + expect(result.constructor.name).to.be.eq("Local"); }); }); @@ -753,21 +800,11 @@ describe('utils', () => { local_identifier: "xyz" }, }; - let localObj = new browserstack.Local(); - let bsLocalArgs = utils.setLocalArgs(bsConfig, args); - localObj.start(bsLocalArgs,function() {}); - let flag = true; + let args = {}; + let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); + checkLocalIdentifierRunningStub.returns(Promise.resolve(true)); return utils.setupLocalTesting(bsConfig,args).then((result) => { - const entries1 = Object.entries(result); - const entries2 = Object.entries(localObj); - for (const [key, value] of entries1) { - var value1 = entries1[key]; - var value2 = entries2[key]; - if(key != "pid" && value1 != value2){ - flag = false; - } - } - expect(flag).to.be.eq(true); + expect(result).to.be.eq(undefined); }); }); }); @@ -783,6 +820,9 @@ describe('utils', () => { local_identifier: "xyz" }, }; + 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"]); @@ -793,10 +833,43 @@ describe('utils', () => { describe('stopLocalBinary' , () => { it('stopLocalBinary promise gets resolve with undefined' ,() => { - let localObj = new browserstack.Local(); - return utils.stopLocalBinary(localObj).then((result) => { - expect(result).to.be.eq(undefined); + let bsConfig = { + connection_settings: { + local_mode: true + } + }; + return utils.stopLocalBinary(bsConfig).then((result) => { + expect(result).to.be.eq(undefined); + }); + }); + + it('stopLocalBinary promise reolves with undefined if the bs_local isRunning is false' ,() => { + let bsConfig = { + connection_settings: { + local_mode: true + } + }; + let bs_local = new browserstack.Local(); + let isRunningStub = sinon.stub(bs_local,"isRunning"); + isRunningStub.returns(false); + 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, then gets resolve with undefined' ,() => { + let bsConfig = { + connection_settings: { + local_mode: "not-always-on" + } + }; + let bs_local = new browserstack.Local(); + let isRunningStub = sinon.stub(bs_local,"isRunning"); + isRunningStub.returns(true); + return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { + expect(result).to.be.eq(undefined); + expect(bs_local.isProcessRunning).to.be.eq(false); + }); }); }); @@ -808,7 +881,7 @@ describe('utils', () => { }); it('if the mode is always-on it returns getmac() as local-identifier', () => { - expect(utils.generateLocalIdentifier("always-on")).to.be.eq("OGM6ODU6OTA6Nzc6MWU6N2Q="); + 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"); @@ -828,12 +901,15 @@ describe('utils', () => { it('should not change local identifier in bsConfig if process.env.BROWSERSTACK_LOCAL_IDENTIFIER is undefined', () => { let bsConfig = { connection_settings: { - local_identifier: 'local_identifier', + local: true }, }; + 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" ); }); @@ -843,6 +919,7 @@ describe('utils', () => { local_identifier: 'test', }, }; + let args = {}; process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; utils.setLocalIdentifier(bsConfig,args); expect(bsConfig.connection_settings.local_identifier).to.be.eq( @@ -854,12 +931,27 @@ describe('utils', () => { let bsConfig = { connection_settings: {}, }; + let args = {}; process.env.BROWSERSTACK_LOCAL_IDENTIFIER = 'local_identifier'; utils.setLocalIdentifier(bsConfig,args); expect(bsConfig.connection_settings.local_identifier).to.be.eq( 'local_identifier' ); }); + + it('if args local_identifier is defined then it gets assigned to bsConfig connection_settings local_identifier' , () => { + let bsConfig = { + local: true, + connection_settings: { + local_identifier: "abc" + } + }; + let args = { + local_identifier: "xyz" + }; + utils.setLocalIdentifier(bsConfig, args); + expect(bsConfig.connection_settings.local_identifier).to.be.eq(args.local_identifier); + }); }); describe('setUsername', () => { @@ -1327,4 +1419,84 @@ describe('utils', () => { expect(utils.deleteBaseUrlFromError(error)).not.to.match(/To test on BrowserStack/) }); }); + + 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(false, 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(false, 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); + }); + }); + }); + }); From 1edf10b15c8ce5e0dbbb1d02fe3b3af32bc9505d Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Tue, 2 Mar 2021 18:13:38 +0530 Subject: [PATCH 13/38] Adding local start and stop error --- bin/helpers/utils.js | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 034fd99b..7dc6bac5 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -406,8 +406,20 @@ exports.setupLocalTesting = (bsConfig, args) => { if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ var bs_local = new browserstack.Local(); var bs_local_args = this.setLocalArgs(bsConfig, args); - bs_local.start(bs_local_args, function () { - resolve(bs_local); + bs_local.start(bs_local_args, function (localStartError) { + if (this.isUndefined(localStartError)) { + resolve(bs_local); + } else { + let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, + errorCode = "local_start_error"; + this.sendUsageReport( + bsConfig, + args, + message, + Constants.messageTypes.ERROR, + errorCode + ); + } }); } else { resolve(); @@ -418,8 +430,20 @@ exports.setupLocalTesting = (bsConfig, args) => { exports.stopLocalBinary = (bsConfig, bs_local) => { return new Promise((resolve, reject) => { if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { - bs_local.stop(function () { - resolve(); + bs_local.stop(function (localStopError) { + if (this.isUndefined(localStopError)) { + resolve(); + } else { + let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, + errorCode = "local_stop_error"; + this.sendUsageReport( + bsConfig, + args, + message, + Constants.messageTypes.ERROR, + errorCode + ); + } }); } else { resolve(); From 94c6e62bfa8cc9fa1ed5be46a18be363f51fe61e Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 2 Mar 2021 18:57:39 +0530 Subject: [PATCH 14/38] Updated validation messages for local cli --- bin/helpers/capabilityHelper.js | 31 ++++++++++++++++--- bin/helpers/constants.js | 4 ++- bin/helpers/utils.js | 54 ++++++++++++++++++--------------- bin/runner.js | 11 ++----- 4 files changed, 61 insertions(+), 39 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 5d314bdd..c09a1e22 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -42,18 +42,33 @@ const caps = (bsConfig, zip) => { reject("Test suite is empty"); } + // Sync Inferred + if (bsConfig.connection_settings && 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; + logger.info('Setting up Local testing...'); + } + obj.localMode = null; + // Local Mode + if (obj.local === true && bsConfig.connection_settings.local_mode) { + obj.localMode = bsConfig.connection_settings.local_mode; + logger.info(`Local testing set up in ${obj.localMode} mode.`); + } + // Local Identifier obj.localIdentifier = null; if (obj.local === true && (bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier)) { 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 obj.project = "project-name"; // Build name @@ -94,9 +109,9 @@ const caps = (bsConfig, zip) => { if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined - 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}`); if (obj.callbackURL) logger.info(`callback url is : ${obj.callbackURL}`); @@ -132,6 +147,12 @@ const validate = (bsConfig, args) => { // if parallels specified via arguments validate only arguments if (!Utils.isUndefined(args) && !Utils.isUndefined(args.parallels) && !Utils.isParallelValid(args.parallels)) reject(Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION); + // 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_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); + // validate if config file provided exists or not when cypress_config_file provided // validate the cypressProjectDir key otherwise. let cypressConfigFilePath = bsConfig.run_settings.cypressConfigFilePath; diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index edc4a737..6639284d 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -57,7 +57,9 @@ const validationMessages = { INVALID_CYPRESS_JSON: "cypress.json is not a valid json", INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication", LOCAL_NOT_SET: "To test 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_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. <--local-identifier> . For 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. <--local-mode> <\"always-on\" | \"on-demand\">. For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference" }; const cliMessages = { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 0e225d42..fff868e9 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -38,34 +38,40 @@ exports.getErrorCodeFromMsg = (errMsg) => { let errorCode = null; switch (errMsg) { 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_LOCAL_MODE: + errorCode = 'invalid_local_mode'; 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; } if ( @@ -322,9 +328,6 @@ exports.setLocal = (bsConfig, args) => { if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) local = true; bsConfig["connection_settings"]["local"] = local; - logger.info( - "Setting up Local testing..." - ); }else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { let local = false; if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") @@ -339,9 +342,6 @@ exports.setLocal = (bsConfig, args) => { exports.setLocalIdentifier = (bsConfig, args) => { if (!this.isUndefined(args.local_identifier)){ bsConfig["connection_settings"]["local_identifier"] = args.local_identifier; - logger.info( - `Local testing identifier: ${bsConfig['connection_settings']['local_identifier']}` - ); } else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) { bsConfig["connection_settings"]["local_identifier"] = process.env.BROWSERSTACK_LOCAL_IDENTIFIER; @@ -353,9 +353,6 @@ exports.setLocalIdentifier = (bsConfig, args) => { this.isUndefined(bsConfig["connection_settings"]["local_identifier"]) ){ bsConfig["connection_settings"]["local_identifier"] = this.generateLocalIdentifier(bsConfig['connection_settings']['local_mode']); - logger.info( - `Local testing identifier: ${bsConfig['connection_settings']['local_identifier']}` - ); } }; @@ -371,9 +368,10 @@ exports.setLocalMode = (bsConfig, args) => { ) { local_mode = 'always-on'; } - logger.info(`Local testing set up in ${local_mode} mode.`); bsConfig['connection_settings']['local_mode'] = local_mode; - logger.info('Setting "sync" mode to enable Local testing.'); + if (this.isUndefined(args.sync) || !args.sync ){ + bsConfig['connection_settings']['sync_inferred'] = true; + } args.sync = true; } }; @@ -414,6 +412,7 @@ exports.setLocalArgs = (bsConfig, args) => { local_args['daemon'] = true; local_args['enable-logging-for-api'] = true local_args['source'] = `cypress:${usageReporting.cli_version_and_path(bsConfig).version}`; + local_args['bs-host'] = 'k8s-devcypress.bsstag.com'; return local_args; }; @@ -438,14 +437,17 @@ exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { 'User-Agent': this.getUserAgent(), }, }; - - return new Promise ( function(resolve, reject) { + 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 = response['instances']; + let localInstances = []; + if(!that.isUndefined(response['instances'])){ + localInstances = response['instances']; + } let localIdentifiers = []; localInstances.forEach(function(instance){ @@ -522,6 +524,10 @@ exports.isJSONInvalid = (err, args) => { return false } + if( err === Constants.validationMessages.INVALID_LOCAL_IDENTIFIER || err === Constants.validationMessages.INVALID_LOCAL_MODE ){ + return false + } + return invalid } diff --git a/bin/runner.js b/bin/runner.js index a4645bd2..72cb7ce0 100755 --- a/bin/runner.js +++ b/bin/runner.js @@ -212,18 +212,11 @@ var argv = yargs }, 'local-identifier': { describe: Constants.cliMessages.RUN.LOCAL_IDENTIFIER, - default: undefined, - type: "string", - requiresArg: true, - // demand: Constants.cliMessages.RUN.LOCAL_IDENTIFIER_DEMAND + type: "string" }, 'local-mode': { describe: Constants.cliMessages.RUN.LOCAL_MODE, - default: "on-demand", - type: "string", - requiresArg: true, - choices: ["always-on", "on-demand"], - // demand: Constants.cliMessages.RUN.LOCAL_MODE_DEMAND + type: "string" } }) .help('help') From 979d1a40bbff5acda174b73b1c62d492faf928fc Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Tue, 2 Mar 2021 19:20:37 +0530 Subject: [PATCH 15/38] Send the value of local_mode not the true/false --- bin/helpers/utils.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 7dc6bac5..4f6bdfe5 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -374,12 +374,6 @@ exports.setSyncInferred = (bsConfig, args) => { }; exports.setLocalMode = (bsConfig, args) => { - let localModeInferred = this.searchForOption('--local-mode'); - - if (localModeInferred) { - bsConfig.connection_settings.local_mode_inferred = localModeInferred; - } - if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ let local_mode = 'on-demand'; if (!this.isUndefined(args.localMode) && args.localMode == 'always-on') { @@ -395,6 +389,12 @@ exports.setLocalMode = (bsConfig, args) => { bsConfig['connection_settings']['local_mode'] = local_mode; logger.info('Setting "sync" mode to enable Local testing.'); args.sync = true; + + let localModeInferred = this.searchForOption('--local-mode'); + + if (localModeInferred) { + bsConfig.connection_settings.local_mode_inferred = local_mode; + } } }; From d1f5afedcf82f320106e6f8d186a7ab5f2a1a2ea Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 2 Mar 2021 19:25:40 +0530 Subject: [PATCH 16/38] Bug fixes for callback stop and start binary --- bin/helpers/capabilityHelper.js | 26 ++++++++++++-------------- bin/helpers/utils.js | 10 ++++++---- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 8c45785a..fad8e298 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -41,10 +41,20 @@ const caps = (bsConfig, zip) => { } else { reject("Test suite is empty"); } + + // Inferred 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; + } - // Sync Inferred - if (bsConfig.connection_settings && bsConfig.connection_settings.sync_inferred) + if (bsConfig.sync_inferred) { + obj.sync_inferred = bsConfig.sync_inferred; logger.info('Setting "sync" mode to enable Local testing.'); + } // Local obj.local = false; @@ -107,18 +117,6 @@ const caps = (bsConfig, zip) => { } } - 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.sync_inferred) { - obj.sync_inferred = bsConfig.sync_inferred; - } - if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined if (obj.project) logger.info(`Project name is: ${obj.project}`); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 95a40abd..29f540c7 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -404,13 +404,14 @@ exports.setupLocalTesting = (bsConfig, args) => { if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ var bs_local = new browserstack.Local(); var bs_local_args = this.setLocalArgs(bsConfig, args); + let that = this; bs_local.start(bs_local_args, function (localStartError) { - if (this.isUndefined(localStartError)) { + if (that.isUndefined(localStartError)) { resolve(bs_local); } else { let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, errorCode = "local_start_error"; - this.sendUsageReport( + that.sendUsageReport( bsConfig, args, message, @@ -428,13 +429,14 @@ exports.setupLocalTesting = (bsConfig, args) => { exports.stopLocalBinary = (bsConfig, bs_local) => { return new Promise((resolve, reject) => { if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { + let that = this; bs_local.stop(function (localStopError) { - if (this.isUndefined(localStopError)) { + if (that.isUndefined(localStopError)) { resolve(); } else { let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, errorCode = "local_stop_error"; - this.sendUsageReport( + that.sendUsageReport( bsConfig, args, message, From 12bd47fe98b19974eec2ef641f8e46e8104e5835 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 2 Mar 2021 19:53:44 +0530 Subject: [PATCH 17/38] Removing bshost. --- bin/helpers/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index c51e4fc8..46eb5f7b 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -458,7 +458,7 @@ exports.setLocalArgs = (bsConfig, args) => { local_args['daemon'] = true; local_args['enable-logging-for-api'] = true local_args['source'] = `cypress:${usageReporting.cli_version_and_path(bsConfig).version}`; - local_args['bs-host'] = 'k8s-devcypress.bsstag.com'; + return local_args; }; From 29cd24b652eedb8bf5d64e93fa37dfe594c04498 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 3 Mar 2021 11:46:00 +0530 Subject: [PATCH 18/38] Adding local_config_file for passing configuration for local binary --- bin/commands/runs.js | 3 +++ bin/helpers/capabilityHelper.js | 3 ++- bin/helpers/constants.js | 8 ++++---- bin/helpers/utils.js | 15 ++++++++++++++- bin/runner.js | 4 ++++ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index facab013..c879ee97 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -48,6 +48,9 @@ module.exports = function run(args) { //accept the local identifier from env variable if provided utils.setLocalIdentifier(bsConfig, args); + // set Local Config File + utils.setLocalConfigFile(bsConfig, args); + // setup sync inferred utils.setSyncInferred(bsConfig, args); diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index fad8e298..02ce0f6f 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -60,7 +60,6 @@ const caps = (bsConfig, zip) => { obj.local = false; if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) { obj.local = true; - logger.info('Setting up Local testing...'); } obj.localMode = null; @@ -163,6 +162,8 @@ const validate = (bsConfig, args) => { 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 // validate the cypressProjectDir key otherwise. let cypressConfigFilePath = bsConfig.run_settings.cypressConfigFilePath; diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 6639284d..5dc1f0a8 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -58,8 +58,9 @@ const validationMessages = { INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication", LOCAL_NOT_SET: "To test 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.", - INVALID_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. <--local-identifier> . For 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. <--local-mode> <\"always-on\" | \"on-demand\">. For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference" + INVALID_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. \n--local-identifier .\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: "When using --local-config-file, a value needs to be supplied. \n--local-config-file \"path to local-config-file.yaml\".\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference" }; const cliMessages = { @@ -99,8 +100,7 @@ const cliMessages = { 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_MODE_DEMAND: '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#run-tests', - LOCAL_IDENTIFIER_DEMAND: 'When using --local-identifier, a value needs to be supplied. \n--local-identifier \nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference#run-tests' + LOCAL_CONFIG_FILE: "Accepted values: String - path to local config-file to your Local process instance" }, COMMON: { DISABLE_USAGE_REPORTING: "Disable usage reporting", diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 46eb5f7b..1f5bbbf4 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -64,6 +64,9 @@ exports.getErrorCodeFromMsg = (errMsg) => { 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'; break; @@ -405,6 +408,7 @@ exports.setupLocalTesting = (bsConfig, args) => { var bs_local = new browserstack.Local(); 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); @@ -418,6 +422,7 @@ exports.setupLocalTesting = (bsConfig, args) => { Constants.messageTypes.ERROR, errorCode ); + reject(localStartError); } }); } else { @@ -458,7 +463,9 @@ exports.setLocalArgs = (bsConfig, args) => { 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; }; @@ -505,6 +512,12 @@ exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { }); }; +exports.setLocalConfigFile = (bsConfig, args) => { + if(!this.isUndefined(args.localConfigFile)){ + bsConfig['connection_settings']['local_config_file'] = args.localConfigFile; + } +}; + exports.setHeaded = (bsConfig, args) => { if (!this.isUndefined(args.headed) && args.headed === true) { bsConfig.run_settings.headless = false; diff --git a/bin/runner.js b/bin/runner.js index 72cb7ce0..30586293 100755 --- a/bin/runner.js +++ b/bin/runner.js @@ -217,6 +217,10 @@ var argv = yargs 'local-mode': { describe: Constants.cliMessages.RUN.LOCAL_MODE, type: "string" + }, + 'local-config-file': { + describe: Constants.cliMessages.RUN.LOCAL_CONFIG_FILE, + type: "string" } }) .help('help') From 63ce04c6ed29e4129a111f6d1a6c5fa3e219e54f Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Wed, 3 Mar 2021 15:52:04 +0530 Subject: [PATCH 19/38] Updating inferred event logic - If the user passed anything explicitly, then it is not inferred. - This is to understand which of the "auto-fallback" flows does CLI fall in. - Inverted the logic of the *_inferred events. --- bin/commands/runs.js | 3 --- bin/helpers/capabilityHelper.js | 14 +++++++------- bin/helpers/utils.js | 27 +++++++++------------------ 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index c879ee97..b34e5953 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -51,9 +51,6 @@ module.exports = function run(args) { // set Local Config File utils.setLocalConfigFile(bsConfig, args); - // setup sync inferred - utils.setSyncInferred(bsConfig, args); - // run test in headed mode utils.setHeaded(bsConfig, args); diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 02ce0f6f..1c614225 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -41,21 +41,21 @@ const caps = (bsConfig, zip) => { } else { reject("Test suite is empty"); } - + // Inferred settings - if (bsConfig.connection_settings.local_mode_inferred) { + if (bsConfig.connection_settings && bsConfig.connection_settings.local_mode_inferred) { obj.local_mode_inferred = bsConfig.connection_settings.local_mode_inferred; } - if (bsConfig.connection_settings.local_inferred) { + if (bsConfig.connection_settings && bsConfig.connection_settings.local_inferred) { obj.local_inferred = bsConfig.connection_settings.local_inferred; } - if (bsConfig.sync_inferred) { - obj.sync_inferred = bsConfig.sync_inferred; + if (bsConfig.connection_settings && 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) { @@ -68,7 +68,7 @@ const caps = (bsConfig, zip) => { obj.localMode = bsConfig.connection_settings.local_mode; logger.info(`Local testing set up in ${obj.localMode} mode.`); } - + // Local Identifier obj.localIdentifier = null; if (obj.local === true && (bsConfig.connection_settings.localIdentifier || bsConfig.connection_settings.local_identifier)) { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 1f5bbbf4..5f3afbb1 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -326,21 +326,20 @@ exports.getLocalFlag = (connectionSettings) => { }; exports.setLocal = (bsConfig, args) => { - let localInferred = this.searchForOption('--local'); - - if (localInferred) { - bsConfig.connection_settings.local_inferred = localInferred; - } - + let localInferred = !(this.searchForOption('--local')); if (!this.isUndefined(args.local)) { let local = false; - if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) + if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) { local = true; + bsConfig.connection_settings.local_inferred = localInferred; + } bsConfig["connection_settings"]["local"] = local; - }else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { + } else if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) { let local = false; - if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") + if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") { local = true; + bsConfig.connection_settings.local_inferred = localInferred; + } bsConfig["connection_settings"]["local"] = local; logger.info( "Reading local setting from the environment variable BROWSERSTACK_LOCAL" @@ -365,14 +364,6 @@ exports.setLocalIdentifier = (bsConfig, args) => { } }; -exports.setSyncInferred = (bsConfig, args) => { - let syncInferred = this.searchForOption('--sync'); - - if (syncInferred) { - bsConfig.sync_inferred = syncInferred; - } -}; - exports.setLocalMode = (bsConfig, args) => { if(String(bsConfig["connection_settings"]["local"]).toLowerCase() === "true"){ let local_mode = 'on-demand'; @@ -391,7 +382,7 @@ exports.setLocalMode = (bsConfig, args) => { } args.sync = true; - let localModeInferred = this.searchForOption('--local-mode'); + let localModeInferred = !(this.searchForOption('--local-mode')); if (localModeInferred) { bsConfig.connection_settings.local_mode_inferred = local_mode; From fe2405226d0b502e64cdc6016576c06276e011f3 Mon Sep 17 00:00:00 2001 From: Surya Tripathi Date: Wed, 3 Mar 2021 17:34:14 +0530 Subject: [PATCH 20/38] updating user agent to 1.7.2 --- bin/helpers/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 5f3afbb1..ea545990 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -261,7 +261,7 @@ exports.isParallelValid = (value) => { } exports.getUserAgent = () => { - return `BStack-Cypress-CLI/1.5.1 (${os.arch()}/${os.platform()}/${os.release()})`; + return `BStack-Cypress-CLI/1.7.2 (${os.arch()}/${os.platform()}/${os.release()})`; }; exports.isAbsolute = (configPath) => { From 6aef3002e68eca80613b93e03189f2331af45c44 Mon Sep 17 00:00:00 2001 From: roshan Date: Wed, 3 Mar 2021 18:12:41 +0530 Subject: [PATCH 21/38] written extra specs and passed failing spec --- browserstack.err | 1 + local.log | 5 ++ test/unit/bin/commands/runs.js | 41 ++++++++++++---- test/unit/bin/helpers/utils.js | 86 ++++++++++++++++++++++++++++++++-- 4 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 browserstack.err create mode 100644 local.log diff --git a/browserstack.err b/browserstack.err new file mode 100644 index 00000000..a6e14148 --- /dev/null +++ b/browserstack.err @@ -0,0 +1 @@ +[object Object] \ No newline at end of file diff --git a/local.log b/local.log new file mode 100644 index 00000000..3b186797 --- /dev/null +++ b/local.log @@ -0,0 +1,5 @@ + + +Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings +Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 +Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index 3faef5cf..e1a17365 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -5,7 +5,7 @@ const chai = require("chai"), const Constants = require("../../../../bin/helpers/constants"), logger = require("../../../../bin/helpers/logger").winstonLogger, testObjects = require("../../support/fixtures/testObjects"); -const { setHeaded, setupLocalTesting, stopLocalBinary } = require("../../../../bin/helpers/utils"); +const { setHeaded, setupLocalTesting, stopLocalBinary, setUserSpecs, setLocalConfigFile } = require("../../../../bin/helpers/utils"); const proxyquire = require("proxyquire").noCallThru(); @@ -104,6 +104,7 @@ describe("runs", () => { deleteResultsStub = sandbox.stub(); setDefaultsStub = sandbox.stub(); setLocalModeStub = sandbox.stub(); + setLocalConfigFileStub = sandbox.stub(); }); afterEach(() => { @@ -136,7 +137,8 @@ describe("runs", () => { setDefaults: setDefaultsStub, setupLocalTesting: setupLocalTestingStub, isJSONInvalid: isJSONInvalidStub, - setLocalMode: setLocalModeStub + setLocalMode: setLocalModeStub, + setLocalConfigFile: setLocalConfigFileStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub @@ -154,16 +156,23 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); 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(deleteResultsStub); - sinon.assert.calledOnce(setDefaultsStub); + sinon.assert.calledOnce(setUsageReportingFlagStub); sinon.assert.calledOnceWithExactly( sendUsageReportStub, bsConfig, @@ -205,6 +214,7 @@ describe("runs", () => { deleteResultsStub = sandbox.stub(); getNumberOfSpecFilesStub = sandbox.stub().returns([]); setDefaultsStub = sandbox.stub(); + setLocalConfigFileStub = sandbox.stub(); }); afterEach(() => { @@ -237,7 +247,8 @@ describe("runs", () => { setHeaded: setHeadedStub, deleteResults: deleteResultsStub, setDefaults: setDefaultsStub, - getNumberOfSpecFiles: getNumberOfSpecFilesStub + getNumberOfSpecFiles: getNumberOfSpecFilesStub, + setLocalConfigFile: setLocalConfigFileStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -266,6 +277,7 @@ describe("runs", () => { sinon.assert.calledOnce(setUsernameStub); sinon.assert.calledOnce(setAccessKeyStub); sinon.assert.calledOnce(setBuildNameStub); + sinon.assert.calledOnce(setLocalConfigFileStub); sinon.assert.calledOnce(setCypressConfigFilenameStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); @@ -321,6 +333,7 @@ describe("runs", () => { deleteResultsStub = sandbox.stub(); getNumberOfSpecFilesStub = sandbox.stub().returns([]); setDefaultsStub = sandbox.stub(); + setLocalConfigFileStub = sandbox.stub(); }); afterEach(() => { @@ -353,7 +366,8 @@ describe("runs", () => { setHeaded: setHeadedStub, deleteResults: deleteResultsStub, getNumberOfSpecFiles: getNumberOfSpecFilesStub, - setDefaults: setDefaultsStub + setDefaults: setDefaultsStub, + setLocalConfigFile: setLocalConfigFileStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -383,6 +397,7 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setLocalConfigFileStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); @@ -442,6 +457,7 @@ describe("runs", () => { getNumberOfSpecFilesStub = sandbox.stub().returns([]); setDefaultsStub = sandbox.stub(); stopLocalBinaryStub = sandbox.stub(); + setLocalConfigFileStub = sandbox.stub(); }); afterEach(() => { @@ -475,7 +491,8 @@ describe("runs", () => { deleteResults: deleteResultsStub, getNumberOfSpecFiles: getNumberOfSpecFilesStub, setDefaults: setDefaultsStub, - stopLocalBinary: stopLocalBinaryStub + stopLocalBinary: stopLocalBinaryStub, + setLocalConfigFile: setLocalConfigFileStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -511,6 +528,7 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(setLocalConfigFileStub); sinon.assert.calledOnce(setLocalModeStub); sinon.assert.calledOnce(setupLocalTestingStub); sinon.assert.calledOnce(validateBstackJsonStub); @@ -576,6 +594,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); setHeadedStub = sandbox.stub(); getNumberOfSpecFilesStub = sandbox.stub().returns([]); + setLocalConfigFileStub = sandbox.stub(); }); afterEach(() => { @@ -611,7 +630,8 @@ describe("runs", () => { deleteResults: deleteResultsStub, setDefaults: setDefaultsStub, isUndefined: isUndefinedStub, - getNumberOfSpecFiles: getNumberOfSpecFilesStub + getNumberOfSpecFiles: getNumberOfSpecFilesStub, + setLocalConfigFile: setLocalConfigFileStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -650,6 +670,7 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(validateBstackJsonStub); + sinon.assert.calledOnce(setLocalConfigFileStub); sinon.assert.calledOnce(capabilityValidatorStub); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index c78118f0..0c0d8769 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -709,6 +709,9 @@ describe('utils', () => { }); describe('setLocalMode', () => { + afterEach(() =>{ + sinon.restore(); + }) it('if bsconfig local is true and args local is always-on then local_mode should be always-on' , () => { let bsConfig = { connection_settings: { @@ -764,13 +767,65 @@ describe('utils', () => { utils.setLocalMode(bsConfig,args); expect(args.sync).to.be.eq(true); }); + + it('if args sync is false then the bsconfig connection_settings sync_inferred gets true', () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "xyz" + }, + }; + let args = { + localMode: "xyz", + sync: false + } + utils.setLocalMode(bsConfig,args); + expect(bsConfig.connection_settings.sync_inferred).to.be.eq(true); + }); + + it('if localModeInferred is false then the bsConfig local_mode_inferred changes to local_mode', () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "xyz", + local_mode_inferred: "xyz" + }, + }; + let args = { + localMode: "xyz", + sync: false + } + 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 localModeInferred is true then the bsConfig local_mode_inferred remains unchanged', () => { + let bsConfig = { + connection_settings: { + local: true, + local_mode: "xyz", + local_mode_inferred: "xyz" + }, + }; + let args = { + localMode: "xyz", + sync: false + } + let searchForOptionStub = sinon.stub(utils,"searchForOption"); + searchForOptionStub.returns(true); + utils.setLocalMode(bsConfig,args); + expect(bsConfig.connection_settings.local_mode_inferred).to.be.eq("xyz"); + }); }); describe('setupLocalTesting' ,() => { afterEach(function () { sinon.restore(); }); - it('if bsconfig local is false then promise should resolve with undefined', () => { + + it('if the localArgs is passed with no key then error is raised', () => { let bsConfig = { auth: { access_key: "xyz" @@ -785,8 +840,33 @@ describe('utils', () => { checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); let setLocalArgsStub = sinon.stub(utils,"setLocalArgs"); setLocalArgsStub.returns({}); - return utils.setupLocalTesting(bsConfig,args).then((result) => { - expect(result.constructor.name).to.be.eq("Local"); + return utils.setupLocalTesting(bsConfig,args).catch((error) => { + sinon.match(error, "Key is required to start local testing!") + }); + }); + + it('if the local_args is passed with invalid key then error is 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); + return utils.setupLocalTesting(bsConfig,args).catch((error) => { + sinon.match(error, "You provided an invalid key") }); }); From 3564a2c9919bd0870f4642fecb109a37c52c44e6 Mon Sep 17 00:00:00 2001 From: roshan Date: Wed, 3 Mar 2021 18:14:29 +0530 Subject: [PATCH 22/38] removed unwanted log files --- browserstack.err | 1 - local.log | 5 ----- 2 files changed, 6 deletions(-) delete mode 100644 browserstack.err delete mode 100644 local.log diff --git a/browserstack.err b/browserstack.err deleted file mode 100644 index a6e14148..00000000 --- a/browserstack.err +++ /dev/null @@ -1 +0,0 @@ -[object Object] \ No newline at end of file diff --git a/local.log b/local.log deleted file mode 100644 index 3b186797..00000000 --- a/local.log +++ /dev/null @@ -1,5 +0,0 @@ - - -Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- [ERROR] Please provide a valid key, available here: https://www.browserstack.com/accounts/settings -Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- [ERROR] DATA_INCORRECT:3001 https://browserstack.com/docs/local-testing/binary/errors/3001 -Wed Mar 03 2021 18:04:30 GMT+0530 (India Standard Time) -- You can learn more about BrowserStack Binary flags by running ./BrowserStackLocal --help From cbb07e2c4edaed5932286793b17c9c3884f81773 Mon Sep 17 00:00:00 2001 From: roshan Date: Wed, 3 Mar 2021 19:54:40 +0530 Subject: [PATCH 23/38] covered new functions under test --- test/unit/bin/helpers/utils.js | 106 +++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 11 deletions(-) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 0c0d8769..2e0eff64 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -77,6 +77,26 @@ describe('utils', () => { 'Please use --config-file .' ) ).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_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"); }); }); @@ -646,23 +666,49 @@ describe('utils', () => { }); 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 true', () => { + let bsConfig = { + connection_settings: { + local_inferred: false, + }, + }; + let args = { + local: true, + local_mode: false + }; + let searchForOptionStub = sinon.stub(utils,"searchForOption"); + searchForOptionStub.returns(false); + utils.setLocal(bsConfig,args); + expect(bsConfig.connection_settings.local_inferred).to.be.eq(true); }); it('should not change local in bsConfig if process.env.BROWSERSTACK_LOCAL is undefined', () => { + delete process.env.BROWSERSTACK_LOCAL; let bsConfig = { connection_settings: { local: true, }, }; + 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 = { local: true }; + process.env.BROWSERSTACK_LOCAL = true; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); }); @@ -670,26 +716,37 @@ describe('utils', () => { it('should change local to false in bsConfig if process.env.BROWSERSTACK_LOCAL is set to false', () => { let bsConfig = { connection_settings: { - local: true, + local: false, }, }; - let args = { - local: false - }; + let args = {}; process.env.BROWSERSTACK_LOCAL = false; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(false); }); - it('should change local to true in bsConfig if process.env.BROWSERSTACK_LOCAL is set to true', () => { + it('should change local to false in bsConfig if process.env.BROWSERSTACK_LOCAL is set to false', () => { let bsConfig = { connection_settings: { local: false, + local_inferred: false }, }; - let args = { - local: true + let args = {}; + process.env.BROWSERSTACK_LOCAL = true; + let searchForOptionStub = sinon.stub(utils, "searchForOption"); + searchForOptionStub.returns(false); + utils.setLocal(bsConfig,args); + expect(bsConfig.connection_settings.local_inferred).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); @@ -897,7 +954,8 @@ describe('utils', () => { }, connection_settings: { local: true, - local_identifier: "xyz" + local_identifier: "xyz", + local_config_file: "file" }, }; let args = {}; @@ -908,6 +966,7 @@ describe('utils', () => { 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("file")); }); }); @@ -1486,6 +1545,16 @@ describe('utils', () => { let error = constant.validationMessages.INCORRECT_AUTH_PARAMS; expect(utils.isJSONInvalid(error, {})).to.eq(true) }); + + it('JSON is invalid if local identifier is invalid', () =>{ + let error = constant.validationMessages.INVALID_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); + }); }) describe('#deleteBaseUrlFromError', () => { @@ -1579,4 +1648,19 @@ describe('utils', () => { }); }); + 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); + }); + }); + }); From cc3658f955a26a15120af86700c2b833c8c47ab9 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 3 Mar 2021 22:30:17 +0530 Subject: [PATCH 24/38] Modified local unit tests --- bin/helpers/utils.js | 7 +- test/unit/bin/helpers/utils.js | 118 +++++++++++---------------------- 2 files changed, 42 insertions(+), 83 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index ea545990..2def04f1 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -348,14 +348,16 @@ exports.setLocal = (bsConfig, args) => { }; exports.setLocalIdentifier = (bsConfig, args) => { - if (!this.isUndefined(args.local_identifier)){ - bsConfig["connection_settings"]["local_identifier"] = args.local_identifier; + 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"] = process.env.BROWSERSTACK_LOCAL_IDENTIFIER; logger.info( "Reading local identifier from the environment variable BROWSERSTACK_LOCAL_IDENTIFIER" ); + bsConfig['connection_settings']['local_mode'] = 'always-on'; } else if ( bsConfig['connection_settings']['local'] && this.isUndefined(bsConfig["connection_settings"]["local_identifier"]) @@ -439,6 +441,7 @@ exports.stopLocalBinary = (bsConfig, bs_local) => { Constants.messageTypes.ERROR, errorCode ); + resolve(localStopError); } }); } else { diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 2e0eff64..65c8af8c 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -674,8 +674,7 @@ describe('utils', () => { it('bsconfig connection_settings local_inferred as true if serachforOption returns false with args local true', () => { let bsConfig = { connection_settings: { - local_inferred: false, - }, + } }; let args = { local: true, @@ -688,7 +687,6 @@ describe('utils', () => { }); it('should not change local in bsConfig if process.env.BROWSERSTACK_LOCAL is undefined', () => { - delete process.env.BROWSERSTACK_LOCAL; let bsConfig = { connection_settings: { local: true, @@ -706,7 +704,6 @@ describe('utils', () => { }, }; let args = { - local: true }; process.env.BROWSERSTACK_LOCAL = true; utils.setLocal(bsConfig,args); @@ -716,7 +713,7 @@ describe('utils', () => { it('should change local to false in bsConfig if process.env.BROWSERSTACK_LOCAL is set to false', () => { let bsConfig = { connection_settings: { - local: false, + local: true, }, }; let args = {}; @@ -725,18 +722,18 @@ describe('utils', () => { expect(bsConfig.connection_settings.local).to.be.eq(false); }); - it('should change local to false in bsConfig if process.env.BROWSERSTACK_LOCAL is set to false', () => { + it('should change local_inferred to true in bsConfig if process.env.BROWSERSTACK_LOCAL is set to true', () => { let bsConfig = { connection_settings: { local: false, - local_inferred: false + local_inferred: false, }, }; let args = {}; process.env.BROWSERSTACK_LOCAL = true; - let searchForOptionStub = sinon.stub(utils, "searchForOption"); + let searchForOptionStub = sinon.stub(utils, 'searchForOption'); searchForOptionStub.returns(false); - utils.setLocal(bsConfig,args); + utils.setLocal(bsConfig, args); expect(bsConfig.connection_settings.local_inferred).to.be.eq(true); }); @@ -752,46 +749,33 @@ describe('utils', () => { 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: {}, }; let args = { local: true } - process.env.BROWSERSTACK_LOCAL = true; utils.setLocal(bsConfig,args); expect(bsConfig.connection_settings.local).to.be.eq(true); }); }); describe('setLocalMode', () => { + afterEach(() =>{ sinon.restore(); }) - it('if bsconfig local is true and args local is always-on then local_mode should be always-on' , () => { - let bsConfig = { - connection_settings: { - local: true, - local_mode: "xyz" - }, - }; - let args = { - localMode: "always-on" - }; - utils.setLocalMode(bsConfig,args); - expect(bsConfig['connection_settings']['local_mode']).to.be.eq("always-on"); - }); - it('if the bsconfig local mode is always-on then local_mode should also be always-on', () => { + 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: "always-on" + local_mode: "on-demand" }, }; let args = { - localMode: "xyz" + localMode: "always-on" }; utils.setLocalMode(bsConfig,args); expect(bsConfig['connection_settings']['local_mode']).to.be.eq("always-on"); @@ -800,57 +784,35 @@ describe('utils', () => { it('if bsconfig local mode is not always-on then local_mode should be on-demand', () => { let bsConfig = { connection_settings: { - local: true, - local_mode: "xyz" + local: true }, }; - let args = { - localMode: "xyz" - }; + 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 as true', () => { + it('setLocalMode should end up setting args.sync and sync_inferred as true', () => { let bsConfig = { connection_settings: { - local: true, - local_mode: "xyz" + local: true }, }; let args = { - localMode: "xyz" + localMode: "always-on" } utils.setLocalMode(bsConfig,args); expect(args.sync).to.be.eq(true); - }); - - it('if args sync is false then the bsconfig connection_settings sync_inferred gets true', () => { - let bsConfig = { - connection_settings: { - local: true, - local_mode: "xyz" - }, - }; - let args = { - localMode: "xyz", - sync: false - } - utils.setLocalMode(bsConfig,args); expect(bsConfig.connection_settings.sync_inferred).to.be.eq(true); }); - it('if localModeInferred is false then the bsConfig local_mode_inferred changes to local_mode', () => { + it('if local_mode is not provided then the bsConfig local_mode_inferred changes to local_mode', () => { let bsConfig = { connection_settings: { - local: true, - local_mode: "xyz", - local_mode_inferred: "xyz" + local: true }, }; let args = { - localMode: "xyz", - sync: false } let searchForOptionStub = sinon.stub(utils,"searchForOption"); searchForOptionStub.returns(false); @@ -858,22 +820,19 @@ describe('utils', () => { expect(bsConfig.connection_settings.local_mode_inferred).to.be.eq("on-demand"); }); - it('if localModeInferred is true then the bsConfig local_mode_inferred remains unchanged', () => { + it('if local_mode is provided then the bsConfig local_mode_inferred remains unchanged', () => { let bsConfig = { connection_settings: { local: true, - local_mode: "xyz", - local_mode_inferred: "xyz" + local_mode: "always-on" }, }; let args = { - localMode: "xyz", - sync: false } let searchForOptionStub = sinon.stub(utils,"searchForOption"); searchForOptionStub.returns(true); utils.setLocalMode(bsConfig,args); - expect(bsConfig.connection_settings.local_mode_inferred).to.be.eq("xyz"); + expect(bsConfig.connection_settings.local_mode_inferred).to.be.undefined; }); }); @@ -954,8 +913,8 @@ describe('utils', () => { }, connection_settings: { local: true, - local_identifier: "xyz", - local_config_file: "file" + local_identifier: "on-demand", + local_config_file: "./local.yml" }, }; let args = {}; @@ -966,7 +925,8 @@ describe('utils', () => { 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("file")); + expect(local_args['config-file']).to.be.eq(path.resolve('./local.yml')); + sinon.restore(); }); }); @@ -982,7 +942,7 @@ describe('utils', () => { }); }); - it('stopLocalBinary promise reolves with undefined if the bs_local isRunning is false' ,() => { + it('stopLocalBinary promise resolves with undefined if the bs_local isRunning is false' ,() => { let bsConfig = { connection_settings: { local_mode: true @@ -996,10 +956,10 @@ describe('utils', () => { }); }); - it('if the bs_local isRunning is true and local_mode is not always-on, then gets resolve with 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: "not-always-on" + local_mode: "always-on" } }; let bs_local = new browserstack.Local(); @@ -1007,18 +967,12 @@ describe('utils', () => { isRunningStub.returns(true); return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { expect(result).to.be.eq(undefined); - expect(bs_local.isProcessRunning).to.be.eq(false); }); }); }); describe('generateLocalIdentifier', () => { - it('function never returns the undefined', () => { - expect(utils.generateLocalIdentifier("always-on")).to.not.eq(undefined); - expect(utils.generateLocalIdentifier("abc")).to.not.eq(undefined); - }); - 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")); }); @@ -1037,7 +991,7 @@ describe('utils', () => { afterEach(function () { delete process.env.BROWSERSTACK_LOCAL_IDENTIFIER; }); - 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: true @@ -1078,7 +1032,7 @@ describe('utils', () => { ); }); - it('if args local_identifier is defined then it gets assigned to bsConfig connection_settings local_identifier' , () => { + it('if args localIdentifier is defined then it gets assigned to bsConfig connection_settings local_identifier' , () => { let bsConfig = { local: true, connection_settings: { @@ -1086,10 +1040,12 @@ describe('utils', () => { } }; let args = { - local_identifier: "xyz" + localIdentifier: "xyz" }; utils.setLocalIdentifier(bsConfig, args); - expect(bsConfig.connection_settings.local_identifier).to.be.eq(args.local_identifier); + expect(bsConfig.connection_settings.local_identifier).to.be.eq("xyz"); + expect(bsConfig.connection_settings.local_mode).to.be.eq('always-on'); + }); }); @@ -1569,7 +1525,7 @@ describe('utils', () => { }); }); - describe('checkLocalIdentifierRunning', () => { + describe('#checkLocalIdentifierRunning', () => { afterEach(() =>{ sinon.restore(); }); @@ -1595,7 +1551,7 @@ describe('utils', () => { ] }; sinon.stub(request, 'get') - .yields(false, responseObject, JSON.stringify(responseBody)); + .yields(undefined, responseObject, JSON.stringify(responseBody)); let bsConfig = { auth: { @@ -1632,7 +1588,7 @@ describe('utils', () => { ] }; sinon.stub(request, 'get') - .yields(false, responseObject, JSON.stringify(responseBody)); + .yields(undefined, responseObject, JSON.stringify(responseBody)); let bsConfig = { auth: { From b1767140fcefc7db7bc19e4835c832309c1f4347 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Thu, 4 Mar 2021 17:17:02 +0530 Subject: [PATCH 25/38] Fixing Unit test cases --- bin/commands/runs.js | 4 +- bin/helpers/constants.js | 2 +- bin/helpers/utils.js | 12 ++-- test/unit/bin/helpers/utils.js | 115 ++++++++++++++++++++++++++++----- 4 files changed, 110 insertions(+), 23 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index b34e5953..e5535a01 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -95,7 +95,7 @@ module.exports = function run(args) { syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => { // stop the Local instance - await utils.stopLocalBinary(bsConfig, bs_local); + await utils.stopLocalBinary(bsConfig, bs_local, args); // Generate custom report! reportGenerator(bsConfig, data.build_id, args, function(){ @@ -114,7 +114,7 @@ module.exports = function run(args) { // Build creation failed logger.error(err); // stop the Local instance - await utils.stopLocalBinary(bsConfig, bs_local); + await utils.stopLocalBinary(bsConfig, bs_local, args); utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed'); }); diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 5dc1f0a8..b9857f02 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -100,7 +100,7 @@ const cliMessages = { 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" + 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" }, COMMON: { DISABLE_USAGE_REPORTING: "Disable usage reporting", diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 2def04f1..d5934df2 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -398,7 +398,7 @@ exports.setupLocalTesting = (bsConfig, args) => { bsConfig, bsConfig['connection_settings']['local_identifier'] ); if (bsConfig['connection_settings']['local'] && !localIdentifierRunning){ - var bs_local = new browserstack.Local(); + var bs_local = this.getLocalBinary(); var bs_local_args = this.setLocalArgs(bsConfig, args); let that = this; logger.info('Setting up Local testing...'); @@ -424,7 +424,7 @@ exports.setupLocalTesting = (bsConfig, args) => { }); }; -exports.stopLocalBinary = (bsConfig, bs_local) => { +exports.stopLocalBinary = (bsConfig, bs_local, args) => { return new Promise((resolve, reject) => { if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { let that = this; @@ -432,8 +432,8 @@ exports.stopLocalBinary = (bsConfig, bs_local) => { if (that.isUndefined(localStopError)) { resolve(); } else { - let message = `name: ${localStartError.name}, message: ${localStartError.message}, extra: ${localStartError.extra}`, - errorCode = "local_stop_error"; + let message = `name: ${localStopError.name}, message: ${localStopError.message}, extra: ${localStopError.extra}`, + errorCode = 'local_stop_error'; that.sendUsageReport( bsConfig, args, @@ -450,6 +450,10 @@ exports.stopLocalBinary = (bsConfig, bs_local) => { }); }; +exports.getLocalBinary = () => { + return new browserstack.Local(); +}; + exports.setLocalArgs = (bsConfig, args) => { let local_args = {} local_args['key'] = bsConfig['auth']['access_key']; diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 65c8af8c..f442aa38 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1,6 +1,5 @@ 'use strict'; const path = require('path'); -const { stub } = require('sinon'); var sandbox = require('sinon').createSandbox(); const request = require('request'); @@ -354,7 +353,6 @@ describe('utils', () => { let args = testObjects.initSampleArgs; it('should call sendUsageReport', () => { - let sandbox = sinon.createSandbox(); sendUsageReportStub = sandbox .stub(utils, 'sendUsageReport') .callsFake(function () { @@ -362,6 +360,8 @@ describe('utils', () => { }); utils.configCreated(args); sinon.assert.calledOnce(sendUsageReportStub); + sandbox.restore(); + sinon.restore(); }); }); @@ -837,11 +837,18 @@ describe('utils', () => { }); describe('setupLocalTesting' ,() => { + + beforeEach(function () { + sinon.restore(); + sandbox.restore(); + }); + afterEach(function () { sinon.restore(); + sandbox.restore(); }); - it('if the localArgs is passed with no key then error is raised', () => { + it('if local is true and localIdentifier is not running and start error is raised', () => { let bsConfig = { auth: { access_key: "xyz" @@ -856,33 +863,62 @@ describe('utils', () => { checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); let setLocalArgsStub = sinon.stub(utils,"setLocalArgs"); setLocalArgsStub.returns({}); - return utils.setupLocalTesting(bsConfig,args).catch((error) => { + 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) => { sinon.match(error, "Key is required to start local testing!") + sinon.assert.calledOnce(sendUsageReportStub); + sinon.assert.calledOnce(getLocalBinaryStub); }); }); - it('if the local_args is passed with invalid key then error is raised', () => { + it('if local is true and localIdentifier is not running and start error is not raised', () => { let bsConfig = { auth: { - access_key: "xyz" + access_key: 'xyz', }, connection_settings: { local: true, - local_identifier: "xyz" + local_identifier: 'xyz', }, }; let args = {}; let localArgs = { - key: "abc", - localIdentifier: "abc", - daemon: true - } - let checkLocalIdentifierRunningStub = sinon.stub(utils, "checkLocalIdentifierRunning"); + key: 'abc', + localIdentifier: 'abc', + daemon: true, + }; + let checkLocalIdentifierRunningStub = sinon.stub( + utils, + 'checkLocalIdentifierRunning' + ); checkLocalIdentifierRunningStub.returns(Promise.resolve(false)); - let setLocalArgsStub = sinon.stub(utils,"setLocalArgs"); + let setLocalArgsStub = sinon.stub(utils, 'setLocalArgs'); setLocalArgsStub.returns(localArgs); - return utils.setupLocalTesting(bsConfig,args).catch((error) => { - sinon.match(error, "You provided an invalid key") + + 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); }); }); @@ -931,10 +967,14 @@ describe('utils', () => { }); describe('stopLocalBinary' , () => { + afterEach(function () { + sinon.restore(); + sandbox.restore(); + }); it('stopLocalBinary promise gets resolve with undefined' ,() => { let bsConfig = { connection_settings: { - local_mode: true + local: true } }; return utils.stopLocalBinary(bsConfig).then((result) => { @@ -969,6 +1009,45 @@ describe('utils', () => { 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 bs_local = new browserstack.Local(); + let isRunningStub = sinon.stub(bs_local,"isRunning"); + isRunningStub.returns(true); + sinon.stub(bs_local,"stop").yields(undefined); + 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 bs_local = new browserstack.Local(); + let isRunningStub = sinon.stub(bs_local,"isRunning"); + isRunningStub.returns(true); + let error = new Error('Local Stop Error'); + let stopStub = sinon.stub(bs_local,"stop").yields(error); + let sendUsageReportStub = sandbox + .stub(utils, 'sendUsageReport') + .callsFake(function () { + return 'end'; + }); + return utils.stopLocalBinary(bsConfig, bs_local, {}).then((result) => { + expect(result).to.be.eq(error); + sinon.assert.calledOnce(sendUsageReportStub); + sinon.assert.calledOnce(stopStub); + }); + }); + }); describe('generateLocalIdentifier', () => { @@ -1218,6 +1297,10 @@ describe('utils', () => { }; }); + afterEach(function(){ + sinon.restore(); + }); + it('has user provided ccf flag', () => { ccfBool = true; From 899ad87f2330768455b26c5989e1b9c7e490874f Mon Sep 17 00:00:00 2001 From: roshan Date: Thu, 4 Mar 2021 21:46:31 +0530 Subject: [PATCH 26/38] removed local object creation --- test/unit/bin/helpers/utils.js | 40 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index f442aa38..c1af83d5 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -837,7 +837,7 @@ describe('utils', () => { }); describe('setupLocalTesting' ,() => { - + beforeEach(function () { sinon.restore(); sandbox.restore(); @@ -985,12 +985,13 @@ describe('utils', () => { it('stopLocalBinary promise resolves with undefined if the bs_local isRunning is false' ,() => { let bsConfig = { connection_settings: { - local_mode: true + local_mode: "on-demand" } }; - let bs_local = new browserstack.Local(); - let isRunningStub = sinon.stub(bs_local,"isRunning"); - isRunningStub.returns(false); + let isRunningStub = sandbox.stub().returns(false); + let bs_local = { + isRunning: isRunningStub, + }; return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { expect(result).to.be.eq(undefined); }); @@ -1002,24 +1003,27 @@ describe('utils', () => { local_mode: "always-on" } }; - let bs_local = new browserstack.Local(); - let isRunningStub = sinon.stub(bs_local,"isRunning"); - isRunningStub.returns(true); + let isRunningStub = sandbox.stub().returns(true); + let bs_local = { + isRunning: isRunningStub, + } 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 bs_local = new browserstack.Local(); - let isRunningStub = sinon.stub(bs_local,"isRunning"); - isRunningStub.returns(true); - sinon.stub(bs_local,"stop").yields(undefined); + let isRunningStub = sandbox.stub().returns(true); + let stopStub = sandbox.stub().yields(undefined); + let bs_local = { + isRunning: isRunningStub, + stop: stopStub + } return utils.stopLocalBinary(bsConfig, bs_local).then((result) => { expect(result).to.be.eq(undefined); }); @@ -1031,11 +1035,13 @@ describe('utils', () => { local_mode: "on-demand" } }; - let bs_local = new browserstack.Local(); - let isRunningStub = sinon.stub(bs_local,"isRunning"); - isRunningStub.returns(true); + let isRunningStub = sandbox.stub().returns(true); let error = new Error('Local Stop Error'); - let stopStub = sinon.stub(bs_local,"stop").yields(error); + let stopStub = sandbox.stub().yields(error); + let bs_local = { + isRunning: isRunningStub, + stop: stopStub + } let sendUsageReportStub = sandbox .stub(utils, 'sendUsageReport') .callsFake(function () { From 73f70aa8d6e360339688abc8a6e85b7e05fc6d05 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 5 Mar 2021 13:29:45 +0530 Subject: [PATCH 27/38] Indentation and minor null pointer fixes. --- bin/helpers/capabilityHelper.js | 20 ++++---- bin/helpers/config.json | 2 +- bin/helpers/utils.js | 85 +++++++++++++++++---------------- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 1c614225..a7855e03 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -43,17 +43,19 @@ const caps = (bsConfig, zip) => { } // Inferred settings - if (bsConfig.connection_settings && bsConfig.connection_settings.local_mode_inferred) { - obj.local_mode_inferred = bsConfig.connection_settings.local_mode_inferred; - } + 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 && bsConfig.connection_settings.local_inferred) { - obj.local_inferred = bsConfig.connection_settings.local_inferred; - } + if (bsConfig.connection_settings.local_inferred) { + obj.local_inferred = bsConfig.connection_settings.local_inferred; + } - if (bsConfig.connection_settings && bsConfig.connection_settings.sync_inferred) { - obj.sync_inferred = bsConfig.connection_settings.sync_inferred; - logger.info('Setting "sync" mode to enable Local testing.'); + if (bsConfig.connection_settings.sync_inferred) { + obj.sync_inferred = bsConfig.connection_settings.sync_inferred; + logger.info('Setting "sync" mode to enable Local testing.'); + } } // Local diff --git a/bin/helpers/config.json b/bin/helpers/config.json index 447d2b98..83596c99 100644 --- a/bin/helpers/config.json +++ b/bin/helpers/config.json @@ -3,5 +3,5 @@ "rails_host": "https://api.browserstack.com", "dashboardUrl": "https://automate.browserstack.com/dashboard/v2/builds/", "usageReportingUrl": "https://eds.browserstack.com:443/send_event_cy_internal", - "localTestingUrl": "https://www.browserstack.com/local/v1" + "localTestingListUrl": "https://www.browserstack.com/local/v1/list" } diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index d5934df2..3d25a6ef 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -394,39 +394,40 @@ exports.setLocalMode = (bsConfig, args) => { exports.setupLocalTesting = (bsConfig, args) => { return new Promise(async (resolve, reject) => { - let localIdentifierRunning = await this.checkLocalIdentifierRunning( - bsConfig, bsConfig['connection_settings']['local_identifier'] - ); - if (bsConfig['connection_settings']['local'] && !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(localStartError); - } - }); - } else { - resolve(); + 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(localStartError); + } + }); + } } + resolve(); }); }; exports.stopLocalBinary = (bsConfig, bs_local, args) => { return new Promise((resolve, reject) => { - if (!this.isUndefined(bs_local) && bs_local.isRunning() && bsConfig['connection_settings']['local_mode'].toLowerCase() != "always-on") { + 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)) { @@ -479,7 +480,7 @@ exports.generateLocalIdentifier = (mode) => { exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { let options = { - url: `${config.localTestingUrl}/list?auth_token=${bsConfig.auth.access_key}&state=running`, + url: `${config.localTestingListUrl}?auth_token=${bsConfig.auth.access_key}&state=running`, auth: { user: bsConfig.auth.username, password: bsConfig.auth.access_key, @@ -491,21 +492,21 @@ exports.checkLocalIdentifierRunning = (bsConfig, localIdentifier) => { 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']); - }); + 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)); + resolve(localIdentifiers.includes(localIdentifier)); }); }); }; From 3296165ec4a7496f5b157ea53f0cb4a0921b2cf7 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 5 Mar 2021 14:53:04 +0530 Subject: [PATCH 28/38] Adding placeholders for local_mode and local_config_file in default json --- bin/helpers/utils.js | 22 +++++++++++++--------- bin/templates/configTemplate.js | 4 +++- test/unit/bin/helpers/utils.js | 23 ++++------------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 3d25a6ef..da8daf28 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -326,24 +326,25 @@ exports.getLocalFlag = (connectionSettings) => { }; exports.setLocal = (bsConfig, args) => { - let localInferred = !(this.searchForOption('--local')); + let localInferred = !(this.searchForOption('--local-mode')); if (!this.isUndefined(args.local)) { let local = false; - if (String(args.local).toLowerCase() === "true" || !this.isUndefined(args.local_mode)) { + if (String(args.local).toLowerCase() === 'true') { local = true; - bsConfig.connection_settings.local_inferred = localInferred; } - 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") { + if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === 'true') { local = true; - bsConfig.connection_settings.local_inferred = localInferred; } - bsConfig["connection_settings"]["local"] = local; + 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(args.localMode)) { + bsConfig['connection_settings']['local'] = true; + bsConfig.connection_settings.local_inferred = localInferred; } }; @@ -369,6 +370,9 @@ exports.setLocalIdentifier = (bsConfig, args) => { 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) && args.localMode == 'always-on') { local_mode = 'always-on'; } else if ( @@ -386,7 +390,7 @@ exports.setLocalMode = (bsConfig, args) => { let localModeInferred = !(this.searchForOption('--local-mode')); - if (localModeInferred) { + if (localModeInferred && localModeUndefined) { bsConfig.connection_settings.local_mode_inferred = local_mode; } } diff --git a/bin/templates/configTemplate.js b/bin/templates/configTemplate.js index 8593abc6..192983d4 100644 --- a/bin/templates/configTemplate.js +++ b/bin/templates/configTemplate.js @@ -65,7 +65,9 @@ module.exports = function () { }, "connection_settings": { "local": false, - "local_identifier": null + "local_identifier": null, + "local_mode": null, + "local_config_file": null }, "disable_usage_reporting": false } diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index c1af83d5..4ddcce3c 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -671,14 +671,14 @@ describe('utils', () => { delete process.env.BROWSERSTACK_LOCAL; }); - it('bsconfig connection_settings local_inferred as true if serachforOption returns false with args local true', () => { + it('bsconfig connection_settings local_inferred as true if serachforOption returns false with args local-mode true', () => { let bsConfig = { connection_settings: { + "local": false } }; let args = { - local: true, - local_mode: false + localMode: "always-on" }; let searchForOptionStub = sinon.stub(utils,"searchForOption"); searchForOptionStub.returns(false); @@ -722,21 +722,6 @@ describe('utils', () => { expect(bsConfig.connection_settings.local).to.be.eq(false); }); - it('should change local_inferred to true in bsConfig if process.env.BROWSERSTACK_LOCAL is set to true', () => { - let bsConfig = { - connection_settings: { - local: false, - local_inferred: false, - }, - }; - let args = {}; - process.env.BROWSERSTACK_LOCAL = true; - let searchForOptionStub = sinon.stub(utils, 'searchForOption'); - searchForOptionStub.returns(false); - utils.setLocal(bsConfig, args); - expect(bsConfig.connection_settings.local_inferred).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: { @@ -784,7 +769,7 @@ describe('utils', () => { it('if bsconfig local mode is not always-on then local_mode should be on-demand', () => { let bsConfig = { connection_settings: { - local: true + local: true, }, }; let args = {}; From 6210a6c65bb5550c80e0a75d673778851f51547d Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 5 Mar 2021 15:18:10 +0530 Subject: [PATCH 29/38] Local Start fail error. --- bin/commands/runs.js | 12 ++++++++---- bin/helpers/constants.js | 3 ++- bin/helpers/utils.js | 9 ++++++--- test/unit/bin/helpers/utils.js | 2 +- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index e5535a01..fb9af132 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -119,11 +119,15 @@ module.exports = function run(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'); + } }); }).catch(function (err) { // Zipping failed diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index b9857f02..f1c70514 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -37,7 +37,8 @@ const userMessages = { FATAL_NETWORK_ERROR: `fatal: unable to access '${config.buildUrl}': Could not resolve host: ${config.rails_host}`, RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`, CHECK_DASHBOARD_AT: "Please check the build status at: ", - CYPRESS_VERSION_CHANGED: "Your build will run using Cypress instead of Cypress . Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions" + CYPRESS_VERSION_CHANGED: "Your build will run using Cypress instead of Cypress . Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions", + LOCAL_START_FAILED: "Local Testing setup failed." }; const validationMessages = { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index da8daf28..b418e08b 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -420,12 +420,15 @@ exports.setupLocalTesting = (bsConfig, args) => { Constants.messageTypes.ERROR, errorCode ); - reject(localStartError); + reject(Constants.userMessages.LOCAL_START_FAILED); } }); - } + } else { + resolve(); + } + } else { + resolve(); } - resolve(); }); }; diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 4ddcce3c..54a90ec5 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -860,7 +860,7 @@ describe('utils', () => { return 'end'; }); utils.setupLocalTesting(bsConfig,args).catch((error) => { - sinon.match(error, "Key is required to start local testing!") + expect(error).to.eq(constant.userMessages.LOCAL_START_FAILED); sinon.assert.calledOnce(sendUsageReportStub); sinon.assert.calledOnce(getLocalBinaryStub); }); From a8ebf1e3aa7c24f2c62b801c0d08d905f48ac14b Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 8 Mar 2021 16:34:27 +0530 Subject: [PATCH 30/38] Fix Local Inferred logic --- bin/helpers/utils.js | 5 ++++- test/unit/bin/helpers/utils.js | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index b418e08b..99bc2eda 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -342,7 +342,10 @@ exports.setLocal = (bsConfig, args) => { logger.info( 'Reading local setting from the environment variable BROWSERSTACK_LOCAL' ); - } else if (!this.isUndefined(args.localMode)) { + } 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; } diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 54a90ec5..d0678e9d 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -674,7 +674,6 @@ describe('utils', () => { it('bsconfig connection_settings local_inferred as true if serachforOption returns false with args local-mode true', () => { let bsConfig = { connection_settings: { - "local": false } }; let args = { From eb75a45a3836382fc22624ec457ddc56c876dd41 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 8 Mar 2021 17:42:24 +0530 Subject: [PATCH 31/38] Fixed local_mode not set to always-on when local_identifier is supplied in browserstack.json --- bin/helpers/utils.js | 5 +++++ test/unit/bin/helpers/utils.js | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 99bc2eda..4da6136e 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -362,6 +362,11 @@ exports.setLocalIdentifier = (bsConfig, args) => { "Reading local identifier from the environment variable 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"]) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index d0678e9d..1ec829e6 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1114,7 +1114,19 @@ describe('utils', () => { 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'); }); }); From c7a3b6588f0f1d6a155b0d69bc98638c66921ffd Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 8 Mar 2021 19:51:52 +0530 Subject: [PATCH 32/38] Send local_identifier_error when local_identifier not running in stopBinary --- bin/helpers/constants.js | 3 ++- bin/helpers/utils.js | 18 ++++++++++++++++-- test/unit/bin/helpers/utils.js | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index f1c70514..ed9f13b9 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -38,7 +38,8 @@ const userMessages = { RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`, CHECK_DASHBOARD_AT: "Please check the build status at: ", CYPRESS_VERSION_CHANGED: "Your build will run using Cypress instead of Cypress . Read more about supported versions here: http://browserstack.com/docs/automate/cypress/supported-versions", - LOCAL_START_FAILED: "Local Testing setup failed." + LOCAL_START_FAILED: "Local Testing setup failed.", + LOCAL_STOP_FAILED: "Local Binary stop failed." }; const validationMessages = { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 4da6136e..3c70a00b 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -441,7 +441,21 @@ exports.setupLocalTesting = (bsConfig, args) => { }; exports.stopLocalBinary = (bsConfig, bs_local, args) => { - return new Promise((resolve, reject) => { + 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) { @@ -457,7 +471,7 @@ exports.stopLocalBinary = (bsConfig, bs_local, args) => { Constants.messageTypes.ERROR, errorCode ); - resolve(localStopError); + resolve(Constants.userMessages.LOCAL_STOP_FAILED); } }); } else { diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 1ec829e6..505c2cc1 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -961,8 +961,16 @@ describe('utils', () => { 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); }); }); @@ -976,6 +984,8 @@ describe('utils', () => { 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); }); @@ -991,6 +1001,8 @@ describe('utils', () => { 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); }); @@ -1008,6 +1020,8 @@ describe('utils', () => { 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); }); @@ -1022,6 +1036,8 @@ describe('utils', () => { 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 @@ -1032,7 +1048,7 @@ describe('utils', () => { return 'end'; }); return utils.stopLocalBinary(bsConfig, bs_local, {}).then((result) => { - expect(result).to.be.eq(error); + expect(result).to.be.eq(constant.userMessages.LOCAL_STOP_FAILED); sinon.assert.calledOnce(sendUsageReportStub); sinon.assert.calledOnce(stopStub); }); From 710bd53a4be9c79a8626fdcff43478be8851f2b7 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 8 Mar 2021 20:37:46 +0530 Subject: [PATCH 33/38] Local mode and id validation --- bin/helpers/capabilityHelper.js | 4 +++- bin/helpers/constants.js | 5 +++-- bin/helpers/utils.js | 4 ++-- test/unit/bin/helpers/utils.js | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index a7855e03..c03f6dbb 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -160,7 +160,9 @@ const validate = (bsConfig, args) => { // 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_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); diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index ed9f13b9..beda2e16 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -60,9 +60,10 @@ const validationMessages = { INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication", LOCAL_NOT_SET: "To test 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.", - INVALID_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. \n--local-identifier .\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference", + INVALID_CLI_LOCAL_IDENTIFIER: "When using --local-identifier, a value needs to be supplied. \n--local-identifier .\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: "When using --local-config-file, a value needs to be supplied. \n--local-config-file \"path to local-config-file.yaml\".\nFor more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference" + INVALID_LOCAL_CONFIG_FILE: "When using --local-config-file, a value needs to be supplied. \n--local-config-file \"path to local-config-file.yaml\".\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" }; const cliMessages = { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 3c70a00b..d35e9a09 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -385,7 +385,7 @@ exports.setLocalMode = (bsConfig, args) => { local_mode = 'always-on'; } else if ( !this.isUndefined(bsConfig['connection_settings']['local_mode']) && - bsConfig['connection_settings']['local_mode'].toLowerCase() === + String(bsConfig['connection_settings']['local_mode']).toLowerCase() === 'always-on' ) { local_mode = 'always-on'; @@ -611,7 +611,7 @@ exports.isJSONInvalid = (err, args) => { return false } - if( err === Constants.validationMessages.INVALID_LOCAL_IDENTIFIER || err === Constants.validationMessages.INVALID_LOCAL_MODE ){ + if( err === Constants.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER || err === Constants.validationMessages.INVALID_LOCAL_MODE ){ return false } diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 505c2cc1..9fbc515d 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1604,7 +1604,7 @@ describe('utils', () => { }); it('JSON is invalid if local identifier is invalid', () =>{ - let error = constant.validationMessages.INVALID_LOCAL_IDENTIFIER; + let error = constant.validationMessages.INVALID_CLI_LOCAL_IDENTIFIER; expect(utils.isJSONInvalid(error,{})).to.eq(false); }); From c56466d7e88a06aeb9218fa23caff97df59aae64 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 8 Mar 2021 20:59:25 +0530 Subject: [PATCH 34/38] Added test cases for local testing bug fixes --- bin/helpers/utils.js | 3 +++ test/unit/bin/helpers/utils.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index d35e9a09..371c5b71 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -61,6 +61,9 @@ exports.getErrorCodeFromMsg = (errMsg) => { 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; diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 9fbc515d..1cdd615a 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -81,6 +81,11 @@ describe('utils', () => { 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 From 15de10a3307268ea2aeaea853d82e76f4726eb27 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 9 Mar 2021 14:09:53 +0530 Subject: [PATCH 35/38] Warning message in case of local_mode is invalid --- bin/helpers/capabilityHelper.js | 3 +++ bin/helpers/constants.js | 3 ++- bin/helpers/utils.js | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index c03f6dbb..0872f6b8 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -68,6 +68,9 @@ const caps = (bsConfig, zip) => { // 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.`); } diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index beda2e16..e0a289c6 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -39,7 +39,8 @@ const userMessages = { CHECK_DASHBOARD_AT: "Please check the build status at: ", CYPRESS_VERSION_CHANGED: "Your build will run using Cypress instead of Cypress . 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." + 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" }; const validationMessages = { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 371c5b71..b27c8b16 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -386,6 +386,8 @@ exports.setLocalMode = (bsConfig, args) => { if (!this.isUndefined(args.localMode) && 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() === From b33cc0dffc2ac0f28f8b8ab1f8ed974f390ed27f Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 9 Mar 2021 16:48:21 +0530 Subject: [PATCH 36/38] Updated message for invalid local config file --- bin/helpers/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index e0a289c6..17eb1afc 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -63,7 +63,7 @@ const validationMessages = { 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 .\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: "When using --local-config-file, a value needs to be supplied. \n--local-config-file \"path to local-config-file.yaml\".\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" }; From 0bf70fe4120af122852b92c1c213b67cbdd0ee63 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 10 Mar 2021 18:31:05 +0530 Subject: [PATCH 37/38] Fixed cli args precendence on-demand bug --- bin/helpers/utils.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index b27c8b16..1cf1f8b0 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -384,8 +384,10 @@ exports.setLocalMode = (bsConfig, args) => { let localModeUndefined= this.isUndefined(bsConfig["connection_settings"]["local_mode"]); - if (!this.isUndefined(args.localMode) && args.localMode == 'always-on') { - local_mode = 'always-on'; + 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 ( From fb5f69cd52233c369155dc3ecb56bde3f34d5dfe Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 10 Mar 2021 19:54:23 +0530 Subject: [PATCH 38/38] Updating version to 1.8.0 --- bin/helpers/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 1cf1f8b0..e61ee06d 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -264,7 +264,7 @@ exports.isParallelValid = (value) => { } exports.getUserAgent = () => { - return `BStack-Cypress-CLI/1.7.2 (${os.arch()}/${os.platform()}/${os.release()})`; + return `BStack-Cypress-CLI/1.8.0 (${os.arch()}/${os.platform()}/${os.release()})`; }; exports.isAbsolute = (configPath) => {