From 3db1d90cac3e7572411e1bf2176bbacc7a013cce Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 4 Nov 2020 14:01:37 +0530 Subject: [PATCH 1/7] Limiting the allocation of parallels w.r.t specs . --- bin/commands/runs.js | 7 +++++-- bin/helpers/capabilityHelper.js | 3 ++- bin/helpers/constants.js | 8 +++++++- bin/helpers/utils.js | 9 +++++++++ package.json | 3 ++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 0d9a0e5c..700ee575 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -45,8 +45,11 @@ module.exports = function run(args) { utils.setLocalIdentifier(bsConfig); // Validate browserstack.json values and parallels specified via arguments - return capabilityHelper.validate(bsConfig, args).then(function (validated) { - logger.info(validated); + return capabilityHelper.validate(bsConfig, args).then(function (cypressJson) { + + //get the number of spec files + let files = utils.getNumberOfSpecFiles(bsConfig,args,cypressJson); + logger.info(files); // accept the number of parallels utils.setParallels(bsConfig, args); diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index bb7a3268..2db4a70d 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -123,6 +123,7 @@ const validate = (bsConfig, args) => { // validate if config file provided exists or not when cypress_config_file provided // validate the cypressProjectDir key otherwise. let cypressConfigFilePath = bsConfig.run_settings.cypressConfigFilePath; + let cypressJson = {}; if (!fs.existsSync(cypressConfigFilePath) && bsConfig.run_settings.cypress_config_filename !== 'false') reject(Constants.validationMessages.INVALID_CYPRESS_CONFIG_FILE); @@ -141,7 +142,7 @@ const validate = (bsConfig, args) => { reject(Constants.validationMessages.INVALID_CYPRESS_JSON) } - resolve(Constants.validationMessages.VALIDATED); + resolve(cypressJson); }); } diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 0f89948a..02b206fa 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -91,11 +91,17 @@ const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json'] +const specFileTypes = ['js', 'ts', 'feature', 'jsx', 'coffee', 'cjsx'] + +const DEFAULT_CYPRESS_SPEC_PATH = "cypress/integration" + module.exports = Object.freeze({ userMessages, cliMessages, validationMessages, messageTypes, allowedFileTypes, - filesToIgnoreWhileUploading + filesToIgnoreWhileUploading, + specFileTypes, + DEFAULT_CYPRESS_SPEC_PATH }); diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 66df447c..9c6d8793 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -2,6 +2,7 @@ const os = require("os"); const path = require("path"); const fs = require("fs"); +const glob = require('glob'); const usageReporting = require("./usageReporting"), logger = require("./logger").winstonLogger, @@ -314,3 +315,11 @@ exports.setLocalIdentifier = (bsConfig) => { ); } }; + +exports.getNumberOfSpecFiles = (bsConfig, args, cypressJson) => { + let testFolderPath = cypressJson.integrationFolder || Constants.DEFAULT_CYPRESS_SPEC_PATH; + let globSearchPatttern = bsConfig.run_settings.specs || `${testFolderPath}/**/*.+(${Constants.specFileTypes.join("|")})`; + let ignoreFiles = args.exclude || bsConfig.run_settings.exclude; + let files = glob.sync(globSearchPatttern, {cmd: bsConfig.run_settings.cypressConfigFilePath, matchBase: true, ignore: ignoreFiles}); + return files; +}; diff --git a/package.json b/package.json index 3068c04d..42e22ae3 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "request": "^2.88.0", "requestretry": "^4.1.0", "winston": "^2.3.1", - "yargs": "^14.2.2" + "yargs": "^14.2.2", + "glob": "^7.1.6" }, "repository": { "type": "git", From 137aa3f7083ece0cbdafb73828f69d4094717b9b Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Wed, 4 Nov 2020 18:44:34 +0530 Subject: [PATCH 2/7] Unit test cases fix --- bin/helpers/capabilityHelper.js | 1 - test/unit/bin/commands/runs.js | 32 ++++++++++++++--------- test/unit/bin/helpers/capabilityHelper.js | 30 +++++---------------- test/unit/bin/helpers/utils.js | 27 ++++++++++++++++++- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/bin/helpers/capabilityHelper.js b/bin/helpers/capabilityHelper.js index 2db4a70d..15e61fe6 100644 --- a/bin/helpers/capabilityHelper.js +++ b/bin/helpers/capabilityHelper.js @@ -141,7 +141,6 @@ const validate = (bsConfig, args) => { } catch(error){ reject(Constants.validationMessages.INVALID_CYPRESS_JSON) } - resolve(cypressJson); }); } diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index ef8f75ad..749e0ec2 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -189,6 +189,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub(); }); afterEach(() => { @@ -217,7 +218,8 @@ describe("runs", () => { setLocal: setLocalStub, setLocalIdentifier: setLocalIdentifierStub, deleteResults: deleteResultsStub, - setDefaultAuthHash: setDefaultAuthHashStub + setDefaultAuthHash: setDefaultAuthHashStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -289,6 +291,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub(); }); afterEach(() => { @@ -317,7 +320,8 @@ describe("runs", () => { setLocal: setLocalStub, setLocalIdentifier: setLocalIdentifierStub, deleteResults: deleteResultsStub, - setDefaultAuthHash: setDefaultAuthHashStub + setDefaultAuthHash: setDefaultAuthHashStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -397,6 +401,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub(); }); afterEach(() => { @@ -425,7 +430,8 @@ describe("runs", () => { setLocal: setLocalStub, setLocalIdentifier: setLocalIdentifierStub, deleteResults: deleteResultsStub, - setDefaultAuthHash: setDefaultAuthHashStub + setDefaultAuthHash: setDefaultAuthHashStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub }, '../helpers/capabilityHelper': { validate: capabilityValidatorStub, @@ -519,6 +525,7 @@ describe("runs", () => { isUndefinedStub = sandbox.stub(); setLocalStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub(); }); afterEach(() => { @@ -532,8 +539,8 @@ describe("runs", () => { let message = `Success! ${Constants.userMessages.BUILD_CREATED} with build id: random_build_id`; let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${dashboardUrl}random_build_id`; - const runs = proxyquire("../../../../bin/commands/runs", { - "../helpers/utils": { + const runs = proxyquire('../../../../bin/commands/runs', { + '../helpers/utils': { validateBstackJson: validateBstackJsonStub, sendUsageReport: sendUsageReportStub, setUsername: setUsernameStub, @@ -550,24 +557,25 @@ describe("runs", () => { exportResults: exportResultsStub, deleteResults: deleteResultsStub, setDefaultAuthHash: setDefaultAuthHashStub, - isUndefined: isUndefinedStub + isUndefined: isUndefinedStub, + getNumberOfSpecFiles: getNumberOfSpecFilesStub }, - "../helpers/capabilityHelper": { + '../helpers/capabilityHelper': { validate: capabilityValidatorStub, }, - "../helpers/archiver": { + '../helpers/archiver': { archive: archiverStub, }, - "../helpers/fileHelpers": { + '../helpers/fileHelpers': { deleteZip: deleteZipStub, }, - "../helpers/zipUpload": { + '../helpers/zipUpload': { zipUpload: zipUploadStub, }, - "../helpers/build": { + '../helpers/build': { createBuild: createBuildStub, }, - "../helpers/config": { + '../helpers/config': { dashboardUrl: dashboardUrl, }, }); diff --git a/test/unit/bin/helpers/capabilityHelper.js b/test/unit/bin/helpers/capabilityHelper.js index 0d68d25e..9e379f64 100644 --- a/test/unit/bin/helpers/capabilityHelper.js +++ b/test/unit/bin/helpers/capabilityHelper.js @@ -561,10 +561,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: undefined }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); @@ -574,10 +571,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: undefined }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); @@ -586,10 +580,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: 200 }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); @@ -598,10 +589,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: -1 }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); @@ -611,10 +599,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: -1 }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); @@ -624,10 +609,7 @@ describe("capabilityHelper.js", () => { return capabilityHelper .validate(bsConfig, { parallels: -1 }) .then(function (data) { - chai.assert.equal(data, Constants.validationMessages.VALIDATED); - }) - .catch((error) => { - chai.assert.fail("Promise error"); + chai.assert.deepEqual(data, {}); }); }); }); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 1222ffde..6967899d 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1,11 +1,14 @@ 'use strict'; +const { it } = require('mocha'); const path = require('path'); +const { sandbox } = require('sinon'); const chai = require('chai'), expect = chai.expect, sinon = require('sinon'), chaiAsPromised = require('chai-as-promised'), - fs = require('fs'); + fs = require('fs'), + glob = require('glob'); const utils = require('../../../../bin/helpers/utils'), constant = require('../../../../bin/helpers/constants'), @@ -946,4 +949,26 @@ describe('utils', () => { expect(utils.isUndefined(bsConfig.auth)).to.be.true; }); }); + + describe('getNumberOfSpecFiles', () => { + + it('glob search pattern should be equal to bsConfig.run_settings.specs', () => { + sinon.stub(glob, 'sync').returns(true); + let bsConfig = { + run_settings: { + cypressConfigFilePath: 'cypressConfigFilePath', + exclude: 'exclude' + }, + }; + // sinon.assert.calledOnce(getNumberOfSpecFilesStub); + // sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, 'specs', { + // cmd: 'cypressConfigFilePath', + // matchBase: true, + // ignore: 'exclude', + // }); + utils.getNumberOfSpecFiles(bsConfig,{},{}); + glob.sync.restore(); + }); + }); + }); From 0089b8c0af3e7481c7474885724a3ca14b0a156a Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Thu, 5 Nov 2020 19:06:14 +0530 Subject: [PATCH 3/7] Added new test cases --- bin/commands/runs.js | 5 +- bin/helpers/utils.js | 24 +++++++- test/unit/bin/commands/runs.js | 12 ++-- test/unit/bin/helpers/utils.js | 100 ++++++++++++++++++++++++++++++--- 4 files changed, 125 insertions(+), 16 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 700ee575..6af04b32 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -48,11 +48,10 @@ module.exports = function run(args) { return capabilityHelper.validate(bsConfig, args).then(function (cypressJson) { //get the number of spec files - let files = utils.getNumberOfSpecFiles(bsConfig,args,cypressJson); - logger.info(files); + let specFiles = utils.getNumberOfSpecFiles(bsConfig,args,cypressJson); // accept the number of parallels - utils.setParallels(bsConfig, args); + utils.setParallels(bsConfig, args, specFiles.length); // Archive the spec files return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude).then(function (data) { diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index 9c6d8793..bbb3cfb2 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -110,10 +110,18 @@ exports.setUsageReportingFlag = (bsConfig, disableUsageReporting) => { } }; -exports.setParallels = (bsConfig, args) => { +exports.setParallels = (bsConfig, args, numOfSpecs) => { if (!this.isUndefined(args.parallels)) { bsConfig["run_settings"]["parallels"] = args.parallels; } + let browserCombinations = this.getBrowserCombinations(bsConfig); + let maxParallels = browserCombinations.length * numOfSpecs; + if (bsConfig['run_settings']['parallels'] > maxParallels) { + logger.warn( + `Using ${maxParallels} machines instead of ${bsConfig['run_settings']['parallels']} that you configured as there are ${numOfSpecs} specs to be run on ${browserCombinations.length} browser combinations.` + ); + bsConfig['run_settings']['parallels'] = maxParallels; + } }; exports.setDefaultAuthHash = (bsConfig, args) => { @@ -323,3 +331,17 @@ exports.getNumberOfSpecFiles = (bsConfig, args, cypressJson) => { let files = glob.sync(globSearchPatttern, {cmd: bsConfig.run_settings.cypressConfigFilePath, matchBase: true, ignore: ignoreFiles}); return files; }; + +exports.getBrowserCombinations = (bsConfig) => { + let osBrowserArray = []; + let osBrowser = ""; + if (bsConfig.browsers) { + bsConfig.browsers.forEach((element) => { + osBrowser = element.os + '-' + element.browser; + element.versions.forEach((version) => { + osBrowserArray.push(osBrowser + version); + }); + }); + } + return osBrowserArray; +}; diff --git a/test/unit/bin/commands/runs.js b/test/unit/bin/commands/runs.js index 749e0ec2..4e9e4991 100644 --- a/test/unit/bin/commands/runs.js +++ b/test/unit/bin/commands/runs.js @@ -189,7 +189,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); - getNumberOfSpecFilesStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub().returns([]); }); afterEach(() => { @@ -243,6 +243,7 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); sinon.assert.calledOnce(setLocalIdentifierStub); @@ -291,7 +292,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); - getNumberOfSpecFilesStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub().returns([]); }); afterEach(() => { @@ -349,6 +350,7 @@ describe("runs", () => { .catch((error) => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(getConfigPathStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); sinon.assert.calledOnce(setLocalIdentifierStub); @@ -401,7 +403,7 @@ describe("runs", () => { setLocalIdentifierStub = sandbox.stub(); deleteResultsStub = sandbox.stub(); setDefaultAuthHashStub = sandbox.stub(); - getNumberOfSpecFilesStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub().returns([]); }); afterEach(() => { @@ -467,6 +469,7 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(validateBstackJsonStub); sinon.assert.calledOnce(capabilityValidatorStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); sinon.assert.calledOnce(setLocalIdentifierStub); @@ -525,7 +528,7 @@ describe("runs", () => { isUndefinedStub = sandbox.stub(); setLocalStub = sandbox.stub(); setLocalIdentifierStub = sandbox.stub(); - getNumberOfSpecFilesStub = sandbox.stub(); + getNumberOfSpecFilesStub = sandbox.stub().returns([]); }); afterEach(() => { @@ -597,6 +600,7 @@ describe("runs", () => { sinon.assert.calledOnce(getConfigPathStub); sinon.assert.calledOnce(validateBstackJsonStub); sinon.assert.calledOnce(capabilityValidatorStub); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnce(setParallelsStub); sinon.assert.calledOnce(setLocalStub); sinon.assert.calledOnce(setLocalIdentifierStub); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 6967899d..c1107b77 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -302,7 +302,7 @@ describe('utils', () => { let args = testObjects.initSampleArgs; it('should call sendUsageReport', () => { - sandbox = sinon.createSandbox(); + let sandbox = sinon.createSandbox(); sendUsageReportStub = sandbox .stub(utils, 'sendUsageReport') .callsFake(function () { @@ -953,22 +953,106 @@ describe('utils', () => { describe('getNumberOfSpecFiles', () => { it('glob search pattern should be equal to bsConfig.run_settings.specs', () => { - sinon.stub(glob, 'sync').returns(true); + let getNumberOfSpecFilesStub = sinon.stub(glob, 'sync'); let bsConfig = { run_settings: { + specs: 'specs', cypressConfigFilePath: 'cypressConfigFilePath', exclude: 'exclude' }, }; - // sinon.assert.calledOnce(getNumberOfSpecFilesStub); - // sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, 'specs', { - // cmd: 'cypressConfigFilePath', - // matchBase: true, - // ignore: 'exclude', - // }); + + utils.getNumberOfSpecFiles(bsConfig,{},{}); + sinon.assert.calledOnce(getNumberOfSpecFilesStub); + sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, 'specs', { + cmd: 'cypressConfigFilePath', + matchBase: true, + ignore: 'exclude', + }); + glob.sync.restore(); + }); + + it('glob search pattern should be equal to default', () => { + let getNumberOfSpecFilesStub = sinon.stub(glob, 'sync'); + let bsConfig = { + run_settings: { + cypressConfigFilePath: 'cypressConfigFilePath', + exclude: 'exclude' + }, + }; + utils.getNumberOfSpecFiles(bsConfig,{},{}); + + sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, `cypress/integration/**/*.+(${constant.specFileTypes.join("|")})`, { + cmd: 'cypressConfigFilePath', + matchBase: true, + ignore: 'exclude', + }); + glob.sync.restore(); + }); + + it('glob search pattern should be equal to default with integrationFolder', () => { + let getNumberOfSpecFilesStub = sinon.stub(glob, 'sync'); + let bsConfig = { + run_settings: { + cypressConfigFilePath: 'cypressConfigFilePath', + exclude: 'exclude', + }, + }; + + utils.getNumberOfSpecFiles(bsConfig, {}, { "integrationFolder": "specs"}); + + sinon.assert.calledOnceWithExactly( + getNumberOfSpecFilesStub, + `specs/**/*.+(${constant.specFileTypes.join('|')})`, + { + cmd: 'cypressConfigFilePath', + matchBase: true, + ignore: 'exclude', + } + ); glob.sync.restore(); }); + + }); + + describe('getBrowserCombinations', () => { + + it('returns correct number of browserCombinations for one combination', () => { + let bsConfig = { + browsers: [ + { + browser: 'chrome', + os: 'OS X Mojave', + versions: ['85'], + }, + ] + }; + chai.assert.deepEqual(utils.getBrowserCombinations(bsConfig), ['OS X Mojave-chrome85']); + }); + + it('returns correct number of browserCombinations for multiple combinations', () => { + let bsConfig = { + browsers: [ + { + browser: 'chrome', + os: 'OS X Mojave', + versions: ['85'], + }, + { + browser: 'chrome', + os: 'OS X Catalina', + versions: ['85','84'], + }, + ], + }; + chai.assert.deepEqual(utils.getBrowserCombinations(bsConfig), [ + 'OS X Mojave-chrome85', + 'OS X Catalina-chrome85', + 'OS X Catalina-chrome84' + ]); + }); + }); }); From 609bb926bfe2646639dc806ad200d7664f784718 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 6 Nov 2020 15:09:06 +0530 Subject: [PATCH 4/7] Added unit test cases and handle -1 parallels case --- bin/commands/runs.js | 2 +- bin/helpers/constants.js | 2 +- bin/helpers/utils.js | 6 ++++- test/unit/bin/helpers/utils.js | 47 ++++++++++++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/bin/commands/runs.js b/bin/commands/runs.js index 6af04b32..ac73e00f 100644 --- a/bin/commands/runs.js +++ b/bin/commands/runs.js @@ -48,7 +48,7 @@ module.exports = function run(args) { return capabilityHelper.validate(bsConfig, args).then(function (cypressJson) { //get the number of spec files - let specFiles = utils.getNumberOfSpecFiles(bsConfig,args,cypressJson); + let specFiles = utils.getNumberOfSpecFiles(bsConfig, args, cypressJson); // accept the number of parallels utils.setParallels(bsConfig, args, specFiles.length); diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index 02b206fa..ed8021d9 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -91,7 +91,7 @@ const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json'] -const specFileTypes = ['js', 'ts', 'feature', 'jsx', 'coffee', 'cjsx'] +const specFileTypes = ['js', 'ts', 'feature'] const DEFAULT_CYPRESS_SPEC_PATH = "cypress/integration" diff --git a/bin/helpers/utils.js b/bin/helpers/utils.js index bbb3cfb2..5c33e6ed 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -116,7 +116,11 @@ exports.setParallels = (bsConfig, args, numOfSpecs) => { } let browserCombinations = this.getBrowserCombinations(bsConfig); let maxParallels = browserCombinations.length * numOfSpecs; - if (bsConfig['run_settings']['parallels'] > maxParallels) { + if (numOfSpecs <= 0) { + bsConfig['run_settings']['parallels'] = browserCombinations.length; + return; + } + if (bsConfig['run_settings']['parallels'] > maxParallels && bsConfig['run_settings']['parallels'] != -1 ) { logger.warn( `Using ${maxParallels} machines instead of ${bsConfig['run_settings']['parallels']} that you configured as there are ${numOfSpecs} specs to be run on ${browserCombinations.length} browser combinations.` ); diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index c1107b77..954fabe8 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -140,13 +140,25 @@ describe('utils', () => { }); describe('setParallels', () => { + var sandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + sandbox.stub(utils,'getBrowserCombinations').returns(['a','b']); + }); + + afterEach(() => { + sandbox.restore(); + sinon.restore(); + }); + it('should set bsconfig parallels equal to value provided in args', () => { let bsConfig = { run_settings: { parallels: 10, }, }; - utils.setParallels(bsConfig, {parallels: 100}); + + utils.setParallels(bsConfig, {parallels: 100}, 100); expect(bsConfig['run_settings']['parallels']).to.be.eq(100); }); @@ -156,9 +168,40 @@ describe('utils', () => { parallels: 10, }, }; - utils.setParallels(bsConfig, {parallels: undefined}); + utils.setParallels(bsConfig, {parallels: undefined}, 10); expect(bsConfig['run_settings']['parallels']).to.be.eq(10); }); + + it('should set bsconfig parallels to browserCombinations.length if numOfSpecs is zero', () => { + let bsConfig = { + run_settings: { + parallels: 10, + }, + }; + utils.setParallels(bsConfig, {parallels: undefined}, 0); + expect(bsConfig['run_settings']['parallels']).to.be.eq(2); + }); + + it('shouldnot set bsconfig parallels if parallels is -1', () => { + let bsConfig = { + run_settings: { + parallels: -1, + }, + }; + utils.setParallels(bsConfig, {parallels: undefined}, 2); + expect(bsConfig['run_settings']['parallels']).to.be.eq(-1); + }); + + it('should set bsconfig parallels if parallels is greater than numOfSpecs * combinations', () => { + let bsConfig = { + run_settings: { + parallels: 100, + }, + }; + utils.setParallels(bsConfig, {parallels: undefined}, 2); + expect(bsConfig['run_settings']['parallels']).to.be.eq(4); + }); + }); describe('getErrorCodeFromErr', () => { From 303faa9e87759c17559fec9d30b84f851fe5e79e Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 9 Nov 2020 18:21:45 +0530 Subject: [PATCH 5/7] Remove unused imports --- test/unit/bin/helpers/utils.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 954fabe8..106bf458 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1,7 +1,5 @@ 'use strict'; -const { it } = require('mocha'); const path = require('path'); -const { sandbox } = require('sinon'); const chai = require('chai'), expect = chai.expect, From adf556b0f6aaf683dff135d7abf82ff202d6c9bf Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 17 Nov 2020 17:45:06 +0530 Subject: [PATCH 6/7] Allocate parallels cwd bug fix --- 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 6ec7ea82..8415c8e8 100644 --- a/bin/helpers/utils.js +++ b/bin/helpers/utils.js @@ -334,7 +334,7 @@ exports.getNumberOfSpecFiles = (bsConfig, args, cypressJson) => { let testFolderPath = cypressJson.integrationFolder || Constants.DEFAULT_CYPRESS_SPEC_PATH; let globSearchPatttern = bsConfig.run_settings.specs || `${testFolderPath}/**/*.+(${Constants.specFileTypes.join("|")})`; let ignoreFiles = args.exclude || bsConfig.run_settings.exclude; - let files = glob.sync(globSearchPatttern, {cmd: bsConfig.run_settings.cypressConfigFilePath, matchBase: true, ignore: ignoreFiles}); + let files = glob.sync(globSearchPatttern, {cwd: bsConfig.run_settings.cypressProjectDir, matchBase: true, ignore: ignoreFiles}); return files; }; From a96d7f4f9e7318e1b304d90a66b54a4706377e17 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Tue, 17 Nov 2020 17:48:17 +0530 Subject: [PATCH 7/7] cwd unit test case fix --- test/unit/bin/helpers/utils.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/unit/bin/helpers/utils.js b/test/unit/bin/helpers/utils.js index 42b62c39..2fedf697 100644 --- a/test/unit/bin/helpers/utils.js +++ b/test/unit/bin/helpers/utils.js @@ -1006,15 +1006,15 @@ describe('utils', () => { let bsConfig = { run_settings: { specs: 'specs', - cypressConfigFilePath: 'cypressConfigFilePath', - exclude: 'exclude' + cypressProjectDir: 'cypressProjectDir', + exclude: 'exclude', }, }; utils.getNumberOfSpecFiles(bsConfig,{},{}); sinon.assert.calledOnce(getNumberOfSpecFilesStub); sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, 'specs', { - cmd: 'cypressConfigFilePath', + cwd: 'cypressProjectDir', matchBase: true, ignore: 'exclude', }); @@ -1025,15 +1025,15 @@ describe('utils', () => { let getNumberOfSpecFilesStub = sinon.stub(glob, 'sync'); let bsConfig = { run_settings: { - cypressConfigFilePath: 'cypressConfigFilePath', - exclude: 'exclude' + cypressProjectDir: 'cypressProjectDir', + exclude: 'exclude', }, }; utils.getNumberOfSpecFiles(bsConfig,{},{}); sinon.assert.calledOnceWithExactly(getNumberOfSpecFilesStub, `cypress/integration/**/*.+(${constant.specFileTypes.join("|")})`, { - cmd: 'cypressConfigFilePath', + cwd: 'cypressProjectDir', matchBase: true, ignore: 'exclude', }); @@ -1044,7 +1044,7 @@ describe('utils', () => { let getNumberOfSpecFilesStub = sinon.stub(glob, 'sync'); let bsConfig = { run_settings: { - cypressConfigFilePath: 'cypressConfigFilePath', + cypressProjectDir: 'cypressProjectDir', exclude: 'exclude', }, }; @@ -1055,7 +1055,7 @@ describe('utils', () => { getNumberOfSpecFilesStub, `specs/**/*.+(${constant.specFileTypes.join('|')})`, { - cmd: 'cypressConfigFilePath', + cwd: 'cypressProjectDir', matchBase: true, ignore: 'exclude', }