From 6c20b8bc618397b1e4aebe44b73f0a64ab5ee855 Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Tue, 28 Nov 2023 15:54:38 +0530 Subject: [PATCH 1/9] Changes for enforce_settings to enforce run_settings over cypress conf --- bin/commands/runs.js | 10 +++++++++- bin/helpers/capabilityHelper.js | 10 +++++++++- bin/helpers/constants.js | 4 ++++ bin/helpers/packageInstaller.js | 5 ++++- bin/helpers/utils.js | 28 ++++++++++++++++++++++++++-- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index e198d291..9085efd6 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -186,7 +186,7 @@ module.exports = function run(args, rawArgs) { let specFiles = utils.getNumberOfSpecFiles(bsConfig, args, cypressConfigFile); markBlockEnd('getNumberOfSpecFiles'); - bsConfig['run_settings']['video_config'] = utils.getVideoConfig(cypressConfigFile); + bsConfig['run_settings']['video_config'] = utils.getVideoConfig(cypressConfigFile, bsConfig); // return the number of parallels user specified let userSpecifiedParallels = utils.getParallels(bsConfig, args); @@ -248,6 +248,14 @@ module.exports = function run(args, rawArgs) { if (process.env.BROWSERSTACK_TEST_ACCESSIBILITY === 'true') { supportFileCleanup(); } + // Set config args for enforce_settings + if ( !utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) ) { + markBlockStart('setEnforceSettingsConfig'); + logger.debug('Started setting the configs'); + utils.setEnforceSettingsConfig(bsConfig); + logger.debug('Completed setting the configs'); + markBlockEnd('setEnforceSettingsConfig'); + } // Create build //setup Local Testing markBlockStart('localSetup'); diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 968605cf..f2e2df93 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -184,6 +184,10 @@ const validate = (bsConfig, args) => { reject(Constants.validationMessages.EMPTY_CYPRESS_CONFIG_FILE); } + if ( bsConfig && bsConfig.run_settings && bsConfig.run_settings.enforce_settings && bsConfig.run_settings.enforce_settings.toString() === 'true' && Utils.isUndefined(bsConfig.run_settings.specs) ) { + reject(Constants.validationMessages.EMPTY_SPECS_IN_BROWSERSTACK_JSON); + } + // validate parallels specified in browserstack.json if parallels are not specified via arguments if (!Utils.isUndefined(args) && Utils.isUndefined(args.parallels) && !Utils.isParallelValid(bsConfig.run_settings.parallels)) reject(Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION); @@ -214,7 +218,8 @@ const validate = (bsConfig, args) => { logger.debug(`Validating ${bsConfig.run_settings.cypress_config_filename}`); try { - if (bsConfig.run_settings.cypress_config_filename !== 'false') { + // Not reading cypress config file upon enforce_settings + if (Utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && bsConfig.run_settings.cypress_config_filename !== 'false') { if (bsConfig.run_settings.cypressTestSuiteType === Constants.CYPRESS_V10_AND_ABOVE_TYPE) { const completeCypressConfigFile = readCypressConfigFile(bsConfig) if (!Utils.isUndefined(completeCypressConfigFile)) { @@ -234,6 +239,9 @@ const validate = (bsConfig, args) => { // Detect if the user is not using the right directory structure, and throw an error if (!Utils.isUndefined(cypressConfigFile.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,cypressConfigFile.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE); } + logger.debug("Validating baseurl and integrationFolder in browserstack.json"); + if (!Utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !Utils.isUndefined(bsConfig.run_settings.baseUrl) && bsConfig.run_settings.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET.replace("", bsConfig.run_settings.baseUrl)); + if (!Utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !Utils.isUndefined(bsConfig.run_settings.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,bsConfig.run_settings.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE); } catch(error){ reject(Constants.validationMessages.INVALID_CYPRESS_JSON) } diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 70dac61c..a2f2ebfd 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -70,6 +70,8 @@ const userMessages = { UPLOADING_TESTS_SUCCESS: "Uploaded tests successfully", UPLOADING_NPM_PACKAGES: "Uploading required node_modules to BrowserStack", UPLOADING_NPM_PACKAGES_SUCCESS: "Uploaded node_modules successfully", + SKIP_CYPRESSCONFIG_INSTALL: + "Skipping Cypress Config Install as the enforce_settings has been passed.", SKIP_UPLOADING_TESTS: "Skipping zip upload since BrowserStack already has your test suite that has not changed since the last run.", SKIP_UPLOADING_NPM_PACKAGES: @@ -134,6 +136,8 @@ const validationMessages = { "cypress_proj_dir is not set in run_settings. See https://www.browserstack.com/docs/automate/cypress/sample-tutorial to learn more.", EMPTY_CYPRESS_CONFIG_FILE: "cypress_config_file is not set in run_settings. See https://www.browserstack.com/docs/automate/cypress/configuration-file to learn more.", + EMPTY_SPECS_IN_BROWSERSTACK_JSON: + "No specs have been provided in run_settings. It is required to be passed on browserstack.json if enforce_settings is set.", VALIDATED: "browserstack.json file is validated", NOT_VALID: "browerstack.json is not valid", NOT_VALID_JSON: "browerstack.json is not a valid json", diff --git a/bin/helpers/packageInstaller.js b/bin/helpers/packageInstaller.js index 35850237..b5b43493 100644 --- a/bin/helpers/packageInstaller.js +++ b/bin/helpers/packageInstaller.js @@ -133,7 +133,10 @@ const packageSetupAndInstaller = (bsConfig, packageDir, instrumentBlocks) => { let obj = { packagesInstalled: false }; - + if (bsConfig && bsConfig.run_settings && bsConfig.run_settings.enforce_settings && bsConfig.run_settings.enforce_settings.toString() === 'true' ) { + logger.info(Constants.userMessages.SKIP_NPM_INSTALL); + return resolve(obj); + } logger.info(Constants.userMessages.NPM_INSTALL); instrumentBlocks.markBlockStart("packageInstaller.folderSetup"); logger.debug("Started setting up package folder"); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 7c608280..fc49e67f 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -628,6 +628,8 @@ exports.isPositiveInteger = (str) => { exports.isTrueString = value => (!this.isUndefined(value) && value.toString().toLowerCase() === 'true'); +exports.isUndefinedOrFalse = value => ( this.isUndefined(value) || value.toString().toLowerCase() === 'false'); + exports.isFloat = (value) => Number(value) && Number(value) % 1 !== 0; exports.isInteger = (value) => Number.isInteger(value); @@ -1077,7 +1079,8 @@ exports.getNumberOfSpecFiles = (bsConfig, args, cypressConfig) => { if (bsConfig.run_settings.cypressTestSuiteType === Constants.CYPRESS_V10_AND_ABOVE_TYPE) { defaultSpecFolder = Constants.DEFAULT_CYPRESS_10_SPEC_PATH testFolderPath = defaultSpecFolder - if(!this.isUndefined(cypressConfig) && !this.isUndefined(cypressConfig.e2e)) { + // Read cypress config if enforce_settings is not present + if(this.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !this.isUndefined(cypressConfig) && !this.isUndefined(cypressConfig.e2e)) { if(!this.isUndefined(cypressConfig.e2e.specPattern)) { globCypressConfigSpecPatterns = Array.isArray(cypressConfig.e2e.specPattern) ? cypressConfig.e2e.specPattern : [cypressConfig.e2e.specPattern]; @@ -1286,6 +1289,24 @@ exports.setConfig = (bsConfig, args) => { } } +// set configs if enforce_settings is passed +exports.setEnforceSettingsConfig = (bsConfig) => { + let config_args = (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.config)) ? bsConfig.run_settings.config : undefined; + if ( this.isUndefined(config_args) || !config_args.includes("video") ) { + let video_args = (this.isUndefined(bsConfig.run_settings.video_config) || this.isUndefined(bsConfig.run_settings.video_config.video) || !bsConfig.run_settings.video_config.video ) ? 'video=false' : 'video=true' ; + video_args += (this.isUndefined(bsConfig.run_settings.video_config) || this.isUndefined(bsConfig.run_settings.video_config.videoUploadOnPasses) || !bsConfig.run_settings.video_config.videoUploadOnPasses ) ? ',videoUploadOnPasses=false' : ',videoUploadOnPasses=true'; + config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; + logger.debug(`Setting video_args for enforce_settings to ${video_args}`); + } + if ( this.isUndefined(config_args) || !config_args.includes("baseUrl") ) { + let base_url_args = (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.config)) ? "baseUrl='"+bsConfig.run_settings.baseUrl+"'" : "baseUrl=''"; + config_args = this.isUndefined(config_args) ? base_url_args : config_args + ',' + base_url_args; + logger.debug(`Setting base_url_args for enforce_settings to ${base_url_args}`); + } + if ( !this.isUndefined(config_args) ) bsConfig["run_settings"]["config"] = config_args; + logger.debug(`Setting conifg_args for enforce_settings to ${config_args}`); +} + // blindly send other passed configs with run_settings and handle at backend exports.setOtherConfigs = (bsConfig, args) => { if(isTestObservabilitySession() && process.env.BS_TESTOPS_JWT) { @@ -1499,11 +1520,14 @@ exports.fetchFolderSize = async (dir) => { } } -exports.getVideoConfig = (cypressConfig) => { +exports.getVideoConfig = (cypressConfig, bsConfig = {}) => { let conf = { video: true, videoUploadOnPasses: true } + // Reading from bsconfig first to give precedance and cypress config will be empty in case of enforce_settings + if (!this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; + if (!this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; if (!this.isUndefined(cypressConfig.video)) conf.video = cypressConfig.video; if (!this.isUndefined(cypressConfig.videoUploadOnPasses)) conf.videoUploadOnPasses = cypressConfig.videoUploadOnPasses; From fab5b000fd2c348426c405b0c2656e5430b44ac7 Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Wed, 29 Nov 2023 11:03:43 +0530 Subject: [PATCH 2/9] Spec addition --- bin/helpers/constants.js | 4 +- bin/helpers/packageInstaller.js | 3 +- bin/helpers/utils.js | 25 +++++++--- test/unit/bin/commands/runs.js | 10 ++++ test/unit/bin/helpers/capabilityHelper.js | 34 +++++++++++++ test/unit/bin/helpers/utils.js | 59 +++++++++++++++++++++++ 6 files changed, 126 insertions(+), 9 deletions(-) diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index a2f2ebfd..85cc91b1 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -74,6 +74,8 @@ const userMessages = { "Skipping Cypress Config Install as the enforce_settings has been passed.", SKIP_UPLOADING_TESTS: "Skipping zip upload since BrowserStack already has your test suite that has not changed since the last run.", + SKIP_NPM_INSTALL: + "Skipping NPM Install as the enforce_settings has been passed.", SKIP_UPLOADING_NPM_PACKAGES: "Skipping the upload of node_modules since BrowserStack has already cached your npm dependencies that have not changed since the last run.", LOCAL_TRUE: "you will now be able to test localhost / private URLs", @@ -137,7 +139,7 @@ const validationMessages = { EMPTY_CYPRESS_CONFIG_FILE: "cypress_config_file is not set in run_settings. See https://www.browserstack.com/docs/automate/cypress/configuration-file to learn more.", EMPTY_SPECS_IN_BROWSERSTACK_JSON: - "No specs have been provided in run_settings. It is required to be passed on browserstack.json if enforce_settings is set.", + "specs is required when enforce_settings is true in run_settings of browserstack.json", VALIDATED: "browserstack.json file is validated", NOT_VALID: "browerstack.json is not valid", NOT_VALID_JSON: "browerstack.json is not a valid json", diff --git a/bin/helpers/packageInstaller.js b/bin/helpers/packageInstaller.js index b5b43493..1cdc3ea4 100644 --- a/bin/helpers/packageInstaller.js +++ b/bin/helpers/packageInstaller.js @@ -134,7 +134,8 @@ const packageSetupAndInstaller = (bsConfig, packageDir, instrumentBlocks) => { packagesInstalled: false }; if (bsConfig && bsConfig.run_settings && bsConfig.run_settings.enforce_settings && bsConfig.run_settings.enforce_settings.toString() === 'true' ) { - logger.info(Constants.userMessages.SKIP_NPM_INSTALL); + logger.info("Enforce_settings is enabled in run_settings"); + logger.debug(Constants.userMessages.SKIP_NPM_INSTALL); return resolve(obj); } logger.info(Constants.userMessages.NPM_INSTALL); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index fc49e67f..87215414 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -434,7 +434,8 @@ exports.setProjectId = (bsConfig, args, cypressConfigFile) => { } else if(!this.isUndefined(bsConfig.run_settings["projectId"])) { return bsConfig.run_settings["projectId"]; } else { - if (!this.isUndefined(cypressConfigFile) && !this.isUndefined(cypressConfigFile["projectId"])) { + // ignore reading cypressconfig if enforce_settings is passed + if (this.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !this.isUndefined(cypressConfigFile) && !this.isUndefined(cypressConfigFile["projectId"])) { return cypressConfigFile["projectId"]; } } @@ -1298,11 +1299,19 @@ exports.setEnforceSettingsConfig = (bsConfig) => { config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; logger.debug(`Setting video_args for enforce_settings to ${video_args}`); } - if ( this.isUndefined(config_args) || !config_args.includes("baseUrl") ) { - let base_url_args = (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.config)) ? "baseUrl='"+bsConfig.run_settings.baseUrl+"'" : "baseUrl=''"; + if ( (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.baseUrl)) && (this.isUndefined(config_args) || !config_args.includes("baseUrl")) ) { + let base_url_args = 'baseUrl='+bsConfig.run_settings.baseUrl; config_args = this.isUndefined(config_args) ? base_url_args : config_args + ',' + base_url_args; logger.debug(`Setting base_url_args for enforce_settings to ${base_url_args}`); } + // set specs in config of specpattern to override cypress config + if(!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.specs)) { + let spec_pattern_args = "specPattern='"+bsConfig.run_settings.specs+"'"; + if( bsConfig.run_settings.cypressTestSuiteType !== Constants.CYPRESS_V10_AND_ABOVE_TYPE) { + spec_pattern_args = "testFiles='"+bsConfig.run_settings.specs+"'"; + } + config_args = this.isUndefined(config_args) ? spec_pattern_args : config_args + ',' + spec_pattern_args; + } if ( !this.isUndefined(config_args) ) bsConfig["run_settings"]["config"] = config_args; logger.debug(`Setting conifg_args for enforce_settings to ${config_args}`); } @@ -1526,10 +1535,12 @@ exports.getVideoConfig = (cypressConfig, bsConfig = {}) => { videoUploadOnPasses: true } // Reading from bsconfig first to give precedance and cypress config will be empty in case of enforce_settings - if (!this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; - if (!this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; - if (!this.isUndefined(cypressConfig.video)) conf.video = cypressConfig.video; - if (!this.isUndefined(cypressConfig.videoUploadOnPasses)) conf.videoUploadOnPasses = cypressConfig.videoUploadOnPasses; + if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; + if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; + if ( this.isUndefined(bsConfig.run_settings) || this.isUndefined(bsConfig.run_settings.enforce_settings) ) { + if (!this.isUndefined(cypressConfig.video)) conf.video = cypressConfig.video; + if (!this.isUndefined(cypressConfig.videoUploadOnPasses)) conf.videoUploadOnPasses = cypressConfig.videoUploadOnPasses; + } logger.debug(`Setting video = ${conf.video}`); logger.debug(`Setting videoUploadOnPasses = ${conf.videoUploadOnPasses}`); diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index aa4a9e8e..b84513ba 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -713,6 +713,8 @@ describe("runs", () => { stopLocalBinaryStub = sandbox.stub(); setLocalConfigFileStub = sandbox.stub(); setConfigStub = sandbox.stub(); + setEnforceSettingsConfigStub = sandbox.stub(); + isUndefinedOrFalseStub = sandbox.stub(); setBrowsersStub = sandbox.stub(); setCLIModeStub = sandbox.stub(); fetchZipSizeStub = sandbox.stub(); @@ -773,6 +775,8 @@ describe("runs", () => { setLocalConfigFile: setLocalConfigFileStub, setBrowsers: setBrowsersStub, setConfig: setConfigStub, + setEnforceSettingsConfig: setEnforceSettingsConfigStub, + isUndefinedOrFalse: isUndefinedOrFalseStub, setCLIMode: setCLIModeStub, fetchZipSize: fetchZipSizeStub, setGeolocation: setGeolocationStub, @@ -882,6 +886,7 @@ describe("runs", () => { sinon.assert.calledTwice(fetchZipSizeStub); sinon.assert.calledOnce(fetchFolderSizeStub); sinon.assert.calledOnce(zipUploadStub); + sinon.assert.calledOnce(isUndefinedOrFalseStub); sinon.assert.calledOnce(createBuildStub); sinon.assert.calledOnce(stopLocalBinaryStub); sinon.assert.calledOnceWithExactly( @@ -939,6 +944,7 @@ describe("runs", () => { deleteResultsStub = sandbox.stub(); setDefaultsStub = sandbox.stub(); isUndefinedStub = sandbox.stub(); + isUndefinedOrFalseStub = sandbox.stub(); setLocalStub = sandbox.stub(); setLocalModeStub = sandbox.stub(); setupLocalTestingStub = sandbox.stub(); @@ -954,6 +960,7 @@ describe("runs", () => { markBlockStartStub = sandbox.stub(); markBlockEndStub = sandbox.stub(); setConfigStub = sandbox.stub(); + setEnforceSettingsConfigStub = sandbox.stub(); setBrowsersStub = sandbox.stub(); stopLocalBinaryStub = sandbox.stub(); nonEmptyArrayStub = sandbox.stub(); @@ -1021,6 +1028,8 @@ describe("runs", () => { setLocalConfigFile: setLocalConfigFileStub, setBrowsers: setBrowsersStub, setConfig: setConfigStub, + setEnforceSettingsConfig: setEnforceSettingsConfigStub, + isUndefinedOrFalse: isUndefinedOrFalseStub, stopLocalBinary: stopLocalBinaryStub, nonEmptyArray: nonEmptyArrayStub, checkError: checkErrorStub, @@ -1150,6 +1159,7 @@ describe("runs", () => { sinon.assert.calledTwice(fetchZipSizeStub); sinon.assert.calledOnce(fetchFolderSizeStub); sinon.assert.calledOnce(zipUploadStub); + sinon.assert.calledOnce(isUndefinedOrFalseStub); sinon.assert.calledOnce(createBuildStub); sinon.assert.calledOnce(setProcessHooksStub); sinon.assert.calledOnce(exportResultsStub); diff --git a/test/unit/bin/helpers/capabilityHelper.js b/test/unit/bin/helpers/capabilityHelper.js index 68e47ae1..490d3dee 100644 --- a/test/unit/bin/helpers/capabilityHelper.js +++ b/test/unit/bin/helpers/capabilityHelper.js @@ -925,6 +925,40 @@ describe("capabilityHelper.js", () => { }); }); + it("validate bsConfig.run_settings.enforce_settings", () => { + let bsConfig = { + auth: {}, + browsers: [ + { + browser: "chrome", + os: "Windows 10", + versions: ["78", "77"], + }, + ], + run_settings: { + cypress_proj_dir: "random path", + cypressConfigFilePath: "random path", + cypressProjectDir: "random path", + cypress_config_filename: "cypress.json", + spec_timeout: 10, + cypressTestSuiteType: Constants.CYPRESS_V9_AND_OLDER_TYPE, + enforce_settings: true + }, + }; + + return capabilityHelper + .validate(bsConfig, { parallels: undefined }) + .then(function (data) { + chai.assert.fail("Promise error"); + }) + .catch((error) => { + chai.assert.equal( + error, + Constants.validationMessages.EMPTY_SPECS_IN_BROWSERSTACK_JSON + ); + }); + }); + it("resolve with proper message", () => { let bsConfig = { auth: {}, diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index f2751d76..0212881b 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -3055,6 +3055,49 @@ describe('utils', () => { }); }); + describe('setEnforceSettingsConfig', () => { + it('the video config should be assigned to bsconfig run_settings config', () => { + let bsConfig = { + run_settings: { video_config: { video:true, videoUploadOnPasses:true} }, + }; + let args = { + config: 'video=true,videoUploadOnPasses=true' + } + utils.setEnforceSettingsConfig(bsConfig); + expect(args.config).to.be.eql(bsConfig.run_settings.config); + }); + it('the specPattern config should be assigned to bsconfig run_settings config', () => { + let bsConfig = { + run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V10_AND_ABOVE_TYPE' }, + }; + let args = { + config: "video=false,videoUploadOnPasses=false,specPattern='somerandomspecs'" + } + utils.setEnforceSettingsConfig(bsConfig); + expect(args.config).to.be.eql(bsConfig.run_settings.config); + }); + it('the testFiles config should be assigned to bsconfig run_settings config', () => { + let bsConfig = { + run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V9_AND_OLDER_TYPE' }, + }; + let args = { + config: "video=false,videoUploadOnPasses=false,testFiles='somerandomspecs'" + } + utils.setEnforceSettingsConfig(bsConfig); + expect(args.config).to.be.eql(bsConfig.run_settings.config); + }); + it('the baseUrl config should be assigned to bsconfig run_settings config', () => { + let bsConfig = { + run_settings: { baseUrl: 'http://localhost:8080' }, + }; + let args = { + config: 'video=false,videoUploadOnPasses=false,baseUrl=http://localhost:8080' + } + utils.setEnforceSettingsConfig(bsConfig); + expect(args.config).to.be.eql(bsConfig.run_settings.config); + }); + }); + describe('generateUniqueHash', () => { beforeEach(() => { let interfaceList = { @@ -3419,6 +3462,22 @@ describe('utils', () => { expect(utils.getVideoConfig({videoUploadOnPasses: false})).to.be.eql({video: true, videoUploadOnPasses: false}); expect(utils.getVideoConfig({video: false, videoUploadOnPasses: false})).to.be.eql({video: false, videoUploadOnPasses: false}); }); + + it('should return default hash and ignore video config in cypress config if enforce_settings is passed by the user', () => { + expect(utils.getVideoConfig({video: false}, {run_settings: {enforce_settings: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); + expect(utils.getVideoConfig({videoUploadOnPasses: false}, {run_settings: {enforce_settings: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); + expect(utils.getVideoConfig({video: false, videoUploadOnPasses: false}, {run_settings: {enforce_settings: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); + }); + + it('should return bsconfig value and ignore video config in cypress config if enforce_settings is passed by the user', () => { + expect(utils.getVideoConfig({video: true}, {run_settings: {enforce_settings: true, video: false }})).to.be.eql({video: false, videoUploadOnPasses: true}); + expect(utils.getVideoConfig({videoUploadOnPasses: true}, {run_settings: {enforce_settings: true, videoUploadOnPasses: false}})).to.be.eql({video: true, videoUploadOnPasses: false}); + expect(utils.getVideoConfig({video: true, videoUploadOnPasses: true}, {run_settings: {enforce_settings: true, video: false, videoUploadOnPasses: false}})).to.be.eql({video: false, videoUploadOnPasses: false}); + expect(utils.getVideoConfig({video: false}, {run_settings: {enforce_settings: true, video: true }})).to.be.eql({video: true, videoUploadOnPasses: true}); + expect(utils.getVideoConfig({videoUploadOnPasses: false}, {run_settings: {enforce_settings: true, videoUploadOnPasses: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); + expect(utils.getVideoConfig({video: false, videoUploadOnPasses: false}, {run_settings: {enforce_settings: true, video: true, videoUploadOnPasses: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); + }); + }); describe('setNetworkLogs', () => { From 19f083d050d59e5c2783dafad84fd53fbdcc1c04 Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Wed, 29 Nov 2023 13:09:56 +0530 Subject: [PATCH 3/9] Specpattern quote fix for windows --- bin/helpers/utils.js | 4 ++-- test/unit/bin/helpers/utils.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 87215414..6f979d71 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1306,9 +1306,9 @@ exports.setEnforceSettingsConfig = (bsConfig) => { } // set specs in config of specpattern to override cypress config if(!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.specs)) { - let spec_pattern_args = "specPattern='"+bsConfig.run_settings.specs+"'"; + let spec_pattern_args = 'specPattern="'+bsConfig.run_settings.specs+'"'; if( bsConfig.run_settings.cypressTestSuiteType !== Constants.CYPRESS_V10_AND_ABOVE_TYPE) { - spec_pattern_args = "testFiles='"+bsConfig.run_settings.specs+"'"; + spec_pattern_args = 'testFiles="'+bsConfig.run_settings.specs+'"'; } config_args = this.isUndefined(config_args) ? spec_pattern_args : config_args + ',' + spec_pattern_args; } diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 0212881b..7d7e28db 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -3071,7 +3071,7 @@ describe('utils', () => { run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V10_AND_ABOVE_TYPE' }, }; let args = { - config: "video=false,videoUploadOnPasses=false,specPattern='somerandomspecs'" + config: 'video=false,videoUploadOnPasses=false,specPattern="somerandomspecs"' } utils.setEnforceSettingsConfig(bsConfig); expect(args.config).to.be.eql(bsConfig.run_settings.config); @@ -3081,7 +3081,7 @@ describe('utils', () => { run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V9_AND_OLDER_TYPE' }, }; let args = { - config: "video=false,videoUploadOnPasses=false,testFiles='somerandomspecs'" + config: 'video=false,videoUploadOnPasses=false,testFiles="somerandomspecs"' } utils.setEnforceSettingsConfig(bsConfig); expect(args.config).to.be.eql(bsConfig.run_settings.config); From 489f23652a07266eda3f28dda464b1d09b4d31dd Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Wed, 29 Nov 2023 15:45:15 +0530 Subject: [PATCH 4/9] Spec addition --- test/unit/bin/commands/runs.js | 362 +++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index b84513ba..56a6582f 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -15,6 +15,8 @@ describe("runs", () => { let args = testObjects.runSampleArgs; let rawArgs = testObjects.runSampleRawArgs; let bsConfig = testObjects.sampleBsConfig; + let bsConfigWithEnforceSettings = testObjects.sampleBsConfig; + bsConfigWithEnforceSettings.enforce_settings = true; describe("handle browserstack.json not valid", () => { var sandbox; @@ -901,6 +903,170 @@ describe("runs", () => { ); }); }); + it("send error report with enforce_settings", () => { + let message = `random-error`; + let messageType = Constants.messageTypes.ERROR; + let errorCode = "build_failed"; + + const runs = proxyquire('../../../../bin/commands/runs', { + '../helpers/utils': { + validateBstackJson: validateBstackJsonStub, + sendUsageReport: sendUsageReportStub, + getParallels: getParallelsStub, + setParallels: setParallelsStub, + warnSpecLimit: warnSpecLimitStub, + setUsername: setUsernameStub, + setAccessKey: setAccessKeyStub, + setBuildName: setBuildNameStub, + setCypressConfigFilename: setCypressConfigFilenameStub, + setCypressTestSuiteType: setCypressTestSuiteTypeStub, + setUserSpecs: setUserSpecsStub, + setTestEnvs: setTestEnvsStub, + setSystemEnvs: setSystemEnvsStub, + setUsageReportingFlag: setUsageReportingFlagStub, + getConfigPath: getConfigPathStub, + setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, + setLocalIdentifier: setLocalIdentifierStub, + setHeaded: setHeadedStub, + setNoWrap: setNoWrapStub, + setOtherConfigs: setOtherConfigsStub, + deleteResults: deleteResultsStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub, + setDefaults: setDefaultsStub, + stopLocalBinary: stopLocalBinaryStub, + setLocalConfigFile: setLocalConfigFileStub, + setBrowsers: setBrowsersStub, + setConfig: setConfigStub, + setEnforceSettingsConfig: setEnforceSettingsConfigStub, + isUndefinedOrFalse: isUndefinedOrFalseStub, + setCLIMode: setCLIModeStub, + fetchZipSize: fetchZipSizeStub, + setGeolocation: setGeolocationStub, + getVideoConfig: getVideoConfigStub, + setSpecTimeout: setSpecTimeoutStub, + setRecordCaps: setRecordCapsStub, + setDebugMode: setDebugModeStub, + setNodeVersion: setNodeVersionStub, + setBuildTags: setBuildTagsStub, + setNetworkLogs: setNetworkLogsStub, + setInteractiveCapability: setInteractiveCapabilityStub, + setTimezone: setTimezoneStub, + setCypressNpmDependency: setCypressNpmDependencyStub, + fetchFolderSize: fetchFolderSizeStub + }, + '../helpers/capabilityHelper': { + validate: capabilityValidatorStub, + }, + '../helpers/archiver': { + archive: archiverStub, + }, + '../helpers/fileHelpers': { + deleteZip: deleteZipStub, + deletePackageArchieve: deletePackageArchieveStub + }, + '../helpers/zipUpload': { + zipUpload: zipUploadStub, + }, + '../helpers/build': { + createBuild: createBuildStub, + }, + '../helpers/checkUploaded': { + checkUploadedMd5: checkUploadedStub, + }, + '../helpers/packageInstaller': { + packageWrapper: packageInstallerStub, + packageSetupAndInstaller: packageSetupAndInstallerStub + }, + '../helpers/getInitialDetails': { + getInitialDetails: getInitialDetailsStub, + } + }); + + validateBstackJsonStub.returns(Promise.resolve(bsConfigWithEnforceSettings)); + setupLocalTestingStub.returns(Promise.resolve("nothing")); + capabilityValidatorStub.returns( + Promise.resolve(Constants.validationMessages.VALIDATED) + ); + archiverStub.returns(Promise.resolve("Zipping completed")); + checkUploadedStub.returns(Promise.resolve({ zipUrlPresent: false })); + packageInstallerStub.returns(Promise.resolve({ packageArchieveCreated: false })); + zipUploadStub.returns(Promise.resolve("zip uploaded")); + stopLocalBinaryStub.returns(Promise.resolve("nothing")); + createBuildStub.returns(Promise.reject("random-error")); + fetchZipSizeStub.returns(123); + getInitialDetailsStub.returns(Promise.resolve({})); + fetchFolderSizeStub.returns(123); + packageSetupAndInstallerStub.returns(true) + isUndefinedOrFalseStub.returns(false); + + return runs(args, rawArgs) + .then(function (_bsConfig) { + chai.assert.fail("Promise error"); + }) + .catch((error) => { + sinon.assert.calledOnce(setDebugModeStub); + sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(deleteResultsStub); + sinon.assert.calledOnce(validateBstackJsonStub); + sinon.assert.calledOnce(setUsageReportingFlagStub); + sinon.assert.calledOnce(setDefaultsStub); + sinon.assert.calledOnce(setUsernameStub); + sinon.assert.calledOnce(setAccessKeyStub); + sinon.assert.calledOnce(getInitialDetailsStub); + sinon.assert.calledOnce(setBuildNameStub); + sinon.assert.calledOnce(setCypressConfigFilenameStub); + sinon.assert.calledOnce(setCypressTestSuiteTypeStub); + sinon.assert.calledOnce(setGeolocationStub); + sinon.assert.calledOnce(setTimezoneStub); + sinon.assert.calledOnce(setSpecTimeoutStub); + sinon.assert.calledOnce(setUserSpecsStub); + sinon.assert.calledOnce(setTestEnvsStub); + sinon.assert.calledOnce(setBuildTagsStub); + sinon.assert.calledOnce(setSystemEnvsStub); + sinon.assert.calledOnce(setLocalStub); + sinon.assert.calledOnce(setNetworkLogsStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setLocalIdentifierStub); + sinon.assert.calledOnce(setLocalConfigFileStub); + sinon.assert.calledOnce(setHeadedStub); + sinon.assert.calledOnce(setNoWrapStub); + sinon.assert.calledOnce(setCypressNpmDependencyStub); + sinon.assert.calledOnce(setNodeVersionStub); + sinon.assert.calledOnce(setConfigStub); + sinon.assert.calledOnce(setCLIModeStub); + sinon.assert.calledOnce(setOtherConfigsStub); + sinon.assert.calledOnce(capabilityValidatorStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); + sinon.assert.calledOnce(getVideoConfigStub); + sinon.assert.calledOnce(getParallelsStub); + sinon.assert.calledOnce(setParallelsStub); + sinon.assert.calledOnce(setRecordCapsStub); + sinon.assert.calledOnce(setInteractiveCapabilityStub); + sinon.assert.calledOnce(warnSpecLimitStub); + sinon.assert.calledOnce(packageInstallerStub); + sinon.assert.calledOnce(archiverStub); + sinon.assert.calledTwice(fetchZipSizeStub); + sinon.assert.calledOnce(fetchFolderSizeStub); + sinon.assert.calledOnce(zipUploadStub); + sinon.assert.calledOnce(isUndefinedOrFalseStub); + sinon.assert.calledOnce(setEnforceSettingsConfigStub); + sinon.assert.calledOnce(createBuildStub); + sinon.assert.calledOnce(stopLocalBinaryStub); + sinon.assert.calledOnceWithExactly( + sendUsageReportStub, + bsConfig, + args, + message, + messageType, + errorCode, + {}, + rawArgs + ); + }); + }); }); @@ -1181,5 +1347,201 @@ describe("runs", () => { ); }); }); + + it("with enforce_settings", () => { + let messageType = Constants.messageTypes.SUCCESS; + let errorCode = null; + let message = `Success! ${Constants.userMessages.BUILD_CREATED} with build id: random_build_id`; + let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${dashboardUrl}`; + let data = { user_id: 1234, parallels: 10, time_components: {}, unique_id: 'random_hash', package_error: 'test', checkmd5_error: 'test', build_id: 'random_build_id', test_zip_size: 123, npm_zip_size: 123, node_modules_size: 123, test_suite_zip_upload: 1, package_zip_upload: 1, is_package_diff: false} + + const runs = proxyquire('../../../../bin/commands/runs', { + '../helpers/utils': { + validateBstackJson: validateBstackJsonStub, + sendUsageReport: sendUsageReportStub, + setUsername: setUsernameStub, + setAccessKey: setAccessKeyStub, + setBuildName: setBuildNameStub, + setCypressConfigFilename: setCypressConfigFilenameStub, + setCypressTestSuiteType: setCypressTestSuiteTypeStub, + setUserSpecs: setUserSpecsStub, + setTestEnvs: setTestEnvsStub, + setSystemEnvs: setSystemEnvsStub, + setUsageReportingFlag: setUsageReportingFlagStub, + getParallels: getParallelsStub, + setParallels: setParallelsStub, + warnSpecLimit: warnSpecLimitStub, + getConfigPath: getConfigPathStub, + setLocal: setLocalStub, + setLocalMode: setLocalModeStub, + setupLocalTesting: setupLocalTestingStub, + setLocalIdentifier: setLocalIdentifierStub, + setHeaded: setHeadedStub, + setNoWrap: setNoWrapStub, + setOtherConfigs: setOtherConfigsStub, + generateUniqueHash: generateUniqueHashStub, + exportResults: exportResultsStub, + deleteResults: deleteResultsStub, + setDefaults: setDefaultsStub, + isUndefined: isUndefinedStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub, + setLocalConfigFile: setLocalConfigFileStub, + setBrowsers: setBrowsersStub, + setConfig: setConfigStub, + setEnforceSettingsConfig: setEnforceSettingsConfigStub, + isUndefinedOrFalse: isUndefinedOrFalseStub, + stopLocalBinary: stopLocalBinaryStub, + nonEmptyArray: nonEmptyArrayStub, + checkError: checkErrorStub, + setCLIMode: setCLIModeStub, + setProcessHooks: setProcessHooksStub, + fetchZipSize: fetchZipSizeStub, + setGeolocation: setGeolocationStub, + getVideoConfig: getVideoConfigStub, + setSpecTimeout: setSpecTimeoutStub, + setRecordCaps: setRecordCapsStub, + setDebugMode: setDebugModeStub, + setNodeVersion: setNodeVersionStub, + setBuildTags: setBuildTagsStub, + setNetworkLogs: setNetworkLogsStub, + setInteractiveCapability: setInteractiveCapabilityStub, + setTimezone: setTimezoneStub, + setCypressNpmDependency: setCypressNpmDependencyStub, + fetchFolderSize: fetchFolderSizeStub + }, + '../helpers/capabilityHelper': { + validate: capabilityValidatorStub, + }, + '../helpers/archiver': { + archive: archiverStub, + }, + '../helpers/fileHelpers': { + deleteZip: deleteZipStub, + deletePackageArchieve: deletePackageArchieveStub + }, + '../helpers/zipUpload': { + zipUpload: zipUploadStub, + }, + '../helpers/build': { + createBuild: createBuildStub, + }, + '../helpers/config': { + dashboardUrl: dashboardUrl, + packageDirName: packageDirName, + packageFileName: packageFileName, + fileName: fileName, + }, + '../helpers/checkUploaded': { + checkUploadedMd5: checkUploadedStub, + }, + '../helpers/packageInstaller': { + packageWrapper: packageInstallerStub, + packageSetupAndInstaller: packageSetupAndInstallerStub + }, + '../helpers/timeComponents': { + initTimeComponents: initTimeComponentsStub, + instrumentEventTime: instrumentEventTimeStub, + getTimeComponents: getTimeComponentsStub, + markBlockStart: markBlockStartStub, + markBlockEnd: markBlockEndStub, + }, + '../helpers/getInitialDetails': { + getInitialDetails: getInitialDetailsStub, + } + }); + + validateBstackJsonStub.returns(Promise.resolve(bsConfigWithEnforceSettings)); + setupLocalTestingStub.returns(Promise.resolve("nothing")); + capabilityValidatorStub.returns( + Promise.resolve(Constants.validationMessages.VALIDATED) + ); + archiverStub.returns(Promise.resolve("Zipping completed")); + checkUploadedStub.returns(Promise.resolve({ zipUrlPresent: false })); + packageInstallerStub.returns(Promise.resolve({ packageArchieveCreated: false })); + zipUploadStub.returns(Promise.resolve("zip uploaded")); + stopLocalBinaryStub.returns(Promise.resolve("nothing")); + nonEmptyArrayStub.returns(false); + checkErrorStub.returns('test'); + getParallelsStub.returns(10); + createBuildStub.returns(Promise.resolve({ message: 'Success', build_id: 'random_build_id', dashboard_url: dashboardUrl, user_id: 1234 })); + fetchZipSizeStub.returns(123); + getInitialDetailsStub.returns(Promise.resolve({user_id: 1234})); + fetchFolderSizeStub.returns(123); + packageSetupAndInstallerStub.returns(true); + isUndefinedOrFalseStub.returns(false); + + return runs(args, rawArgs) + .then(function (_bsConfig) { + chai.assert.fail("Promise error"); + }) + .catch((error) => { + sinon.assert.calledOnce(setDebugModeStub); + sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(deleteResultsStub); + sinon.assert.calledOnce(validateBstackJsonStub); + sinon.assert.calledOnce(setUsageReportingFlagStub); + sinon.assert.calledOnce(setDefaultsStub); + sinon.assert.calledOnce(setUsernameStub); + sinon.assert.calledOnce(setAccessKeyStub); + sinon.assert.calledOnce(getInitialDetailsStub); + sinon.assert.calledOnce(setBuildNameStub); + sinon.assert.calledOnce(setCypressConfigFilenameStub); + sinon.assert.calledOnce(setCypressTestSuiteTypeStub); + sinon.assert.calledOnce(setGeolocationStub); + sinon.assert.calledOnce(setTimezoneStub); + sinon.assert.calledOnce(setSpecTimeoutStub); + sinon.assert.calledOnce(setUserSpecsStub); + sinon.assert.calledOnce(setTestEnvsStub); + sinon.assert.calledOnce(setBuildTagsStub); + sinon.assert.calledOnce(setSystemEnvsStub); + sinon.assert.calledOnce(setLocalStub); + sinon.assert.calledOnce(setNetworkLogsStub); + sinon.assert.calledOnce(setLocalModeStub); + sinon.assert.calledOnce(setLocalIdentifierStub); + sinon.assert.calledOnce(setLocalConfigFileStub); + sinon.assert.calledOnce(setHeadedStub); + sinon.assert.calledOnce(setNoWrapStub); + sinon.assert.calledOnce(setCypressNpmDependencyStub); + sinon.assert.calledOnce(setNodeVersionStub); + sinon.assert.calledOnce(setConfigStub); + sinon.assert.calledOnce(setCLIModeStub); + sinon.assert.calledOnce(setOtherConfigsStub); + sinon.assert.calledOnce(capabilityValidatorStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); + sinon.assert.calledOnce(getVideoConfigStub); + sinon.assert.calledOnce(getParallelsStub); + sinon.assert.calledOnce(setParallelsStub); + sinon.assert.calledOnce(setRecordCapsStub); + sinon.assert.calledOnce(setInteractiveCapabilityStub); + sinon.assert.calledOnce(warnSpecLimitStub); + sinon.assert.calledOnce(packageInstallerStub); + sinon.assert.calledOnce(archiverStub); + sinon.assert.calledTwice(fetchZipSizeStub); + sinon.assert.calledOnce(fetchFolderSizeStub); + sinon.assert.calledOnce(zipUploadStub); + sinon.assert.calledOnce(isUndefinedOrFalseStub); + sinon.assert.calledOnce(setEnforceSettingsConfigStub); + sinon.assert.calledOnce(createBuildStub); + sinon.assert.calledOnce(setProcessHooksStub); + sinon.assert.calledOnce(exportResultsStub); + sinon.assert.calledTwice(isUndefinedStub); + sinon.assert.calledOnce(nonEmptyArrayStub); + sinon.assert.calledOnce(generateUniqueHashStub); + sinon.assert.calledTwice(checkErrorStub); + sinon.assert.match( + sendUsageReportStub.getCall(0).args, + [ + bsConfig, + args, + `${message}\n${dashboardLink}`, + messageType, + errorCode, + data, + rawArgs + ] + ); + }); + }); }); }); From 4cd5b6f0c82fa2ddc1890c8cc6958fdf44969ad6 Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Wed, 29 Nov 2023 18:40:20 +0530 Subject: [PATCH 5/9] Refactoring --- bin/helpers/capabilityHelper.js | 8 +++++--- bin/helpers/constants.js | 2 -- bin/helpers/utils.js | 15 +++++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index f2e2df93..ac05976e 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -239,9 +239,11 @@ const validate = (bsConfig, args) => { // Detect if the user is not using the right directory structure, and throw an error if (!Utils.isUndefined(cypressConfigFile.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,cypressConfigFile.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE); } - logger.debug("Validating baseurl and integrationFolder in browserstack.json"); - if (!Utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !Utils.isUndefined(bsConfig.run_settings.baseUrl) && bsConfig.run_settings.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET.replace("", bsConfig.run_settings.baseUrl)); - if (!Utils.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) && !Utils.isUndefined(bsConfig.run_settings.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,bsConfig.run_settings.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE); + else { + logger.debug("Validating baseurl and integrationFolder in browserstack.json"); + if (!Utils.isUndefined(bsConfig.run_settings.baseUrl) && bsConfig.run_settings.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET.replace("", bsConfig.run_settings.baseUrl)); + if (!Utils.isUndefined(bsConfig.run_settings.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,bsConfig.run_settings.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE); + } } catch(error){ reject(Constants.validationMessages.INVALID_CYPRESS_JSON) } diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 85cc91b1..9e27de32 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -70,8 +70,6 @@ const userMessages = { UPLOADING_TESTS_SUCCESS: "Uploaded tests successfully", UPLOADING_NPM_PACKAGES: "Uploading required node_modules to BrowserStack", UPLOADING_NPM_PACKAGES_SUCCESS: "Uploaded node_modules successfully", - SKIP_CYPRESSCONFIG_INSTALL: - "Skipping Cypress Config Install as the enforce_settings has been passed.", SKIP_UPLOADING_TESTS: "Skipping zip upload since BrowserStack already has your test suite that has not changed since the last run.", SKIP_NPM_INSTALL: diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 6f979d71..4500e777 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1292,29 +1292,28 @@ exports.setConfig = (bsConfig, args) => { // set configs if enforce_settings is passed exports.setEnforceSettingsConfig = (bsConfig) => { - let config_args = (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.config)) ? bsConfig.run_settings.config : undefined; + if ( this.isUndefined(bsConfig) || this.isUndefined(bsConfig.run_settings) ) return; + let config_args = (bsConfig && bsConfig.run_settings && bsConfig.run_settings.config) ? bsConfig.run_settings.config : undefined; if ( this.isUndefined(config_args) || !config_args.includes("video") ) { let video_args = (this.isUndefined(bsConfig.run_settings.video_config) || this.isUndefined(bsConfig.run_settings.video_config.video) || !bsConfig.run_settings.video_config.video ) ? 'video=false' : 'video=true' ; video_args += (this.isUndefined(bsConfig.run_settings.video_config) || this.isUndefined(bsConfig.run_settings.video_config.videoUploadOnPasses) || !bsConfig.run_settings.video_config.videoUploadOnPasses ) ? ',videoUploadOnPasses=false' : ',videoUploadOnPasses=true'; config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; logger.debug(`Setting video_args for enforce_settings to ${video_args}`); } - if ( (!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.baseUrl)) && (this.isUndefined(config_args) || !config_args.includes("baseUrl")) ) { + if ( (bsConfig && bsConfig.run_settings && bsConfig.run_settings.baseUrl) && (this.isUndefined(config_args) || !config_args.includes("baseUrl")) ) { let base_url_args = 'baseUrl='+bsConfig.run_settings.baseUrl; config_args = this.isUndefined(config_args) ? base_url_args : config_args + ',' + base_url_args; logger.debug(`Setting base_url_args for enforce_settings to ${base_url_args}`); } // set specs in config of specpattern to override cypress config - if(!this.isUndefined(bsConfig) && !this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.specs)) { + if( this.isNotUndefined(bsConfig.run_settings.specs) && bsConfig.run_settings.cypressTestSuiteType === Constants.CYPRESS_V10_AND_ABOVE_TYPE ) { + // doing this only for cypress 10 and above as --spec is given precedence for cypress 9. let spec_pattern_args = 'specPattern="'+bsConfig.run_settings.specs+'"'; - if( bsConfig.run_settings.cypressTestSuiteType !== Constants.CYPRESS_V10_AND_ABOVE_TYPE) { - spec_pattern_args = 'testFiles="'+bsConfig.run_settings.specs+'"'; - } config_args = this.isUndefined(config_args) ? spec_pattern_args : config_args + ',' + spec_pattern_args; } - if ( !this.isUndefined(config_args) ) bsConfig["run_settings"]["config"] = config_args; + if ( this.isNotUndefined(config_args) ) bsConfig["run_settings"]["config"] = config_args; logger.debug(`Setting conifg_args for enforce_settings to ${config_args}`); -} +} // blindly send other passed configs with run_settings and handle at backend exports.setOtherConfigs = (bsConfig, args) => { From c4b5ab7a69cf51d6f35eefe3fbe4c1312ca5888f Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Thu, 30 Nov 2023 15:19:34 +0530 Subject: [PATCH 6/9] Default video true implementation for cypress 13 --- bin/helpers/utils.js | 19 ++++++++- test/unit/bin/helpers/utils.js | 74 +++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 4500e777..3e7d7c9e 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1290,6 +1290,21 @@ exports.setConfig = (bsConfig, args) => { } } +exports.setVideoCliConfig = (bsConfig, videoConfig) => { + // set cli config for video for cypress 13 and above to attain default value of true. + if(this.isUndefined(videoConfig) || this.isUndefined(videoConfig.video) || this.isUndefined(videoConfig.videoUploadOnPasses) || this.isUndefined(bsConfig)) return; + let user_cypress_version = (bsConfig && bsConfig.run_settings && bsConfig.run_settings.cypress_version) ? bsConfig.run_settings.cypress_version.toString() : undefined; + let cypress_major_version = (user_cypress_version && user_cypress_version.match(/^(\d+)/)) ? user_cypress_version.split(".")[0] : undefined; + let config_args = (bsConfig && bsConfig.run_settings && bsConfig.run_settings.config) ? bsConfig.run_settings.config : undefined; + if(this.isUndefined(user_cypress_version) || this.isUndefined(cypress_major_version) || parseInt(cypress_major_version) >= 13 ) { + logger.info('Setting default video for cypress 13 and above'); + let video_args = `video=${videoConfig.video},videoUploadOnPasses=${videoConfig.videoUploadOnPasses}`; + config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; + logger.debug(`Setting video true in cli for cypress version ${user_cypress_version} with cli args - ${config_args}`) + } + if (bsConfig.run_settings && this.isNotUndefined(config_args)) bsConfig["run_settings"]["config"] = config_args; +} + // set configs if enforce_settings is passed exports.setEnforceSettingsConfig = (bsConfig) => { if ( this.isUndefined(bsConfig) || this.isUndefined(bsConfig.run_settings) ) return; @@ -1536,11 +1551,13 @@ exports.getVideoConfig = (cypressConfig, bsConfig = {}) => { // Reading from bsconfig first to give precedance and cypress config will be empty in case of enforce_settings if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; - if ( this.isUndefined(bsConfig.run_settings) || this.isUndefined(bsConfig.run_settings.enforce_settings) ) { + if ( this.isUndefined(bsConfig.run_settings) || this.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) ) { if (!this.isUndefined(cypressConfig.video)) conf.video = cypressConfig.video; if (!this.isUndefined(cypressConfig.videoUploadOnPasses)) conf.videoUploadOnPasses = cypressConfig.videoUploadOnPasses; } + // set video in cli config in case of cypress 13 or above as default value is false there. + this.setVideoCliConfig(bsConfig,conf); logger.debug(`Setting video = ${conf.video}`); logger.debug(`Setting videoUploadOnPasses = ${conf.videoUploadOnPasses}`); return conf; diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 7d7e28db..42feb144 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -3055,6 +3055,41 @@ describe('utils', () => { }); }); + describe('setVideoCliConfig', () => { + it('the args should be empty if any of videoconfig or bsconfig is undefined', () => { + let bsConfig = { + run_settings: {}, + }; + let videoConfig = { + }; + utils.setVideoCliConfig(bsConfig, videoConfig); + expect(undefined).to.be.eql(bsConfig.run_settings.config); + }); + it('the config should have video true if video is passed true', () => { + let bsConfig = { + run_settings: {}, + }; + let videoConfig = {video:true, videoUploadOnPasses:true}; + let outputConfig = { + config: 'video=true,videoUploadOnPasses=true' + }; + utils.setVideoCliConfig(bsConfig, videoConfig); + expect(outputConfig.config).to.be.eql(bsConfig.run_settings.config); + }); + it('the config should have config with video false if video is passed false', () => { + let bsConfig = { + run_settings: {}, + }; + let videoConfig = {video:false, videoUploadOnPasses:true}; + let outputConfig = { + config: 'video=false,videoUploadOnPasses=true' + }; + utils.setVideoCliConfig(bsConfig, videoConfig); + expect(outputConfig.config).to.be.eql(bsConfig.run_settings.config); + }); + }); + + describe('setEnforceSettingsConfig', () => { it('the video config should be assigned to bsconfig run_settings config', () => { let bsConfig = { @@ -3081,7 +3116,7 @@ describe('utils', () => { run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V9_AND_OLDER_TYPE' }, }; let args = { - config: 'video=false,videoUploadOnPasses=false,testFiles="somerandomspecs"' + config: 'video=false,videoUploadOnPasses=false' } utils.setEnforceSettingsConfig(bsConfig); expect(args.config).to.be.eql(bsConfig.run_settings.config); @@ -3463,6 +3498,43 @@ describe('utils', () => { expect(utils.getVideoConfig({video: false, videoUploadOnPasses: false})).to.be.eql({video: false, videoUploadOnPasses: false}); }); + it('should add default video config in cli config only for cyp 13', () => { + let bsConfig = { + run_settings: {cypress_version: '13.latest'}, + }; + let outputConfig = 'video=true,videoUploadOnPasses=true'; + utils.getVideoConfig({}, bsConfig); + expect(outputConfig).to.be.eql(bsConfig.run_settings.config); + }); + + it('should add not default video config in cli config only for cyp 12 or below', () => { + let bsConfig = { + run_settings: {cypress_version: '12.latest'}, + }; + utils.getVideoConfig({}, bsConfig); + expect(undefined).to.be.eql(bsConfig.run_settings.config); + }); + + it('should add bstack json video config in cli config if none in cypress config for cyp 13', () => { + let bsConfig = { + run_settings: {cypress_version: '13.latest', video: true, videoUploadOnPasses: false} + }; + let cypressConfig = {}; + let outputConfig = 'video=true,videoUploadOnPasses=false'; + utils.getVideoConfig(cypressConfig, bsConfig); + expect(outputConfig).to.be.eql(bsConfig.run_settings.config); + }); + + it('should add cypress config video config in cli config over bstack json for cyp 13', () => { + let bsConfig = { + run_settings: {cypress_version: '13.latest'}, + }; + let cypressConfig = {video: false}; + let outputConfig = 'video=false,videoUploadOnPasses=true'; + utils.getVideoConfig(cypressConfig, bsConfig); + expect(outputConfig).to.be.eql(bsConfig.run_settings.config); + }); + it('should return default hash and ignore video config in cypress config if enforce_settings is passed by the user', () => { expect(utils.getVideoConfig({video: false}, {run_settings: {enforce_settings: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); expect(utils.getVideoConfig({videoUploadOnPasses: false}, {run_settings: {enforce_settings: true}})).to.be.eql({video: true, videoUploadOnPasses: true}); From 4e36fdb1d8d631686ed78facff14d6813e06a3c2 Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Fri, 1 Dec 2023 15:26:49 +0530 Subject: [PATCH 7/9] Fix for specs passed as array in enforce_settings --- bin/helpers/utils.js | 11 ++++++++--- test/unit/bin/helpers/utils.js | 12 +++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 3e7d7c9e..db6937ee 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1297,7 +1297,7 @@ exports.setVideoCliConfig = (bsConfig, videoConfig) => { let cypress_major_version = (user_cypress_version && user_cypress_version.match(/^(\d+)/)) ? user_cypress_version.split(".")[0] : undefined; let config_args = (bsConfig && bsConfig.run_settings && bsConfig.run_settings.config) ? bsConfig.run_settings.config : undefined; if(this.isUndefined(user_cypress_version) || this.isUndefined(cypress_major_version) || parseInt(cypress_major_version) >= 13 ) { - logger.info('Setting default video for cypress 13 and above'); + logger.debug('Setting default video for cypress 13 and above'); let video_args = `video=${videoConfig.video},videoUploadOnPasses=${videoConfig.videoUploadOnPasses}`; config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; logger.debug(`Setting video true in cli for cypress version ${user_cypress_version} with cli args - ${config_args}`) @@ -1321,9 +1321,14 @@ exports.setEnforceSettingsConfig = (bsConfig) => { logger.debug(`Setting base_url_args for enforce_settings to ${base_url_args}`); } // set specs in config of specpattern to override cypress config - if( this.isNotUndefined(bsConfig.run_settings.specs) && bsConfig.run_settings.cypressTestSuiteType === Constants.CYPRESS_V10_AND_ABOVE_TYPE ) { + if( this.isNotUndefined(bsConfig.run_settings.specs) && bsConfig.run_settings.cypressTestSuiteType === Constants.CYPRESS_V10_AND_ABOVE_TYPE && (this.isUndefined(config_args) || !config_args.includes("specPattern")) ) { // doing this only for cypress 10 and above as --spec is given precedence for cypress 9. - let spec_pattern_args = 'specPattern="'+bsConfig.run_settings.specs+'"'; + let specConfigs = bsConfig.run_settings.specs; + // if multiple specs are passed, convert it into an array. + if(specConfigs && specConfigs.includes(',')) { + specConfigs = JSON.stringify(bsConfig.run_settings.specs.split(',')); + } + let spec_pattern_args = 'specPattern="'+specConfigs+'"'; config_args = this.isUndefined(config_args) ? spec_pattern_args : config_args + ',' + spec_pattern_args; } if ( this.isNotUndefined(config_args) ) bsConfig["run_settings"]["config"] = config_args; diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 42feb144..559d91e3 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -3101,7 +3101,7 @@ describe('utils', () => { utils.setEnforceSettingsConfig(bsConfig); expect(args.config).to.be.eql(bsConfig.run_settings.config); }); - it('the specPattern config should be assigned to bsconfig run_settings config', () => { + it('the specPattern config should be assigned as strings for single string to bsconfig run_settings config', () => { let bsConfig = { run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V10_AND_ABOVE_TYPE' }, }; @@ -3111,6 +3111,16 @@ describe('utils', () => { utils.setEnforceSettingsConfig(bsConfig); expect(args.config).to.be.eql(bsConfig.run_settings.config); }); + it('the specPattern config should be assigned as array for multiple spec strings to bsconfig run_settings config', () => { + let bsConfig = { + run_settings: { specs: 'somerandomspecs1,somerandomspecs2', cypressTestSuiteType: 'CYPRESS_V10_AND_ABOVE_TYPE' }, + }; + let args = { + config: 'video=false,videoUploadOnPasses=false,specPattern="["somerandomspecs1","somerandomspecs2"]"' + } + utils.setEnforceSettingsConfig(bsConfig); + expect(args.config).to.be.eql(bsConfig.run_settings.config); + }); it('the testFiles config should be assigned to bsconfig run_settings config', () => { let bsConfig = { run_settings: { specs: 'somerandomspecs', cypressTestSuiteType: 'CYPRESS_V9_AND_OLDER_TYPE' }, From a85992de1cf4f0cab1b7831ee2292a6cbf416d4b Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Fri, 1 Dec 2023 15:33:04 +0530 Subject: [PATCH 8/9] Refactor variable --- 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 db6937ee..03198b12 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1326,7 +1326,7 @@ exports.setEnforceSettingsConfig = (bsConfig) => { let specConfigs = bsConfig.run_settings.specs; // if multiple specs are passed, convert it into an array. if(specConfigs && specConfigs.includes(',')) { - specConfigs = JSON.stringify(bsConfig.run_settings.specs.split(',')); + specConfigs = JSON.stringify(specConfigs.split(',')); } let spec_pattern_args = 'specPattern="'+specConfigs+'"'; config_args = this.isUndefined(config_args) ? spec_pattern_args : config_args + ',' + spec_pattern_args; From ae509f857a7640ae7ea03c7a46c013c5b9a1648c Mon Sep 17 00:00:00 2001 From: hariharanbrowserstack Date: Fri, 1 Dec 2023 16:07:48 +0530 Subject: [PATCH 9/9] Default handling video for cyp 13 similar as cyp 12 --- bin/helpers/utils.js | 11 ++++++----- test/unit/bin/helpers/utils.js | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 03198b12..408dbc1b 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -1297,10 +1297,9 @@ exports.setVideoCliConfig = (bsConfig, videoConfig) => { let cypress_major_version = (user_cypress_version && user_cypress_version.match(/^(\d+)/)) ? user_cypress_version.split(".")[0] : undefined; let config_args = (bsConfig && bsConfig.run_settings && bsConfig.run_settings.config) ? bsConfig.run_settings.config : undefined; if(this.isUndefined(user_cypress_version) || this.isUndefined(cypress_major_version) || parseInt(cypress_major_version) >= 13 ) { - logger.debug('Setting default video for cypress 13 and above'); let video_args = `video=${videoConfig.video},videoUploadOnPasses=${videoConfig.videoUploadOnPasses}`; config_args = this.isUndefined(config_args) ? video_args : config_args + ',' + video_args; - logger.debug(`Setting video true in cli for cypress version ${user_cypress_version} with cli args - ${config_args}`) + logger.debug(`Setting default video true for cypress 13 and above in cli for cypress version ${user_cypress_version} with cli args - ${config_args}`) } if (bsConfig.run_settings && this.isNotUndefined(config_args)) bsConfig["run_settings"]["config"] = config_args; } @@ -1553,13 +1552,15 @@ exports.getVideoConfig = (cypressConfig, bsConfig = {}) => { video: true, videoUploadOnPasses: true } - // Reading from bsconfig first to give precedance and cypress config will be empty in case of enforce_settings - if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; - if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; + // Reading bsconfig in case of enforce_settings if ( this.isUndefined(bsConfig.run_settings) || this.isUndefinedOrFalse(bsConfig.run_settings.enforce_settings) ) { if (!this.isUndefined(cypressConfig.video)) conf.video = cypressConfig.video; if (!this.isUndefined(cypressConfig.videoUploadOnPasses)) conf.videoUploadOnPasses = cypressConfig.videoUploadOnPasses; } + else { + if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.video)) conf.video = bsConfig.run_settings.video; + if (!this.isUndefined(bsConfig.run_settings) && !this.isUndefined(bsConfig.run_settings.videoUploadOnPasses)) conf.videoUploadOnPasses = bsConfig.run_settings.videoUploadOnPasses; + } // set video in cli config in case of cypress 13 or above as default value is false there. this.setVideoCliConfig(bsConfig,conf); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 559d91e3..820102dd 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -3517,7 +3517,7 @@ describe('utils', () => { expect(outputConfig).to.be.eql(bsConfig.run_settings.config); }); - it('should add not default video config in cli config only for cyp 12 or below', () => { + it('should not add default video config in cli config only for cyp 12 or below', () => { let bsConfig = { run_settings: {cypress_version: '12.latest'}, }; @@ -3525,12 +3525,12 @@ describe('utils', () => { expect(undefined).to.be.eql(bsConfig.run_settings.config); }); - it('should add bstack json video config in cli config if none in cypress config for cyp 13', () => { + it('should not add bstack json video config in cli config if none in cypress config for cyp 13', () => { let bsConfig = { run_settings: {cypress_version: '13.latest', video: true, videoUploadOnPasses: false} }; let cypressConfig = {}; - let outputConfig = 'video=true,videoUploadOnPasses=false'; + let outputConfig = 'video=true,videoUploadOnPasses=true'; utils.getVideoConfig(cypressConfig, bsConfig); expect(outputConfig).to.be.eql(bsConfig.run_settings.config); });