browserstack-cypress-cli
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -48,2 +48,5 @@ 'use strict'; | ||
// run test in headed mode | ||
utils.setHeaded(bsConfig, args); | ||
// Validate browserstack.json values and parallels specified via arguments | ||
@@ -126,3 +129,3 @@ return capabilityHelper.validate(bsConfig, args).then(function (cypressJson) { | ||
// If parallels specified in arguments are invalid do not display browserstack.json is invalid message | ||
if (!(err === Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION && !utils.isUndefined(args.parallels))) { | ||
if (utils.isJSONInvalid(err, args)) { | ||
logger.error(Constants.validationMessages.NOT_VALID); | ||
@@ -129,0 +132,0 @@ } |
@@ -87,2 +87,8 @@ const logger = require("./logger").winstonLogger, | ||
} | ||
if (!Utils.isUndefined(bsConfig.run_settings.headless) && String(bsConfig.run_settings.headless) === "false"){ | ||
obj.headless = bsConfig.run_settings.headless; | ||
} else { | ||
logger.info(`Running your tests in headless mode. Use --headed arg to run in headful mode.`); | ||
} | ||
} | ||
@@ -143,3 +149,3 @@ | ||
// 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); | ||
if (!Utils.isUndefined(cypressJson.baseUrl) && cypressJson.baseUrl.includes("localhost") && !Utils.getLocalFlag(bsConfig.connection_settings)) reject(Constants.validationMessages.LOCAL_NOT_SET.replace("<baseUrlValue>", cypressJson.baseUrl)); | ||
@@ -146,0 +152,0 @@ // Detect if the user is not using the right directory structure, and throw an error |
@@ -18,3 +18,3 @@ let config = require("./config"); | ||
BUILD_REPORT_MESSAGE: "See the entire build report here:", | ||
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.", | ||
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach BrowserStack APIs. Please check your network or see if you need to whitelist *.browserstack.com", | ||
ZIP_UPLOAD_FAILED: "Zip Upload failed.", | ||
@@ -60,3 +60,3 @@ CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run", | ||
INVALID_DEFAULT_AUTH_PARAMS: "Your username and access key are required to run your tests on BrowserStack. Learn more at https://www.browserstack.com/docs/automate/cypress/authentication", | ||
LOCAL_NOT_SET: "To test <baseUrl value> on BrowserStack, you will have to set up Local testing. Read more here: https://www.browserstack.com/docs/automate/cypress/local-testing", | ||
LOCAL_NOT_SET: "To test <baseUrlValue> on BrowserStack, you will have to set up Local testing. Read more here: https://www.browserstack.com/docs/automate/cypress/local-testing", | ||
INCORRECT_DIRECTORY_STRUCTURE: "No tests to run. Note that your Cypress tests should be in the same directory where the cypress.json exists." | ||
@@ -98,2 +98,3 @@ }; | ||
BUILD_REPORT_MESSAGE: "See the entire build report here", | ||
HEADED: "Run your tests in a headed browser instead of a headless browser", | ||
}, | ||
@@ -120,7 +121,7 @@ COMMON: { | ||
const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf', 'jpg', 'jpeg', 'png', 'zip', 'npmrc', 'xml', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'jsx', 'coffee', 'cjsx']; | ||
const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf', 'jpg', 'jpeg', 'png', 'zip', 'npmrc', 'xml', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'jsx', 'coffee', 'cjsx', 'csv', 'tsv']; | ||
const filesToIgnoreWhileUploading = ['**/node_modules/**', 'node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json'] | ||
const specFileTypes = ['js', 'ts', 'feature'] | ||
const specFileTypes = ['js', 'ts', 'feature', 'jsx', 'coffee', 'cjsx']; | ||
@@ -127,0 +128,0 @@ const DEFAULT_CYPRESS_SPEC_PATH = "cypress/integration" |
@@ -138,2 +138,13 @@ const fs = require('fs'), | ||
} | ||
} else if (resp.statusCode === 422) { | ||
messageType = Constants.messageTypes.ERROR; | ||
errorCode = 'api_failed_build_generate_report'; | ||
try { | ||
response = JSON.parse(body); | ||
message = response.message; | ||
} catch (error) { | ||
logger.error(`Error generating the report: ${error}`); | ||
response = {message: message}; | ||
} | ||
logger.error(response.message); | ||
} else if (resp.statusCode != 200) { | ||
@@ -170,3 +181,3 @@ messageType = Constants.messageTypes.ERROR; | ||
let metaViewPort = `<meta name="viewport" content="width=device-width, initial-scale=1"> `; | ||
let pageTitle = `<title> Browserstack Cypress Report </title>`; | ||
let pageTitle = `<title> BrowserStack Cypress Report </title>`; | ||
let inlineCss = `<style type="text/css"> ${loadInlineCss()} </style>`; | ||
@@ -173,0 +184,0 @@ let head = `<head> ${metaCharSet} ${metaViewPort} ${pageTitle} ${inlineCss} </head>`; |
@@ -56,3 +56,3 @@ const tablePrinter = require('table'), // { table, getBorderCharacters } | ||
columns: { | ||
0: { alignment: 'left' }, | ||
0: { alignment: 'left' , width: 60 }, | ||
1: { alignment: 'left' }, | ||
@@ -69,3 +69,3 @@ 2: { alignment: 'left' }, | ||
drawHorizontalLine: (index, size) => { | ||
return (index === 0 || index === 1 || index === size); | ||
return (index === 0 || index === 1 || index === specData.length); | ||
} | ||
@@ -72,0 +72,0 @@ } |
@@ -11,3 +11,3 @@ "use strict"; | ||
let whileLoop = true, whileTries = config.retries, options, timeout = 3000, n = 10, tableConfig, stream, endTime, startTime = Date.now(); | ||
let whileLoop = true, whileTries = config.retries, options, timeout = 3000, n = 2, tableConfig, stream, endTime, startTime = Date.now(); | ||
let specSummary = { | ||
@@ -39,6 +39,6 @@ "specs": [], | ||
1: {alignment: 'center', width: 1}, | ||
2: {alignment: 'left', width: 50} | ||
2: {alignment: 'left', width: 100} | ||
}, | ||
columnDefault: { | ||
width: 25, | ||
width: 30, | ||
}, | ||
@@ -45,0 +45,0 @@ columnCount: 3, |
@@ -177,2 +177,5 @@ 'use strict'; | ||
let cli_details = cli_version_and_path(bsConfig); | ||
let data = { | ||
cypress_version: bsConfig.run_settings.cypress_version | ||
}; | ||
@@ -194,2 +197,3 @@ delete args.bstack_config; | ||
event_timestamp: new Date().toLocaleString(), | ||
data: JSON.stringify(data), | ||
...args, | ||
@@ -196,0 +200,0 @@ }, |
@@ -336,2 +336,8 @@ "use strict"; | ||
exports.setHeaded = (bsConfig, args) => { | ||
if (!this.isUndefined(args.headed) && args.headed === true) { | ||
bsConfig.run_settings.headless = false; | ||
} | ||
}; | ||
exports.getNumberOfSpecFiles = (bsConfig, args, cypressJson) => { | ||
@@ -384,1 +390,20 @@ let testFolderPath = cypressJson.integrationFolder || Constants.DEFAULT_CYPRESS_SPEC_PATH; | ||
} | ||
exports.isJSONInvalid = (err, args) => { | ||
let invalid = true | ||
if (err === Constants.validationMessages.INVALID_PARALLELS_CONFIGURATION && !this.isUndefined(args.parallels)) { | ||
return false | ||
} | ||
if (this.deleteBaseUrlFromError(err) === this.deleteBaseUrlFromError(Constants.validationMessages.LOCAL_NOT_SET)) { | ||
return false | ||
} | ||
return invalid | ||
} | ||
exports.deleteBaseUrlFromError = (err) => { | ||
return err.replace(/To test ([\s\S]*)on BrowserStack/g, 'To test on BrowserStack'); | ||
} | ||
@@ -203,2 +203,7 @@ #!/usr/bin/env node | ||
type: "boolean" | ||
}, | ||
'headed': { | ||
default: false, | ||
describe: Constants.cliMessages.RUN.HEADED, | ||
type: "boolean" | ||
} | ||
@@ -205,0 +210,0 @@ }) |
@@ -63,3 +63,4 @@ module.exports = function () { | ||
"package_config_options": { | ||
} | ||
}, | ||
"headless": true | ||
}, | ||
@@ -66,0 +67,0 @@ "connection_settings": { |
{ | ||
"name": "browserstack-cypress-cli", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"description": "BrowserStack Cypress CLI for Cypress integration with BrowserStack's remote devices.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,2 +8,3 @@ const chai = require("chai"), | ||
testObjects = require("../../support/fixtures/testObjects"); | ||
const { setHeaded } = require("../../../../bin/helpers/utils"); | ||
@@ -86,2 +87,3 @@ const proxyquire = require("proxyquire").noCallThru(); | ||
validateBstackJsonStub = sandbox.stub(); | ||
isJSONInvalidStub = sandbox.stub(); | ||
setUsernameStub = sandbox.stub(); | ||
@@ -102,2 +104,3 @@ setAccessKeyStub = sandbox.stub(); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
deleteResultsStub = sandbox.stub(); | ||
@@ -132,4 +135,6 @@ setDefaultsStub = sandbox.stub(); | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
setHeaded: setHeadedStub, | ||
deleteResults: deleteResultsStub, | ||
setDefaults: setDefaultsStub | ||
setDefaults: setDefaultsStub, | ||
isJSONInvalid: isJSONInvalidStub | ||
}, | ||
@@ -157,2 +162,3 @@ '../helpers/capabilityHelper': { | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(deleteResultsStub); | ||
@@ -195,2 +201,3 @@ sinon.assert.calledOnce(setDefaultsStub); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
deleteResultsStub = sandbox.stub(); | ||
@@ -226,2 +233,3 @@ getNumberOfSpecFilesStub = sandbox.stub().returns([]); | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
setHeaded: setHeadedStub, | ||
deleteResults: deleteResultsStub, | ||
@@ -257,2 +265,3 @@ setDefaults: setDefaultsStub, | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(validateBstackJsonStub); | ||
@@ -301,2 +310,3 @@ sinon.assert.calledOnce(capabilityValidatorStub); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
deleteResultsStub = sandbox.stub(); | ||
@@ -332,2 +342,3 @@ getNumberOfSpecFilesStub = sandbox.stub().returns([]); | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
setHeaded: setHeadedStub, | ||
deleteResults: deleteResultsStub, | ||
@@ -367,2 +378,3 @@ getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(validateBstackJsonStub); | ||
@@ -415,2 +427,3 @@ sinon.assert.calledOnce(capabilityValidatorStub); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
deleteResultsStub = sandbox.stub(); | ||
@@ -446,2 +459,3 @@ getNumberOfSpecFilesStub = sandbox.stub().returns([]); | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
setHeaded: setHeadedStub, | ||
deleteResults: deleteResultsStub, | ||
@@ -489,2 +503,3 @@ getNumberOfSpecFiles: getNumberOfSpecFilesStub, | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(archiverStub); | ||
@@ -542,2 +557,3 @@ sinon.assert.calledOnce(setUsageReportingFlagStub); | ||
setLocalIdentifierStub = sandbox.stub(); | ||
setHeadedStub = sandbox.stub(); | ||
getNumberOfSpecFilesStub = sandbox.stub().returns([]); | ||
@@ -572,2 +588,3 @@ }); | ||
setLocalIdentifier: setLocalIdentifierStub, | ||
setHeaded: setHeadedStub, | ||
exportResults: exportResultsStub, | ||
@@ -620,2 +637,3 @@ deleteResults: deleteResultsStub, | ||
sinon.assert.calledOnce(setLocalIdentifierStub); | ||
sinon.assert.calledOnce(setHeadedStub); | ||
sinon.assert.calledOnce(archiverStub); | ||
@@ -622,0 +640,0 @@ sinon.assert.calledOnce(setUsageReportingFlagStub); |
@@ -417,2 +417,132 @@ const chai = require("chai"), | ||
}); | ||
context("headless in run_settings", () => { | ||
it("sets headless if false", () => { | ||
let headless = false; | ||
let zip_url = "bs://<random>"; | ||
let bsConfig = { | ||
auth: { | ||
username: "random", | ||
access_key: "random", | ||
}, | ||
browsers: [ | ||
{ | ||
browser: "chrome", | ||
os: "Windows 10", | ||
versions: ["78", "77"], | ||
}, | ||
], | ||
run_settings: { | ||
headless: headless | ||
}, | ||
}; | ||
return capabilityHelper | ||
.caps(bsConfig, { zip_url: zip_url }) | ||
.then(function (data) { | ||
let parsed_data = JSON.parse(data); | ||
chai.assert.equal(parsed_data.headless, headless); | ||
chai.assert.equal(parsed_data.env, undefined); | ||
}) | ||
.catch((error) => { | ||
chai.assert.fail("Promise error"); | ||
}); | ||
}); | ||
it("sets headless if string false", () => { | ||
let headless = "false"; | ||
let zip_url = "bs://<random>"; | ||
let bsConfig = { | ||
auth: { | ||
username: "random", | ||
access_key: "random", | ||
}, | ||
browsers: [ | ||
{ | ||
browser: "chrome", | ||
os: "Windows 10", | ||
versions: ["78", "77"], | ||
}, | ||
], | ||
run_settings: { | ||
headless: headless | ||
}, | ||
}; | ||
return capabilityHelper | ||
.caps(bsConfig, { zip_url: zip_url }) | ||
.then(function (data) { | ||
let parsed_data = JSON.parse(data); | ||
chai.assert.equal(parsed_data.headless, headless); | ||
chai.assert.equal(parsed_data.env, undefined); | ||
}) | ||
.catch((error) => { | ||
chai.assert.fail("Promise error"); | ||
}); | ||
}); | ||
it("does not set headless if true", () => { | ||
let headless = true; | ||
let zip_url = "bs://<random>"; | ||
let bsConfig = { | ||
auth: { | ||
username: "random", | ||
access_key: "random", | ||
}, | ||
browsers: [ | ||
{ | ||
browser: "chrome", | ||
os: "Windows 10", | ||
versions: ["78", "77"], | ||
}, | ||
], | ||
run_settings: { | ||
headless: headless | ||
}, | ||
}; | ||
return capabilityHelper | ||
.caps(bsConfig, { zip_url: zip_url }) | ||
.then(function (data) { | ||
let parsed_data = JSON.parse(data); | ||
chai.assert.equal(parsed_data.headless, undefined); | ||
chai.assert.equal(parsed_data.env, undefined); | ||
}) | ||
.catch((error) => { | ||
chai.assert.fail("Promise error"); | ||
}); | ||
}); | ||
it("does not set headless if truthy", () => { | ||
let headless = "enable"; | ||
let zip_url = "bs://<random>"; | ||
let bsConfig = { | ||
auth: { | ||
username: "random", | ||
access_key: "random", | ||
}, | ||
browsers: [ | ||
{ | ||
browser: "chrome", | ||
os: "Windows 10", | ||
versions: ["78", "77"], | ||
}, | ||
], | ||
run_settings: { | ||
headless: headless | ||
}, | ||
}; | ||
return capabilityHelper | ||
.caps(bsConfig, { zip_url: zip_url }) | ||
.then(function (data) { | ||
let parsed_data = JSON.parse(data); | ||
chai.assert.equal(parsed_data.headless, undefined); | ||
chai.assert.equal(parsed_data.env, undefined); | ||
}) | ||
.catch((error) => { | ||
chai.assert.fail("Promise error"); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -860,3 +990,3 @@ | ||
error, | ||
Constants.validationMessages.LOCAL_NOT_SET | ||
Constants.validationMessages.LOCAL_NOT_SET.replace("<baseUrlValue>", "http://localhost:3000") | ||
); | ||
@@ -863,0 +993,0 @@ fs.existsSync.restore(); |
@@ -114,2 +114,33 @@ const chai = require("chai"), | ||
context("non 200 response", () => { | ||
it("422 status, build available but running, cannot generate report", () => { | ||
let build = { message: 'The report cannot be generated as the build is running' }; | ||
let body = JSON.stringify(build); | ||
let requestStub = sandbox.stub(request, "get").yields(null, { statusCode: 422 }, body); | ||
let message = build.message; | ||
let messageType = Constants.messageTypes.ERROR; | ||
let errorCode = 'api_failed_build_generate_report'; | ||
const reporterHTML = proxyquire('../../../../bin/helpers/reporterHTML', { | ||
'./utils': { | ||
validateBstackJson: validateBstackJsonStub, | ||
setDefaultAuthHash: setDefaultAuthHashStub, | ||
setUsername: setUsernameStub, | ||
setAccessKey: setAccessKeyStub, | ||
getUserAgent: getUserAgentStub, | ||
setUsageReportingFlag: setUsageReportingFlagStub, | ||
setCypressConfigFilename: setCypressConfigFilenameStub, | ||
sendUsageReport: sendUsageReportStub, | ||
setDefaults: setDefaultsStub, | ||
getErrorCodeFromErr: getErrorCodeFromErrStub | ||
}, | ||
request: {get: requestStub} | ||
}); | ||
reporterHTML.reportGenerator(bsConfig, buildId, args); | ||
sinon.assert.calledOnce(requestStub); | ||
sinon.assert.calledOnce(getUserAgentStub); | ||
sinon.assert.calledOnceWithExactly(sendUsageReportStub, bsConfig, args, message, messageType, errorCode); | ||
}); | ||
it("400 status, build available, cannot generate report", () => { | ||
@@ -116,0 +147,0 @@ let build = { buildId: buildId, message: 'success', rows: [] }; |
@@ -95,7 +95,7 @@ "use strict"; | ||
let options = getTableConfig(); | ||
expect(options.columnDefault.width).to.equal(25); | ||
expect(options.columnDefault.width).to.equal(30); | ||
expect(options.columns[1].alignment).to.equal('center'); | ||
expect(options.columns[2].alignment).to.equal('left'); | ||
expect(options.columns[1].width).to.equal(1); | ||
expect(options.columns[2].width).to.equal(50); | ||
expect(options.columns[2].width).to.equal(100); | ||
expect(options.columnCount).to.equal(3); | ||
@@ -102,0 +102,0 @@ expect(getBorderConfigStub.calledOnce).to.be.true; |
@@ -148,3 +148,3 @@ 'use strict'; | ||
}); | ||
afterEach(() => { | ||
@@ -549,2 +549,28 @@ sandbox.restore(); | ||
describe('setHeaded', () => { | ||
it('sets the headless to false', () => { | ||
let args = { | ||
headed: true | ||
}; | ||
let bsConfig = { | ||
run_settings: {} | ||
}; | ||
utils.setHeaded(bsConfig, args); | ||
expect(bsConfig.run_settings.headless).to.be.eq(false); | ||
}); | ||
it('sets the headless to false', () => { | ||
let args = { | ||
headed: false | ||
}; | ||
let bsConfig = { | ||
run_settings: {} | ||
}; | ||
utils.setHeaded(bsConfig, args); | ||
expect(bsConfig.run_settings.headless).to.be.eq(undefined); | ||
}); | ||
}); | ||
describe('exportResults', () => { | ||
@@ -1151,2 +1177,32 @@ it('should export results to log/build_results.txt', () => { | ||
}) | ||
describe('#isJSONInvalid', () => { | ||
it('JSON is valid when error is parallel misconfiguration', () => { | ||
let error = constant.validationMessages.INVALID_PARALLELS_CONFIGURATION; | ||
let args = {"parallels": 4} | ||
expect(utils.isJSONInvalid(error, args)).to.eq(false) | ||
}); | ||
it('JSON is valid when local is not set for localhost url', () => { | ||
let error = constant.validationMessages.LOCAL_NOT_SET.replace("<baseUrlValue>", "localhost:4000"); | ||
expect(utils.isJSONInvalid(error, {})).to.eq(false) | ||
}); | ||
it('JSON is invalid for errors apart from Local or Prallell misconfiguration', () => { | ||
let error = constant.validationMessages.INCORRECT_AUTH_PARAMS; | ||
expect(utils.isJSONInvalid(error, {})).to.eq(true) | ||
}); | ||
}) | ||
describe('#deleteBaseUrlFromError', () => { | ||
it('Replace baseUrl in Local error string', () => { | ||
let error = constant.validationMessages.LOCAL_NOT_SET; | ||
expect(utils.deleteBaseUrlFromError(error)).to.match(/To test on BrowserStack/) | ||
}); | ||
it('should not replace baseUrl in other error string', () => { | ||
let error = constant.validationMessages.NOT_VALID_JSON; | ||
expect(utils.deleteBaseUrlFromError(error)).not.to.match(/To test on BrowserStack/) | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
289705
7488