Skip to content

Commit

Permalink
Merge pull request #54 from browserstack/cypress_config_file_support
Browse files Browse the repository at this point in the history
Cypress config file support
  • Loading branch information
suryart committed Sep 25, 2020
2 parents 9661f75 + 3886bd5 commit 81c3235
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 22 deletions.
3 changes: 3 additions & 0 deletions bin/commands/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ module.exports = function run(args) {
// accept the build name from command line if provided
utils.setBuildName(bsConfig, args);

// set cypress config filename
utils.setCypressConfigFilename(bsConfig, args);

// accept the specs list from command line if provided
utils.setUserSpecs(bsConfig, args);

Expand Down
12 changes: 10 additions & 2 deletions bin/helpers/archiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ const fs = require("fs");
const archiver = require("archiver"),
Constants = require('../helpers/constants'),
logger = require("./logger").winstonLogger,
utils = require('../helpers/utils');
utils = require('../helpers/utils'),
path = require('path');

const archiveSpecs = (runSettings, filePath, excludeFiles) => {
return new Promise(function (resolve, reject) {
var output = fs.createWriteStream(filePath);

var cypressFolderPath = runSettings.cypress_proj_dir;
var cypressFolderPath = path.dirname(runSettings.cypressConfigFilePath);

var archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
Expand Down Expand Up @@ -59,6 +60,13 @@ const archiveSpecs = (runSettings, filePath, excludeFiles) => {
archive.append(packageJSONString, { name: 'browserstack-package.json' });
}

// do not add cypress.json if arg provided is false
if (runSettings.cypress_config_file && runSettings.cypress_config_filename !== 'false') {
let cypressJSON = JSON.parse(fs.readFileSync(runSettings.cypressConfigFilePath));
let cypressJSONString = JSON.stringify(cypressJSON, null, 4);
archive.append(cypressJSONString, { name: 'cypress.json' });
}

archive.finalize();
});
}
Expand Down
36 changes: 24 additions & 12 deletions bin/helpers/capabilityHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ const caps = (bsConfig, zip) => {
obj.projectNotifyURL = bsConfig.run_settings.project_notify_URL;
obj.parallels = bsConfig.run_settings.parallels;

if (!Utils.isUndefined(bsConfig.run_settings.cypress_config_filename)) {
obj.cypress_config_filename = bsConfig.run_settings.cypress_config_filename;
}

if (!Utils.isUndefined(bsConfig.run_settings.specs)){
obj.specs = bsConfig.run_settings.specs;
}
Expand All @@ -78,7 +82,7 @@ const caps = (bsConfig, zip) => {
}

if(obj.parallels === Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE) obj.parallels = undefined

if (obj.project) logger.log(`Project name is: ${obj.project}`);

if (obj.customBuildName) logger.log(`Build name is: ${obj.customBuildName}`);
Expand Down Expand Up @@ -106,26 +110,34 @@ const validate = (bsConfig, args) => {

if (!bsConfig.run_settings) reject(Constants.validationMessages.EMPTY_RUN_SETTINGS);

if (!bsConfig.run_settings.cypress_proj_dir) reject(Constants.validationMessages.EMPTY_CYPRESS_PROJ_DIR);
if (!bsConfig.run_settings.cypress_proj_dir && !bsConfig.run_settings.userProvidedCypessConfigFile) {
reject(Constants.validationMessages.EMPTY_CYPRESS_PROJ_DIR);
}

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

// if parallels specified via arguments validate only arguments
if (!Utils.isUndefined(args) && !Utils.isUndefined(args.parallels) && !Utils.isParallelValid(args.parallels)) reject(Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION);

if (!fs.existsSync(path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json'))) reject(Constants.validationMessages.CYPRESS_JSON_NOT_FOUND + bsConfig.run_settings.cypress_proj_dir);
// validate if config file provided exists or not when cypress_config_file provided
// validate the cypressProjectDir key otherwise.
let cypressConfigFilePath = bsConfig.run_settings.cypressConfigFilePath;

if (!fs.existsSync(cypressConfigFilePath) && bsConfig.run_settings.cypress_config_filename !== 'false') reject(Constants.validationMessages.INVALID_CYPRESS_CONFIG_FILE);

try {
let cypressJson = fs.readFileSync(path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json'));
cypressJson = JSON.parse(cypressJson);
// Cypress Json Base Url & Local true check
if (!Utils.isUndefined(cypressJson.baseUrl) && cypressJson.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET);

// Detect if the user is not using the right directory structure, and throw an error
if (!Utils.isUndefined(cypressJson.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypress_proj_dir,cypressJson.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE);

} catch (error) {
if (bsConfig.run_settings.cypress_config_filename !== 'false') {
let cypressJsonContent = fs.readFileSync(cypressConfigFilePath);
cypressJson = JSON.parse(cypressJsonContent);

// Cypress Json Base Url & Local true check
if (!Utils.isUndefined(cypressJson.baseUrl) && cypressJson.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET);

// Detect if the user is not using the right directory structure, and throw an error
if (!Utils.isUndefined(cypressJson.integrationFolder) && !Utils.isCypressProjDirValid(bsConfig.run_settings.cypressProjectDir,cypressJson.integrationFolder)) reject(Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE);
}
} catch(error){
reject(Constants.validationMessages.INVALID_CYPRESS_JSON)
}

Expand Down
5 changes: 4 additions & 1 deletion bin/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const validationMessages = {
NOT_VALID_JSON: "browerstack.json is not a valid json",
INVALID_EXTENSION: "Invalid files, please remove these files and try again.",
INVALID_PARALLELS_CONFIGURATION: "Invalid value specified for parallels to use. Maximum parallels to use should be a number greater than 0.",
INVALID_CYPRESS_CONFIG_FILE: "Invalid cypress_config_file",
CYPRESS_JSON_NOT_FOUND: "cypress.json file is not found at cypress_proj_dir path ",
INVALID_CYPRESS_JSON: "cypress.json is not a valid json",
INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication",
Expand Down Expand Up @@ -60,7 +61,9 @@ const cliMessages = {
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
INFO: "Run your tests on BrowserStack.",
DESC: "Path to BrowserStack config",
CYPRESS_DESC: "Path to Cypress config file",
CONFIG_DEMAND: "config file is required",
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
BUILD_NAME: "The build name you want to use to name your test runs",
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
Expand All @@ -86,7 +89,7 @@ const messageTypes = {

const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf', 'jpg', 'jpeg', 'png', 'zip'];

const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip']
const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json']

module.exports = Object.freeze({
userMessages,
Expand Down
2 changes: 1 addition & 1 deletion bin/helpers/usageReporting.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function ci_environment() {
}
// CircleCI
if (env.CI === "true" && env.CIRCLECI === "true") {
return "CircleCI";
return "CircleCI";
}
// Travis CI
if (env.CI === "true" && env.TRAVIS === "true") {
Expand Down
40 changes: 40 additions & 0 deletions bin/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ exports.getErrorCodeFromMsg = (errMsg) => {
case Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE:
errorCode = "invalid_directory_structure";
break;
case Constants.validationMessages.INVALID_CYPRESS_CONFIG_FILE:
errorCode = "invalid_cypress_config_file";
break;
}
if (
errMsg.includes("Please use --config-file <path to browserstack.json>.")
Expand Down Expand Up @@ -140,6 +143,43 @@ exports.setBuildName = (bsConfig, args) => {
}
};

exports.searchForOption = (option) => {
return (process.argv.indexOf(option) > -1);
}

exports.verifyCypressConfigFileOption = () => {
let ccfOptionsSet = (this.searchForOption('-ccf') || this.searchForOption('--ccf'));
let cypressConfigFileSet = (this.searchForOption('-cypress-config-file') || this.searchForOption('--cypress-config-file'));
let cypressConfigOptionsSet = (this.searchForOption('-cypressConfigFile') || this.searchForOption('--cypressConfigFile'));
return (ccfOptionsSet || cypressConfigFileSet || cypressConfigOptionsSet);
}

// TODO: Remove when cleaningup cypress_proj_dir
//
// 1. Remove demand from runner.js for --ccf option.
// 2. Remove the strict check functions: verifyCypressConfigFileOption
// 3. Just use the args.cypressConfigFile for checking the value for cypress config file.
exports.setCypressConfigFilename = (bsConfig, args) => {
let userProvidedCypessConfigFile = this.verifyCypressConfigFileOption();

bsConfig.run_settings.userProvidedCypessConfigFile = (userProvidedCypessConfigFile || (!this.isUndefined(bsConfig.run_settings.cypress_config_file)));

if (userProvidedCypessConfigFile || this.isUndefined(bsConfig.run_settings.cypress_config_file)) {
bsConfig.run_settings.cypress_config_file = args.cypressConfigFile;
bsConfig.run_settings.cypress_config_filename = path.basename(args.cypressConfigFile);
} else if (!this.isUndefined(bsConfig.run_settings.cypress_config_file)) {
bsConfig.run_settings.cypress_config_filename = path.basename(bsConfig.run_settings.cypress_config_file);
}

if (bsConfig.run_settings.userProvidedCypessConfigFile){
bsConfig.run_settings.cypressConfigFilePath = bsConfig.run_settings.cypress_config_file;
bsConfig.run_settings.cypressProjectDir = path.dirname(bsConfig.run_settings.cypress_config_file);
} else {
bsConfig.run_settings.cypressConfigFilePath = path.join(bsConfig.run_settings.cypress_proj_dir, 'cypress.json');
bsConfig.run_settings.cypressProjectDir = bsConfig.run_settings.cypress_proj_dir;
}
}

// specs can be passed from bstack configuration file
// specs can be passed via command line args as a string
// command line args takes precedence over config
Expand Down
9 changes: 9 additions & 0 deletions bin/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ var argv = yargs
demand: true,
demand: Constants.cliMessages.RUN.CONFIG_DEMAND
},
'ccf': {
alias: 'cypress-config-file',
describe: Constants.cliMessages.RUN.CYPRESS_DESC,
default: './cypress.json',
type: 'string',
nargs: 1,
demand: true,
demand: Constants.cliMessages.RUN.CYPRESS_CONFIG_DEMAND
},
'disable-usage-reporting': {
default: undefined,
description: Constants.cliMessages.COMMON.DISABLE_USAGE_REPORTING,
Expand Down
2 changes: 1 addition & 1 deletion bin/templates/configTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports = function () {
}
],
"run_settings": {
"cypress_proj_dir" : "/path/to/directory-that-contains-<cypress.json>-file",
"cypress_config_file" : "/path/to/<cypress config file>.json",
"project_name": "project-name",
"build_name": "build-name",
"exclude": [],
Expand Down
10 changes: 10 additions & 0 deletions test/unit/bin/commands/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe("runs", () => {
setUsernameStub = sandbox.stub();
setAccessKeyStub = sandbox.stub();
setBuildNameStub = sandbox.stub();
setCypressConfigFilenameStub = sandbox.stub();
setUserSpecsStub = sandbox.stub();
setTestEnvsStub = sandbox.stub();
getConfigPathStub = sandbox.stub();
Expand Down Expand Up @@ -118,6 +119,7 @@ describe("runs", () => {
setUsername: setUsernameStub,
setAccessKey: setAccessKeyStub,
setBuildName: setBuildNameStub,
setCypressConfigFilename: setCypressConfigFilenameStub,
setUserSpecs: setUserSpecsStub,
setTestEnvs: setTestEnvsStub,
getConfigPath: getConfigPathStub,
Expand Down Expand Up @@ -169,6 +171,7 @@ describe("runs", () => {
setAccessKeyStub = sandbox.stub();
getConfigPathStub = sandbox.stub();
setBuildNameStub = sandbox.stub();
setCypressConfigFilenameStub = sandbox.stub();
setUserSpecsStub = sandbox.stub();
setTestEnvsStub = sandbox.stub();
validateBstackJsonStub = sandbox.stub();
Expand Down Expand Up @@ -202,6 +205,7 @@ describe("runs", () => {
setUsername: setUsernameStub,
setAccessKey: setAccessKeyStub,
setBuildName: setBuildNameStub,
setCypressConfigFilename: setCypressConfigFilenameStub,
setUserSpecs: setUserSpecsStub,
setTestEnvs: setTestEnvsStub,
setUsageReportingFlag: setUsageReportingFlagStub,
Expand Down Expand Up @@ -263,6 +267,7 @@ describe("runs", () => {
setUsernameStub = sandbox.stub();
setAccessKeyStub = sandbox.stub();
setBuildNameStub = sandbox.stub();
setCypressConfigFilenameStub = sandbox.stub();
setUserSpecsStub = sandbox.stub();
setTestEnvsStub = sandbox.stub();
getConfigPathStub = sandbox.stub();
Expand Down Expand Up @@ -297,6 +302,7 @@ describe("runs", () => {
setUsername: setUsernameStub,
setAccessKey: setAccessKeyStub,
setBuildName: setBuildNameStub,
setCypressConfigFilename: setCypressConfigFilenameStub,
setUserSpecs: setUserSpecsStub,
setTestEnvs: setTestEnvsStub,
setUsageReportingFlag: setUsageReportingFlagStub,
Expand Down Expand Up @@ -365,6 +371,7 @@ describe("runs", () => {
setUsernameStub = sandbox.stub();
setAccessKeyStub = sandbox.stub();
setBuildNameStub = sandbox.stub();
setCypressConfigFilenameStub = sandbox.stub();
setUserSpecsStub = sandbox.stub();
setTestEnvsStub = sandbox.stub();
getConfigPathStub = sandbox.stub();
Expand Down Expand Up @@ -400,6 +407,7 @@ describe("runs", () => {
setUsername: setUsernameStub,
setAccessKey: setAccessKeyStub,
setBuildName: setBuildNameStub,
setCypressConfigFilename: setCypressConfigFilenameStub,
setUserSpecs: setUserSpecsStub,
setTestEnvs: setTestEnvsStub,
setUsageReportingFlag: setUsageReportingFlagStub,
Expand Down Expand Up @@ -479,6 +487,7 @@ describe("runs", () => {
setUsernameStub = sandbox.stub();
setAccessKeyStub = sandbox.stub();
setBuildNameStub = sandbox.stub();
setCypressConfigFilenameStub = sandbox.stub();
setUserSpecsStub = sandbox.stub();
setTestEnvsStub = sandbox.stub();
getConfigPathStub = sandbox.stub();
Expand Down Expand Up @@ -517,6 +526,7 @@ describe("runs", () => {
setUsername: setUsernameStub,
setAccessKey: setAccessKeyStub,
setBuildName: setBuildNameStub,
setCypressConfigFilename: setCypressConfigFilenameStub,
setUserSpecs: setUserSpecsStub,
setTestEnvs: setTestEnvsStub,
setUsageReportingFlag: setUsageReportingFlagStub,
Expand Down
41 changes: 38 additions & 3 deletions test/unit/bin/helpers/capabilityHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ describe("capabilityHelper.js", () => {
},
],
run_settings: {
cypress_proj_dir: "random path"
cypress_proj_dir: "random path",
cypressConfigFilePath: "random path"
},
};
});
Expand Down Expand Up @@ -781,7 +782,9 @@ describe("capabilityHelper.js", () => {
},
],
run_settings: {
cypress_proj_dir: "random path"
cypress_proj_dir: "random path",
cypressConfigFilePath: "random path",
cypressProjectDir: "random path"
},
};
});
Expand All @@ -797,7 +800,7 @@ describe("capabilityHelper.js", () => {
.catch((error) => {
chai.assert.equal(
error,
Constants.validationMessages.CYPRESS_JSON_NOT_FOUND + "random path"
Constants.validationMessages.INVALID_CYPRESS_CONFIG_FILE
);
fs.existsSync.restore();
});
Expand Down Expand Up @@ -858,10 +861,42 @@ describe("capabilityHelper.js", () => {
error,
Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE
);

fs.existsSync.restore();
fs.readFileSync.restore();
});
});

context("cypress config file set to false", () => {
beforeEach(function() {
readFileSpy = sinon.stub(fs, 'readFileSync');
jsonParseSpy = sinon.stub(JSON, 'parse');
});

afterEach(function() {
readFileSpy.restore();
jsonParseSpy.restore();
});

it("does not validate with cypress config filename set to false", () => {
// sinon.stub(fs, 'existsSync').returns(false);
bsConfig.run_settings.cypressConfigFilePath = 'false';
bsConfig.run_settings.cypress_config_filename = 'false';

return capabilityHelper
.validate(bsConfig, {})
.then(function (data) {
sinon.assert.notCalled(readFileSpy);
sinon.assert.notCalled(jsonParseSpy);
})
.catch((error) => {
chai.assert.equal(
error,
Constants.validationMessages.INCORRECT_DIRECTORY_STRUCTURE
);
});
})
});
});
});
});
2 changes: 1 addition & 1 deletion test/unit/bin/helpers/usageReporting.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ describe("usageReporting", () => {
expect(isUsageReportingEnabled()).to.be.undefined;
});
});

describe("ci_environment", () => {
afterEach(() => {
delete process.env.JENKINS_URL;
Expand Down
Loading

0 comments on commit 81c3235

Please sign in to comment.