Merge branch 'develop' into v4.0-release

This commit is contained in:
Gleb Bahmutov
2020-02-03 17:25:31 -05:00
committed by GitHub
9 changed files with 228 additions and 46 deletions
+25
View File
@@ -55,9 +55,30 @@ executors:
PLATFORM: mac
commands:
install-latest-chrome:
description: Install latest Google Chrome (stable)
parameters:
browser:
default: "electron"
description: browser shortname to target
type: string
steps:
- run:
name: Install latest Google Chrome (stable)
command: |
if [ << parameters.browser >> == "chrome" ]; then
echo "**** Running Chrome tests. Installing latest stable version of Google Chrome. ****"
apt-get update
apt-get install google-chrome-stable -y
echo "**** Location of Google Chrome Installation: "`which google-chrome`" ****"
echo "**** Google Chrome Version: "`google-chrome --version`" ****"
else
echo "**** Not updating Chrome. Running tests in '<< parameters.browser >>' ****"
fi
run-e2e-tests:
parameters:
browser:
default: "electron"
description: browser shortname to target
type: string
chunk:
@@ -66,6 +87,8 @@ commands:
steps:
- attach_workspace:
at: ~/
- install-latest-chrome:
browser: << parameters.browser >>
- run:
command: npm run test-e2e -- --chunk << parameters.chunk >> --browser << parameters.browser >>
working_directory: packages/server
@@ -493,6 +516,8 @@ jobs:
steps:
- attach_workspace:
at: ~/
- install-latest-chrome:
browser: chrome
- run:
command: npm start
background: true
+14 -6
View File
@@ -47,9 +47,7 @@
font-size: 13px;
color: #444;
padding: 1px 20px 0 20px;
line-height: 35px;
line-height: 40px;
}
> a {
@@ -164,14 +162,24 @@
}
.browsers-list {
margin: 5px;
border: 1px solid #c7c7c7;
border-radius: 4px;
li {
padding: 9px 15px;
white-space: nowrap;
}
.dropdown-chosen img {
position: relative;
top: -1px;
&>a.dropdown-chosen {
border-radius: 4px;
line-height: 28px !important;
background-color: #f6f6f6;
img {
position: relative;
top: -1px;
}
}
.browser-icon {
@@ -0,0 +1,23 @@
exports['invalid env error'] = `
Cypress encountered an error while parsing the argument env
You passed: nonono
The error was: Cannot read property 'split' of undefined
`
exports['invalid reporter options error'] = `
Cypress encountered an error while parsing the argument reporterOptions
You passed: abc
The error was: Cannot read property 'split' of undefined
`
exports['invalid config error'] = `
Cypress encountered an error while parsing the argument config
You passed: xyz
The error was: Cannot read property 'split' of undefined
`
@@ -264,3 +264,27 @@ These flags can only be used when recording to the Cypress Dashboard service.
https://on.cypress.io/record-params-without-recording
`
exports['could not parse config error'] = `
Cypress encountered an error while parsing the argument config
You passed: xyz
The error was: Cannot read property 'split' of undefined
`
exports['could not parse env error'] = `
Cypress encountered an error while parsing the argument env
You passed: a123
The error was: Cannot read property 'split' of undefined
`
exports['could not parse reporter options error'] = `
Cypress encountered an error while parsing the argument reporterOptions
You passed: nonono
The error was: Cannot read property 'split' of undefined
`
+12 -1
View File
@@ -39,6 +39,8 @@ const exitErr = (err) => {
return require('./errors').logException(err)
.then(() => {
debug('calling exit 1')
return exit(1)
})
}
@@ -109,7 +111,16 @@ module.exports = {
// for https://github.com/cypress-io/cypress/issues/5466
argv = R.without('--', argv)
const options = argsUtils.toObject(argv)
let options
try {
options = argsUtils.toObject(argv)
} catch (argumentsError) {
debug('could not parse CLI arguments: %o', argv)
// note - this is promise-returned call
return exitErr(argumentsError)
}
debug('from argv %o got options %o', argv, options)
+13 -6
View File
@@ -62,7 +62,7 @@ trimMultipleNewLines = (str) ->
isCypressErr = (err) ->
Boolean(err.isCypressErr)
getMsgByType = (type, arg1 = {}, arg2) ->
getMsgByType = (type, arg1 = {}, arg2, arg3) ->
switch type
when "CANNOT_TRASH_ASSETS"
"""
@@ -525,7 +525,6 @@ getMsgByType = (type, arg1 = {}, arg2) ->
#{chalk.blue(arg2)}
"""
when "RENDERER_CRASHED"
"""
We detected that the Chromium Renderer process just crashed.
@@ -881,9 +880,17 @@ getMsgByType = (type, arg1 = {}, arg2) ->
"""
Failed to connect to Chrome, retrying in 1 second (attempt #{chalk.yellow(arg1)}/32)
"""
when "COULD_NOT_PARSE_ARGUMENTS"
"""
Cypress encountered an error while parsing the argument #{chalk.gray(arg1)}
get = (type, arg1, arg2) ->
msg = getMsgByType(type, arg1, arg2)
You passed: #{arg2}
The error was: #{arg3}
"""
get = (type, arg1, arg2, arg3) ->
msg = getMsgByType(type, arg1, arg2, arg3)
if _.isObject(msg)
details = msg.details
@@ -904,8 +911,8 @@ warning = (type, arg1, arg2) ->
return null
throwErr = (type, arg1, arg2) ->
throw get(type, arg1, arg2)
throwErr = (type, arg1, arg2, arg3) ->
throw get(type, arg1, arg2, arg3)
clone = (err, options = {}) ->
_.defaults options, {
+38 -26
View File
@@ -1,10 +1,13 @@
const _ = require('lodash')
const la = require('lazy-ass')
const is = require('check-more-types')
const path = require('path')
const debug = require('debug')('cypress:server:args')
const minimist = require('minimist')
const coerceUtil = require('./coerce')
const configUtil = require('../config')
const proxyUtil = require('./proxy')
const errors = require('../errors')
const nestedObjectsInCurlyBracesRe = /\{(.+?)\}/g
const nestedArraysInSquareBracketsRe = /\[(.+?)\]/g
@@ -107,32 +110,41 @@ const JSONOrCoerce = (str) => {
return coerceUtil(str)
}
const sanitizeAndConvertNestedArgs = (str) => {
const sanitizeAndConvertNestedArgs = (str, argname) => {
la(is.unemptyString(argname), 'missing config argname to be parsed')
try {
// if this is valid JSON then just
// parse it and call it a day
const parsed = tryJSONParse(str)
const parsed = tryJSONParse(str)
if (parsed) {
return parsed
if (parsed) {
return parsed
}
// invalid JSON, so assume mixed usage
// first find foo={a:b,b:c} and bar=[1,2,3]
// syntax and turn those into
// foo: a:b|b:c
// bar: 1|2|3
return _
.chain(str)
.replace(nestedObjectsInCurlyBracesRe, commasToPipes)
.replace(nestedArraysInSquareBracketsRe, commasToPipes)
.split(',')
.map((pair) => {
return pair.split(everythingAfterFirstEqualRe)
})
.fromPairs()
.mapValues(JSONOrCoerce)
.value()
} catch (err) {
debug('could not pass config %s value %s', argname, str)
debug('error %o', err)
return errors.throw('COULD_NOT_PARSE_ARGUMENTS', argname, str, err.message)
}
// invalid JSON, so assume mixed usage
// first find foo={a:b,b:c} and bar=[1,2,3]
// syntax and turn those into
// foo: a:b|b:c
// bar: 1|2|3
return _
.chain(str)
.replace(nestedObjectsInCurlyBracesRe, commasToPipes)
.replace(nestedArraysInSquareBracketsRe, commasToPipes)
.split(',')
.map((pair) => {
return pair.split(everythingAfterFirstEqualRe)
})
.fromPairs()
.mapValues(JSONOrCoerce)
.value()
}
module.exports = {
@@ -219,7 +231,7 @@ module.exports = {
}
if (env) {
options.env = sanitizeAndConvertNestedArgs(env)
options.env = sanitizeAndConvertNestedArgs(env, 'env')
}
const proxySource = proxyUtil.loadSystemProxySettings()
@@ -234,13 +246,13 @@ module.exports = {
}
if (reporterOptions) {
options.reporterOptions = sanitizeAndConvertNestedArgs(reporterOptions)
options.reporterOptions = sanitizeAndConvertNestedArgs(reporterOptions, 'reporterOptions')
}
if (config) {
// convert config to an object
// annd store the config
options.config = sanitizeAndConvertNestedArgs(config)
// and store the config
options.config = sanitizeAndConvertNestedArgs(config, 'config')
}
// get a list of the available config keys
@@ -143,14 +143,22 @@ describe('lib/cypress', () => {
expect(process.exit).to.be.calledWith(code)
}
this.expectExitWithErr = (type, msg) => {
expect(errors.log).to.be.calledWithMatch({ type })
expect(process.exit).to.be.calledWith(1)
if (msg) {
const err = errors.log.getCall(0).args[0]
// returns error object
this.expectExitWithErr = (type, msg1, msg2) => {
expect(errors.log, 'error was logged').to.be.calledWithMatch({ type })
expect(process.exit, 'process.exit was called').to.be.calledWith(1)
expect(err.message).to.include(msg)
const err = errors.log.getCall(0).args[0]
if (msg1) {
expect(err.message, 'error text').to.include(msg1)
}
if (msg2) {
expect(err.message, 'second error text').to.include(msg2)
}
return err
}
})
@@ -193,6 +201,35 @@ describe('lib/cypress', () => {
})
})
context('error handling', function () {
it('exits if config cannot be parsed', function () {
return cypress.start(['--config', 'xyz'])
.then(() => {
const err = this.expectExitWithErr('COULD_NOT_PARSE_ARGUMENTS')
snapshot('could not parse config error', stripAnsi(err.message))
})
})
it('exits if env cannot be parsed', function () {
return cypress.start(['--env', 'a123'])
.then(() => {
const err = this.expectExitWithErr('COULD_NOT_PARSE_ARGUMENTS')
snapshot('could not parse env error', stripAnsi(err.message))
})
})
it('exits if reporter options cannot be parsed', function () {
return cypress.start(['--reporterOptions', 'nonono'])
.then(() => {
const err = this.expectExitWithErr('COULD_NOT_PARSE_ARGUMENTS')
snapshot('could not parse reporter options error', stripAnsi(err.message))
})
})
})
context('--get-key', () => {
it('writes out key and exits on success', function () {
return Promise.all([
+36 -1
View File
@@ -3,7 +3,9 @@ require("../spec_helper")
_ = require("lodash")
path = require("path")
os = require("os")
argsUtil = require("#{root}lib/util/args")
snapshot = require("snap-shot-it")
stripAnsi = require("strip-ansi")
argsUtil = require("#{root}lib/util/args")
proxyUtil = require("#{root}lib/util/proxy")
getWindowsProxyUtil = require("#{root}lib/util/get-windows-proxy")
@@ -74,6 +76,17 @@ describe "lib/util/args", ->
bar: "qux="
})
it "throws if env string cannot be parsed", ->
expect () =>
@setup("--env", "nonono")
.to.throw
# now look at the error
try
@setup("--env", "nonono")
catch err
snapshot("invalid env error", stripAnsi(err.message))
context "--reporterOptions", ->
it "converts to object literal", ->
reporterOpts = {
@@ -112,6 +125,17 @@ describe "lib/util/args", ->
}
})
it "throws if reporter string cannot be parsed", ->
expect () =>
@setup("--reporterOptions", "abc")
.to.throw
# now look at the error
try
@setup("--reporterOptions", "abc")
catch err
snapshot("invalid reporter options error", stripAnsi(err.message))
context "--config", ->
it "converts to object literal", ->
options = @setup("--config", "pageLoadTimeout=10000,waitForAnimations=false")
@@ -172,6 +196,17 @@ describe "lib/util/args", ->
options = @setup("--port", 2222)
expect(options.config.port).to.eq(2222)
it "throws if config string cannot be parsed", ->
expect () =>
@setup("--config", "xyz")
.to.throw
# now look at the error
try
@setup("--config", "xyz")
catch err
snapshot("invalid config error", stripAnsi(err.message))
context ".toArray", ->
beforeEach ->
@obj = {config: {foo: "bar"}, project: "foo/bar"}