From 2eb472e7a8b7acc9ded0540a2862890349a558bb Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Fri, 20 Apr 2018 10:01:29 -0400 Subject: [PATCH 01/13] server: check CYPRESS_ENV variable when merging configs --- packages/server/lib/config.coffee | 10 +++++++ packages/server/lib/errors.coffee | 8 ++++++ packages/server/test/unit/config_spec.coffee | 30 +++++++++++++++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/packages/server/lib/config.coffee b/packages/server/lib/config.coffee index 6f9ac98ad590..1658be414fe9 100644 --- a/packages/server/lib/config.coffee +++ b/packages/server/lib/config.coffee @@ -180,6 +180,11 @@ validate = (file) -> module.exports = { getConfigKeys: -> configKeys + isValidCypressEnvValue: (value) -> + # names of config environments, see "config/app.yml" + names = ["development", "test", "staging", "production"] + _.includes(names, value) + whitelist: (obj = {}) -> _.pick(obj, configKeys) @@ -236,7 +241,12 @@ module.exports = { ## split out our own app wide env from user env variables ## and delete envFile config.env = @parseEnv(config, options.env, resolved) + config.cypressEnv = process.env["CYPRESS_ENV"] + log("using CYPRESS_ENV %s", config.cypressEnv) + if not @isValidCypressEnvValue(config.cypressEnv) + errors.throw("INVALID_CYPRESS_ENV", config.cypressEnv) + delete config.envFile if hosts = config.hosts diff --git a/packages/server/lib/errors.coffee b/packages/server/lib/errors.coffee index 901b7f7bf5ea..886f2a0e4545 100644 --- a/packages/server/lib/errors.coffee +++ b/packages/server/lib/errors.coffee @@ -361,6 +361,14 @@ API = { We looked but did not find a #{chalk.blue('cypress.json')} file in this folder: #{chalk.blue(arg1)} """ + when "INVALID_CYPRESS_ENV" + """ + We have detected unknown or unsupported CYPRESS_ENV value + + #{chalk.yellow(arg1)} + + Please do not modify CYPRESS_ENV value. + """ get: (type, arg1, arg2) -> msg = @getMsgByType(type, arg1, arg2) diff --git a/packages/server/test/unit/config_spec.coffee b/packages/server/test/unit/config_spec.coffee index b22f370f9f78..6a743e51c142 100644 --- a/packages/server/test/unit/config_spec.coffee +++ b/packages/server/test/unit/config_spec.coffee @@ -3,10 +3,11 @@ require("../spec_helper") _ = require("lodash") path = require("path") R = require("ramda") -config = require("#{root}lib/config") -configUtil = require("#{root}lib/util/config") -scaffold = require("#{root}lib/scaffold") -settings = require("#{root}lib/util/settings") +config = require("#{root}lib/config") +errors = require("#{root}lib/errors") +configUtil = require("#{root}lib/util/config") +scaffold = require("#{root}lib/scaffold") +settings = require("#{root}lib/util/settings") describe "lib/config", -> beforeEach -> @@ -17,6 +18,27 @@ describe "lib/config", -> afterEach -> process.env = @env + context "environment name check", -> + it "throws an error for unknown CYPRESS_ENV", -> + @sandbox.stub(errors, "throw").withArgs("INVALID_CYPRESS_ENV", "foo-bar") + process.env.CYPRESS_ENV = "foo-bar" + cfg = { + projectRoot: "/foo/bar/" + } + options = {} + config.mergeDefaults(cfg, options) + expect(errors.throw).have.been.calledOnce + + it "allows known CYPRESS_ENV", -> + @sandbox.stub(errors, "throw") + process.env.CYPRESS_ENV = "test" + cfg = { + projectRoot: "/foo/bar/" + } + options = {} + config.mergeDefaults(cfg, options) + expect(errors.throw).not.to.be.called + context ".get", -> beforeEach -> @projectPath = "/_test-output/path/to/project" From aa5475077904d4869ff2f0d4a69d151166681f50 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Fri, 20 Apr 2018 10:38:05 -0400 Subject: [PATCH 02/13] catch invalid CYPRESS_ENV value in CLI, close #1621 --- cli/__snapshots__/cli_spec.js | 27 +++++++++++++++++++++++++++ cli/__snapshots__/errors_spec.js | 3 ++- cli/index.js | 2 +- cli/lib/cli.js | 6 ++++++ cli/lib/errors.js | 22 ++++++++++++++++++++++ cli/lib/util.js | 20 ++++++++++++++++++++ cli/package.json | 2 +- cli/test/lib/cli_spec.js | 24 ++++++++++++++++++++++++ 8 files changed, 103 insertions(+), 3 deletions(-) diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index b0bf0dc880e4..91009141f80d 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -168,3 +168,30 @@ exports['cli -v no binary version 1'] = ` Cypress package version: 1.2.3 Cypress binary version: not installed ` + +exports['cli CYPRESS_ENV allows staging environment 1'] = ` + code: 0 + stderr: + ------- + + ------- + +` + +exports['cli CYPRESS_ENV catches environment "foo" 1'] = ` + code: 11 + stderr: + ------- + We have detected unknown or unsupported CYPRESS_ENV value + + Please unset CYPRESS_ENV variable and run Cypress again + ---------- + + foo + ---------- + + Platform: darwin (16.7.0) + Cypress Version: 0.0.0 + ------- + +` diff --git a/cli/__snapshots__/errors_spec.js b/cli/__snapshots__/errors_spec.js index 1d5ae4d7a0b4..db8f9ed40908 100644 --- a/cli/__snapshots__/errors_spec.js +++ b/cli/__snapshots__/errors_spec.js @@ -6,7 +6,8 @@ exports['errors individual has the following errors 1'] = [ "versionMismatch", "unexpected", "failedDownload", - "failedUnzip" + "failedUnzip", + "invalidCypressEnv" ] exports['errors .errors.formErrorText returns fully formed text message 1'] = ` diff --git a/cli/index.js b/cli/index.js index 7da84f9ec87b..250d3d4b52b1 100644 --- a/cli/index.js +++ b/cli/index.js @@ -23,6 +23,6 @@ switch (args.exec) { break default: - // export our node module interface + debug('exporting Cypress module interface') module.exports = require('./lib/cypress') } diff --git a/cli/lib/cli.js b/cli/lib/cli.js index 4d22b703ce61..d132f3b3b732 100644 --- a/cli/lib/cli.js +++ b/cli/lib/cli.js @@ -4,6 +4,7 @@ const { oneLine } = require('common-tags') const debug = require('debug')('cypress:cli') const util = require('./util') const logger = require('./logger') +const errors = require('./errors') const coerceFalse = (arg) => { return arg !== 'false' @@ -77,6 +78,11 @@ module.exports = { args = process.argv } + if (!util.isValidCypressEnvValue(process.env.CYPRESS_ENV)) { + debug('invalid CYPRESS_ENV value', process.env.CYPRESS_ENV) + return errors.exitWithError(errors.errors.invalidCypressEnv)(process.env.CYPRESS_ENV) + } + const program = new commander.Command() // bug in commaner not printing name diff --git a/cli/lib/errors.js b/cli/lib/errors.js index ca6b8d92f2fb..7203991babec 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -89,6 +89,12 @@ const unexpected = { `, } +const invalidCypressEnv = { + description: 'We have detected unknown or unsupported CYPRESS_ENV value', + solution: 'Please unset CYPRESS_ENV variable and run Cypress again', + exitCode: 11, +} + const getOsVersion = () => { if (os.platform() === 'linux') { return getos() @@ -171,8 +177,23 @@ const throwFormErrorText = (info) => (msg) => { .then(raise) } +/** + * Forms full error message with error and OS details, prints to the error output + * and then exits the process. + * @param {ErrorInformation} info Error information {description, solution} + * @example return exitWithError(errors.invalidCypressEnv)('foo') + */ +const exitWithError = (info) => (msg) => { + return formErrorText(info, msg).then((text) => { + // eslint-disable-next-line no-console + console.error(text) + process.exit(info.exitCode || 1) + }) +} + module.exports = { raise, + exitWithError, // formError, formErrorText, throwFormErrorText, @@ -185,5 +206,6 @@ module.exports = { unexpected, failedDownload, failedUnzip, + invalidCypressEnv, }, } diff --git a/cli/lib/util.js b/cli/lib/util.js index fe45ad4ab34d..acb70664ad43 100644 --- a/cli/lib/util.js +++ b/cli/lib/util.js @@ -36,9 +36,29 @@ function stdoutLineMatches (expectedLine, stdout) { return lines.some(lineMatches) } +/** + * Confirms if given value is a valid CYPRESS_ENV value. Undefined values + * are valid, because the system can set the default one. + * + * @param {string} value + * @example util.isValidCypressEnvValue(process.env.CYPRESS_ENV) + */ +function isValidCypressEnvValue (value) { + if (_.isUndefined(value)) { + // will get default value + return true + } + + // names of config environments, see "packages/server/config/app.yml" + const names = ['development', 'test', 'staging', 'production'] + return _.includes(names, value) +} + const util = { normalizeModuleOptions, + isValidCypressEnvValue, + isCi () { return isCi }, diff --git a/cli/package.json b/cli/package.json index 02571cfe5628..742813dad6ca 100644 --- a/cli/package.json +++ b/cli/package.json @@ -74,7 +74,7 @@ "clear-module": "^2.1.0", "dependency-check": "^2.8.0", "dtslint": "0.2.0", - "execa-wrap": "1.1.0", + "execa-wrap": "1.4.0", "nock": "^9.0.9", "shelljs": "0.7.8", "sinon": "3.2.1", diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index 10329b170fbe..ab28b8181dba 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -42,6 +42,30 @@ describe('cli', function () { ) }) + context('CYPRESS_ENV', () => { + it('allows staging environment', () => { + const options = { + env: { + CYPRESS_ENV: 'staging' + }, + // we are only interested in the exit code + filter: ['code', 'stderr'] + } + return execa('bin/cypress', ['help'], options).then(snapshot) + }) + + it('catches environment "foo"', () => { + const options = { + env: { + CYPRESS_ENV: 'foo' + }, + // we are only interested in the exit code + filter: ['code', 'stderr'] + } + return execa('bin/cypress', ['help'], options).then(snapshot) + }) + }) + context('cypress version', function () { it('reports package version', function (done) { this.sandbox.stub(util, 'pkgVersion').returns('1.2.3') From 1b0b08d2e91a7bc9ecb949ab1627f233c251d385 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Fri, 20 Apr 2018 10:38:19 -0400 Subject: [PATCH 03/13] linting --- cli/test/lib/cli_spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index ab28b8181dba..afbbb96b1d1a 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -46,10 +46,10 @@ describe('cli', function () { it('allows staging environment', () => { const options = { env: { - CYPRESS_ENV: 'staging' + CYPRESS_ENV: 'staging', }, // we are only interested in the exit code - filter: ['code', 'stderr'] + filter: ['code', 'stderr'], } return execa('bin/cypress', ['help'], options).then(snapshot) }) @@ -57,10 +57,10 @@ describe('cli', function () { it('catches environment "foo"', () => { const options = { env: { - CYPRESS_ENV: 'foo' + CYPRESS_ENV: 'foo', }, // we are only interested in the exit code - filter: ['code', 'stderr'] + filter: ['code', 'stderr'], } return execa('bin/cypress', ['help'], options).then(snapshot) }) From 7b9ae62374b4b4239060f05f6ba02435bb6315b5 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Sat, 21 Apr 2018 10:26:32 -0400 Subject: [PATCH 04/13] sanitize platform in test snapshot --- cli/__snapshots__/cli_spec.js | 4 ++-- cli/test/lib/cli_spec.js | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index 91009141f80d..1d5835902537 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -190,8 +190,8 @@ exports['cli CYPRESS_ENV catches environment "foo" 1'] = ` foo ---------- - Platform: darwin (16.7.0) - Cypress Version: 0.0.0 + Platform: xxx + Cypress Version: 1.2.3 ------- ` diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index afbbb96b1d1a..54778321b461 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -10,6 +10,7 @@ const verify = require(`${lib}/tasks/verify`) const install = require(`${lib}/tasks/install`) const snapshot = require('snap-shot-it') const execa = require('execa-wrap') +const os = require('os') describe('cli', function () { require('mocha-banner').register() @@ -43,6 +44,26 @@ describe('cli', function () { }) context('CYPRESS_ENV', () => { + /** + * Replaces line "Platform: ..." with "Platform: xxx" + * @param {string} s + */ + const replacePlatform = (s) => + s.replace(/Platform: .+/, 'Platform: xxx') + + /** + * Replaces line "Cypress Version: ..." with "Cypress Version: 1.2.3" + * @param {string} s + */ + const replaceCypressVersion = (s) => + s.replace(/Cypress Version: .+/, 'Cypress Version: 1.2.3') + + const sanitizePlatform = (text) => + text.split(os.eol) + .map(replacePlatform) + .map(replaceCypressVersion) + .join(os.eol) + it('allows staging environment', () => { const options = { env: { @@ -62,7 +83,9 @@ describe('cli', function () { // we are only interested in the exit code filter: ['code', 'stderr'], } - return execa('bin/cypress', ['help'], options).then(snapshot) + return execa('bin/cypress', ['help'], options) + .then(sanitizePlatform) + .then(snapshot) }) }) From f67ad26bffdee9be3ce95cbb3b1fb630dfb25e21 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Sat, 21 Apr 2018 10:26:43 -0400 Subject: [PATCH 05/13] linting --- cli/test/lib/cli_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index 54778321b461..f1b9c0b82128 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -84,8 +84,8 @@ describe('cli', function () { filter: ['code', 'stderr'], } return execa('bin/cypress', ['help'], options) - .then(sanitizePlatform) - .then(snapshot) + .then(sanitizePlatform) + .then(snapshot) }) }) From 2d1c774c33a70f867d1967f313f5253ed577bf97 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Mon, 23 Apr 2018 11:17:03 -0400 Subject: [PATCH 06/13] update error message text --- cli/__snapshots__/cli_spec.js | 4 ++-- cli/lib/errors.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index 1d5835902537..4e3bebc5a623 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -182,9 +182,9 @@ exports['cli CYPRESS_ENV catches environment "foo" 1'] = ` code: 11 stderr: ------- - We have detected unknown or unsupported CYPRESS_ENV value + Environment variable with reserved name "CYPRESS_ENV" was used. - Please unset CYPRESS_ENV variable and run Cypress again + Remove "CYPRESS_ENV" variable and run Cypress again. ---------- foo diff --git a/cli/lib/errors.js b/cli/lib/errors.js index 7203991babec..3993f64fba25 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -90,8 +90,8 @@ const unexpected = { } const invalidCypressEnv = { - description: 'We have detected unknown or unsupported CYPRESS_ENV value', - solution: 'Please unset CYPRESS_ENV variable and run Cypress again', + description: 'Environment variable with reserved name "CYPRESS_ENV" was used.', + solution: 'Remove "CYPRESS_ENV" variable and run Cypress again.', exitCode: 11, } From 8e11237ab2a3aa9fbc80258a1bdab3e5d7e56953 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 15:23:22 -0400 Subject: [PATCH 07/13] add missing comma --- cli/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/package.json b/cli/package.json index 3b83737173fb..7661793138a1 100644 --- a/cli/package.json +++ b/cli/package.json @@ -76,7 +76,6 @@ "chai-as-promised": "7.1.1", "chai-string": "1.4.0", "clear-module": "^2.1.0", - "strip-ansi": "4.0.0" "dependency-check": "3.4.1", "dtslint": "0.9.0", "execa-wrap": "1.4.0", @@ -88,7 +87,8 @@ "shelljs": "0.8.3", "sinon": "7.2.2", "snap-shot-it": "7.8.0", - "spawn-mock": "1.0.0" + "spawn-mock": "1.0.0", + "strip-ansi": "4.0.0" }, "files": [ "bin", From d2f47cfecb2d2287faa866cb7dcfbf2e14cf1180 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 15:30:41 -0400 Subject: [PATCH 08/13] fix finally merge in JS code --- cli/lib/errors.js | 88 +++++++++++++++++++++++++++-------------------- cli/package.json | 1 - 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/cli/lib/errors.js b/cli/lib/errors.js index 636593760422..e56044e4e053 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -36,7 +36,9 @@ const failedUnzip = { const missingApp = (binaryDir) => { return { - description: `No version of Cypress is installed in: ${chalk.cyan(binaryDir)}`, + description: `No version of Cypress is installed in: ${chalk.cyan( + binaryDir + )}`, solution: stripIndent` \nPlease reinstall Cypress by running: ${chalk.cyan('cypress install')} `, @@ -59,7 +61,8 @@ const binaryNotExecutable = (executable) => { const notInstalledCI = (executable) => { return { - description: 'The cypress npm package is installed, but the Cypress binary is missing.', + description: + 'The cypress npm package is installed, but the Cypress binary is missing.', solution: stripIndent`\n We expected the binary to be installed here: ${chalk.cyan(executable)} @@ -114,7 +117,7 @@ const smokeTestFailure = (smokeTestCommand, timedOut) => { const invalidSmokeTestDisplayError = { code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR', description: 'Cypress verification failed.', - solution (msg) { + solution (msg) { return stripIndent` Cypress failed to start after spawning a new Xvfb server. @@ -152,7 +155,8 @@ const missingDependency = { } const invalidCacheDirectory = { - description: 'Cypress cannot write to the cache directory due to file permissions', + description: + 'Cypress cannot write to the cache directory due to file permissions', solution: stripIndent` See discussion and possible solutions at ${chalk.blue(util.getGitHubIssueUrl(1281))} @@ -165,7 +169,8 @@ const versionMismatch = { } const unexpected = { - description: 'An unexpected error occurred while verifying the Cypress executable.', + description: + 'An unexpected error occurred while verifying the Cypress executable.', solution: stripIndent` Please search Cypress documentation for possible solutions: @@ -180,23 +185,28 @@ const unexpected = { } const invalidCypressEnv = { - description: 'Environment variable with reserved name "CYPRESS_ENV" was used.', + description: + 'Environment variable with reserved name "CYPRESS_ENV" was used.', solution: 'Remove "CYPRESS_ENV" variable and run Cypress again.', exitCode: 11, } -const getOsVersion = () => { - if (os.platform() === 'linux') { - return getos() - .then((osInfo) => [osInfo.dist, osInfo.release].join(' - ')) - .catch(() => os.release()) - } else { - return Promise.resolve(os.release()) - } +// const getOsVersion = () => { +// if (os.platform() === 'linux') { +// return getos() +// .then(osInfo => [osInfo.dist, osInfo.release].join(' - ')) +// .catch(() => os.release()) +// } +// return Promise.resolve(os.release()) + +// } + const removed = { CYPRESS_BINARY_VERSION: { description: stripIndent` - The environment variable CYPRESS_BINARY_VERSION has been renamed to CYPRESS_INSTALL_BINARY as of version ${chalk.green('3.0.0')} + The environment variable CYPRESS_BINARY_VERSION has been renamed to CYPRESS_INSTALL_BINARY as of version ${chalk.green( + '3.0.0' + )} `, solution: stripIndent` You should set CYPRESS_INSTALL_BINARY instead. @@ -204,7 +214,9 @@ const removed = { }, CYPRESS_SKIP_BINARY_INSTALL: { description: stripIndent` - The environment variable CYPRESS_SKIP_BINARY_INSTALL has been removed as of version ${chalk.green('3.0.0')} + The environment variable CYPRESS_SKIP_BINARY_INSTALL has been removed as of version ${chalk.green( + '3.0.0' + )} `, solution: stripIndent` To skip the binary install, set CYPRESS_INSTALL_BINARY=0 @@ -224,8 +236,7 @@ const CYPRESS_RUN_BINARY = { } function getPlatformInfo () { - return util.getOsVersionAsync() - .then((version) => { + return util.getOsVersionAsync().then((version) => { return stripIndent` Platform: ${os.platform()} (${version}) Cypress Version: ${util.pkgVersion()} @@ -234,8 +245,7 @@ function getPlatformInfo () { } function addPlatformInformation (info) { - return getPlatformInfo() - .then((platform) => { + return getPlatformInfo().then((platform) => { return merge(info, { platform }) }) } @@ -245,18 +255,18 @@ function addPlatformInformation (info) { * and if possible a way to solve it. Resolves with a string. */ function formErrorText (info, msg, prevMessage) { - return addPlatformInformation(info) - .then((obj) => { + return addPlatformInformation(info).then((obj) => { const formatted = [] function add (msg) { - formatted.push( - stripIndents(msg) - ) + formatted.push(stripIndents(msg)) } - la(is.unemptyString(obj.description), - 'expected error description to be text', obj.description) + la( + is.unemptyString(obj.description), + 'expected error description to be text', + obj.description + ) // assuming that if there the solution is a function it will handle // error message and (optional previous error message) @@ -272,8 +282,11 @@ function formErrorText (info, msg, prevMessage) { `) } else { - la(is.unemptyString(obj.solution), - 'expected error solution to be text', obj.solution) + la( + is.unemptyString(obj.solution), + 'expected error solution to be text', + obj.solution + ) add(` ${obj.description} @@ -326,8 +339,7 @@ const raise = (info) => { const throwFormErrorText = (info) => { return (msg, prevMessage) => { - return formErrorText(info, msg, prevMessage) - .then(raise(info)) + return formErrorText(info, msg, prevMessage).then(raise(info)) } } @@ -337,12 +349,14 @@ const throwFormErrorText = (info) => { * @param {ErrorInformation} info Error information {description, solution} * @example return exitWithError(errors.invalidCypressEnv)('foo') */ -const exitWithError = (info) => (msg) => { - return formErrorText(info, msg).then((text) => { - // eslint-disable-next-line no-console - console.error(text) - process.exit(info.exitCode || 1) - }) +const exitWithError = (info) => { + return (msg) => { + return formErrorText(info, msg).then((text) => { + // eslint-disable-next-line no-console + console.error(text) + process.exit(info.exitCode || 1) + }) + } } module.exports = { diff --git a/cli/package.json b/cli/package.json index 7661793138a1..37ff7f30be79 100644 --- a/cli/package.json +++ b/cli/package.json @@ -75,7 +75,6 @@ "chai": "3.5.0", "chai-as-promised": "7.1.1", "chai-string": "1.4.0", - "clear-module": "^2.1.0", "dependency-check": "3.4.1", "dtslint": "0.9.0", "execa-wrap": "1.4.0", From 65414858962fe4ecd62e505af265c35dbd596497 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 15:42:23 -0400 Subject: [PATCH 09/13] pass CLI linter --- cli/lib/cli.js | 103 ++++++++++++++++++++++++++++++--------- cli/lib/util.js | 1 + cli/test/lib/cli_spec.js | 18 ++++--- 3 files changed, 93 insertions(+), 29 deletions(-) diff --git a/cli/lib/cli.js b/cli/lib/cli.js index 6833c824a908..0e7ed5ca124c 100644 --- a/cli/lib/cli.js +++ b/cli/lib/cli.js @@ -28,7 +28,9 @@ const coerceFalse = (arg) => { const spaceDelimitedSpecsMsg = (files) => { logger.log() logger.warn(stripIndent` - ${logSymbols.warning} Warning: It looks like you're passing --spec a space-separated list of files: + ${ + logSymbols.warning +} Warning: It looks like you're passing --spec a space-separated list of files: "${files.join(' ')}" @@ -55,7 +57,8 @@ const parseVariableOpts = (fnArgs, args) => { const nextOptOffset = _.findIndex(_.slice(args, argIndex), (arg) => { return _.startsWith(arg, '--') }) - const endIndex = nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length + const endIndex = + nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length const maybeSpecs = _.slice(args, argIndex, endIndex) const extraSpecs = _.intersection(maybeSpecs, fnArgs) @@ -71,11 +74,34 @@ const parseVariableOpts = (fnArgs, args) => { } const parseOpts = (opts) => { - opts = _.pick(opts, - 'project', 'spec', 'reporter', 'reporterOptions', 'path', 'destination', - 'port', 'env', 'cypressVersion', 'config', 'record', 'key', - 'browser', 'detached', 'headed', 'global', 'dev', 'force', 'exit', - 'cachePath', 'cacheList', 'cacheClear', 'parallel', 'group', 'ciBuildId') + opts = _.pick( + opts, + 'project', + 'spec', + 'reporter', + 'reporterOptions', + 'path', + 'destination', + 'port', + 'env', + 'cypressVersion', + 'config', + 'record', + 'key', + 'browser', + 'detached', + 'headed', + 'global', + 'dev', + 'force', + 'exit', + 'cachePath', + 'cacheList', + 'cacheClear', + 'parallel', + 'group', + 'ciBuildId' + ) if (opts.exit) { opts = _.omit(opts, 'exit') @@ -87,16 +113,23 @@ const parseOpts = (opts) => { } const descriptions = { - record: 'records the run. sends test results, screenshots and videos to your Cypress Dashboard.', - key: 'your secret Record Key. you can omit this if you set a CYPRESS_RECORD_KEY environment variable.', + record: + 'records the run. sends test results, screenshots and videos to your Cypress Dashboard.', + key: + 'your secret Record Key. you can omit this if you set a CYPRESS_RECORD_KEY environment variable.', spec: 'runs a specific spec file. defaults to "all"', - reporter: 'runs a specific mocha reporter. pass a path to use a custom reporter. defaults to "spec"', + reporter: + 'runs a specific mocha reporter. pass a path to use a custom reporter. defaults to "spec"', reporterOptions: 'options for the mocha reporter. defaults to "null"', port: 'runs Cypress on a specific port. overrides any value in cypress.json.', - env: 'sets environment variables. separate multiple values with a comma. overrides any value in cypress.json or cypress.env.json', - config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.json.', - browserRunMode: 'runs Cypress in the browser with the given name. if a filesystem path is supplied, Cypress will attempt to use the browser at that path.', - browserOpenMode: 'path to a custom browser to be added to the list of available browsers in Cypress', + env: + 'sets environment variables. separate multiple values with a comma. overrides any value in cypress.json or cypress.env.json', + config: + 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.json.', + browserRunMode: + 'runs Cypress in the browser with the given name. if a filesystem path is supplied, Cypress will attempt to use the browser at that path.', + browserOpenMode: + 'path to a custom browser to be added to the list of available browsers in Cypress', detached: 'runs Cypress application in detached mode', project: 'path to the project', global: 'force Cypress into global mode as if its globally installed', @@ -109,11 +142,25 @@ const descriptions = { cacheList: 'list cached binary versions', cacheClear: 'delete all cached binaries', group: 'a named group for recorded runs in the Cypress dashboard', - parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes', - ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers', + parallel: + 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes', + ciBuildId: + 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers', } -const knownCommands = ['version', 'run', 'open', 'install', 'verify', '-v', '--version', 'help', '-h', '--help', 'cache'] +const knownCommands = [ + 'version', + 'run', + 'open', + 'install', + 'verify', + '-v', + '--version', + 'help', + '-h', + '--help', + 'cache', +] const text = (description) => { if (!descriptions[description]) { @@ -124,9 +171,11 @@ const text = (description) => { } function includesVersion (args) { - return _.includes(args, 'version') || + return ( + _.includes(args, 'version') || _.includes(args, '--version') || _.includes(args, '-v') + ) } function showVersions () { @@ -150,7 +199,10 @@ module.exports = { if (!util.isValidCypressEnvValue(process.env.CYPRESS_ENV)) { debug('invalid CYPRESS_ENV value', process.env.CYPRESS_ENV) - return errors.exitWithError(errors.errors.invalidCypressEnv)(process.env.CYPRESS_ENV) + + return errors.exitWithError(errors.errors.invalidCypressEnv)( + process.env.CYPRESS_ENV + ) } const program = new commander.Command() @@ -183,7 +235,10 @@ module.exports = { .option('-k, --key ', text('key')) .option('-s, --spec ', text('spec')) .option('-r, --reporter ', text('reporter')) - .option('-o, --reporter-options ', text('reporterOptions')) + .option( + '-o, --reporter-options ', + text('reporterOptions') + ) .option('-p, --port ', text('port')) .option('-e, --env ', text('env')) .option('-c, --config ', text('config')) @@ -224,7 +279,9 @@ module.exports = { program .command('install') .usage('[options]') - .description('Installs the Cypress executable matching this package\'s version') + .description( + 'Installs the Cypress executable matching this package\'s version' + ) .option('-f, --force', text('forceInstall')) .action((opts) => { require('./tasks/install') @@ -235,7 +292,9 @@ module.exports = { program .command('verify') .usage('[options]') - .description('Verifies that Cypress is installed correctly and executable') + .description( + 'Verifies that Cypress is installed correctly and executable' + ) .option('--dev', text('dev'), coerceFalse) .action((opts) => { const defaultOpts = { force: true, welcomeMessage: false } diff --git a/cli/lib/util.js b/cli/lib/util.js index 923fa0c192b0..029c0bb1893c 100644 --- a/cli/lib/util.js +++ b/cli/lib/util.js @@ -134,6 +134,7 @@ function isValidCypressEnvValue (value) { // names of config environments, see "packages/server/config/app.yml" const names = ['development', 'test', 'staging', 'production'] + return _.includes(names, value) } diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index 2430841d8689..0d66605edf63 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -11,7 +11,6 @@ const verify = require(`${lib}/tasks/verify`) const install = require(`${lib}/tasks/install`) const snapshot = require('../support/snapshot') const execa = require('execa-wrap') -const os = require('os') describe('cli', () => { require('mocha-banner').register() @@ -79,21 +78,24 @@ describe('cli', () => { * Replaces line "Platform: ..." with "Platform: xxx" * @param {string} s */ - const replacePlatform = (s) => - s.replace(/Platform: .+/, 'Platform: xxx') + const replacePlatform = (s) => { + return s.replace(/Platform: .+/, 'Platform: xxx') + } /** * Replaces line "Cypress Version: ..." with "Cypress Version: 1.2.3" * @param {string} s */ - const replaceCypressVersion = (s) => - s.replace(/Cypress Version: .+/, 'Cypress Version: 1.2.3') + const replaceCypressVersion = (s) => { + return s.replace(/Cypress Version: .+/, 'Cypress Version: 1.2.3') + } - const sanitizePlatform = (text) => - text.split(os.eol) + const sanitizePlatform = (text) => { + return text.split(os.eol) .map(replacePlatform) .map(replaceCypressVersion) .join(os.eol) + } it('allows staging environment', () => { const options = { @@ -103,6 +105,7 @@ describe('cli', () => { // we are only interested in the exit code filter: ['code', 'stderr'], } + return execa('bin/cypress', ['help'], options).then(snapshot) }) @@ -114,6 +117,7 @@ describe('cli', () => { // we are only interested in the exit code filter: ['code', 'stderr'], } + return execa('bin/cypress', ['help'], options) .then(sanitizePlatform) .then(snapshot) From 0913a3fb24f835c67fffdcd4c56951b3b7c4b5f9 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 15:43:32 -0400 Subject: [PATCH 10/13] fix log reference, should be debug --- packages/server/lib/config.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/lib/config.coffee b/packages/server/lib/config.coffee index c55e8d3e7a49..96f9a36bd1a8 100644 --- a/packages/server/lib/config.coffee +++ b/packages/server/lib/config.coffee @@ -10,7 +10,7 @@ origin = require("./util/origin") coerce = require("./util/coerce") settings = require("./util/settings") v = require("./util/validation") -debug = require("debug")("cypress:server:config") +debug = require("debug")("cypress:server:config") pathHelpers = require("./util/path_helpers") CYPRESS_ENV_PREFIX = "CYPRESS_" @@ -272,7 +272,7 @@ module.exports = { config.env = @parseEnv(config, options.env, resolved) config.cypressEnv = process.env["CYPRESS_ENV"] - log("using CYPRESS_ENV %s", config.cypressEnv) + debug("using CYPRESS_ENV %s", config.cypressEnv) if not @isValidCypressEnvValue(config.cypressEnv) errors.throw("INVALID_CYPRESS_ENV", config.cypressEnv) From 8b33e53a300c920f3e5018fa173e75209759e416 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 15:52:00 -0400 Subject: [PATCH 11/13] use correct sinon reference --- packages/server/test/unit/config_spec.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/test/unit/config_spec.coffee b/packages/server/test/unit/config_spec.coffee index 2fc9cca61389..57e4f20e47a6 100644 --- a/packages/server/test/unit/config_spec.coffee +++ b/packages/server/test/unit/config_spec.coffee @@ -20,7 +20,7 @@ describe "lib/config", -> context "environment name check", -> it "throws an error for unknown CYPRESS_ENV", -> - @sandbox.stub(errors, "throw").withArgs("INVALID_CYPRESS_ENV", "foo-bar") + sinon.stub(errors, "throw").withArgs("INVALID_CYPRESS_ENV", "foo-bar") process.env.CYPRESS_ENV = "foo-bar" cfg = { projectRoot: "/foo/bar/" @@ -30,7 +30,7 @@ describe "lib/config", -> expect(errors.throw).have.been.calledOnce it "allows known CYPRESS_ENV", -> - @sandbox.stub(errors, "throw") + sinon.stub(errors, "throw") process.env.CYPRESS_ENV = "test" cfg = { projectRoot: "/foo/bar/" From 8a5030af384fb3defc9c3a2444f5b34e4620ea97 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Thu, 29 Aug 2019 17:14:13 -0400 Subject: [PATCH 12/13] update message, show first part in red --- cli/__snapshots__/cli_spec.js | 4 +++- cli/__snapshots__/errors_spec.js | 2 +- cli/lib/cli.js | 2 +- cli/lib/errors.js | 14 ++------------ cli/test/lib/cli_spec.js | 3 ++- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index aab998fd47b8..d8ad47a54de0 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -371,9 +371,11 @@ exports['cli CYPRESS_ENV catches environment "foo" 1'] = ` Environment variable with reserved name "CYPRESS_ENV" was used. Remove "CYPRESS_ENV" variable and run Cypress again. + ---------- - foo + CYPRESS_ENV=foo + ---------- Platform: xxx diff --git a/cli/__snapshots__/errors_spec.js b/cli/__snapshots__/errors_spec.js index 348b29ee5d93..44b1a631d786 100644 --- a/cli/__snapshots__/errors_spec.js +++ b/cli/__snapshots__/errors_spec.js @@ -32,6 +32,7 @@ exports['errors individual has the following errors 1'] = [ "failedDownload", "failedUnzip", "invalidCacheDirectory", + "invalidCypressEnv", "invalidSmokeTestDisplayError", "missingApp", "missingDependency", @@ -41,7 +42,6 @@ exports['errors individual has the following errors 1'] = [ "removed", "smokeTestFailure", "unexpected", - "invalidCypressEnv", "versionMismatch" ] diff --git a/cli/lib/cli.js b/cli/lib/cli.js index 0e7ed5ca124c..fb94e25eebc6 100644 --- a/cli/lib/cli.js +++ b/cli/lib/cli.js @@ -201,7 +201,7 @@ module.exports = { debug('invalid CYPRESS_ENV value', process.env.CYPRESS_ENV) return errors.exitWithError(errors.errors.invalidCypressEnv)( - process.env.CYPRESS_ENV + `CYPRESS_ENV=${process.env.CYPRESS_ENV}` ) } diff --git a/cli/lib/errors.js b/cli/lib/errors.js index e56044e4e053..e4d964b6a062 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -186,21 +186,11 @@ const unexpected = { const invalidCypressEnv = { description: - 'Environment variable with reserved name "CYPRESS_ENV" was used.', - solution: 'Remove "CYPRESS_ENV" variable and run Cypress again.', + chalk.red('Environment variable with reserved name "CYPRESS_ENV" was used.'), + solution: chalk.red('Remove "CYPRESS_ENV" variable and run Cypress again.'), exitCode: 11, } -// const getOsVersion = () => { -// if (os.platform() === 'linux') { -// return getos() -// .then(osInfo => [osInfo.dist, osInfo.release].join(' - ')) -// .catch(() => os.release()) -// } -// return Promise.resolve(os.release()) - -// } - const removed = { CYPRESS_BINARY_VERSION: { description: stripIndent` diff --git a/cli/test/lib/cli_spec.js b/cli/test/lib/cli_spec.js index 0d66605edf63..42ed40e53a41 100644 --- a/cli/test/lib/cli_spec.js +++ b/cli/test/lib/cli_spec.js @@ -91,7 +91,8 @@ describe('cli', () => { } const sanitizePlatform = (text) => { - return text.split(os.eol) + return text + .split(os.eol) .map(replacePlatform) .map(replaceCypressVersion) .join(os.eol) From d5d3bef2b31a995a7eea0dba8be44db6ae07d041 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Fri, 30 Aug 2019 08:04:06 -0400 Subject: [PATCH 13/13] update error message text --- cli/__snapshots__/cli_spec.js | 4 ++-- cli/lib/errors.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/__snapshots__/cli_spec.js b/cli/__snapshots__/cli_spec.js index d8ad47a54de0..5465cc92f7d9 100644 --- a/cli/__snapshots__/cli_spec.js +++ b/cli/__snapshots__/cli_spec.js @@ -368,9 +368,9 @@ exports['cli CYPRESS_ENV catches environment "foo" 1'] = ` code: 11 stderr: ------- - Environment variable with reserved name "CYPRESS_ENV" was used. + The environment variable with the reserved name "CYPRESS_ENV" is set. - Remove "CYPRESS_ENV" variable and run Cypress again. + Unset the "CYPRESS_ENV" environment variable and run Cypress again. ---------- diff --git a/cli/lib/errors.js b/cli/lib/errors.js index e4d964b6a062..ee45a1c21c4a 100644 --- a/cli/lib/errors.js +++ b/cli/lib/errors.js @@ -186,8 +186,8 @@ const unexpected = { const invalidCypressEnv = { description: - chalk.red('Environment variable with reserved name "CYPRESS_ENV" was used.'), - solution: chalk.red('Remove "CYPRESS_ENV" variable and run Cypress again.'), + chalk.red('The environment variable with the reserved name "CYPRESS_ENV" is set.'), + solution: chalk.red('Unset the "CYPRESS_ENV" environment variable and run Cypress again.'), exitCode: 11, }