Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

browserstack-cypress-cli

Package Overview
Dependencies
Maintainers
1
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

browserstack-cypress-cli - npm Package Compare versions

Comparing version 1.6.0 to 1.7.0

5

bin/commands/runs.js

@@ -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 @@ }

8

bin/helpers/capabilityHelper.js

@@ -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/)
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc