fix: Parse JSON string arg properly. (#9584)

This commit is contained in:
Kukhyeon Heo
2021-01-15 01:08:33 +09:00
committed by GitHub
parent d54b2d089d
commit e3973c240d
3 changed files with 69 additions and 20 deletions

View File

@@ -125,8 +125,12 @@ 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
if (typeof str === 'object') {
return str
}
// if this is valid JSON then just
// parse it and call it a day
const parsed = tryJSONParse(str)
if (parsed) {
@@ -239,17 +243,23 @@ module.exports = {
return path.resolve(options.cwd, p)
}
// clean up single quotes wrapping the spec for Windows users
// https://github.com/cypress-io/cypress/issues/2298
if (spec[0] === '\'' && spec[spec.length - 1] === '\'') {
spec = spec.substring(1, spec.length - 1)
}
// https://github.com/cypress-io/cypress/issues/8818
// Sometimes spec is parsed to array. Because of that, we need check.
if (typeof spec === 'string') {
// clean up single quotes wrapping the spec for Windows users
// https://github.com/cypress-io/cypress/issues/2298
if (spec[0] === '\'' && spec[spec.length - 1] === '\'') {
spec = spec.substring(1, spec.length - 1)
}
options.spec = strToArray(spec).map(resolvePath)
options.spec = strToArray(spec).map(resolvePath)
} else {
options.spec = spec.map(resolvePath)
}
}
if (tag) {
options.tag = strToArray(tag)
options.tag = typeof tag === 'string' ? strToArray(tag) : tag
}
if (env) {

View File

@@ -1,12 +1,6 @@
const _ = require('lodash')
const toBoolean = require('underscore.string/toBoolean')
const isValue = (value) => {
return (comparison) => {
return _.invoke(comparison, 'toString') === value
}
}
// https://github.com/cypress-io/cypress/issues/6810
const toArray = (value) => {
const valueIsNotStringOrArray = typeof (value) !== 'string' || (value[0] !== '[' && value[value.length - 1] !== ']')
@@ -30,14 +24,42 @@ const toArray = (value) => {
return arr
}
// https://github.com/cypress-io/cypress/issues/8818
// toArray() above doesn't handle JSON string properly.
// For example, '[{a:b,c:d},{e:f,g:h}]' isn't the parsed object but ['{a:b', 'c:d}', '{e:f', 'g:h}']. It's useless.
// Because of that, we check if the value is a JSON string.
const fromJson = (value) => {
try {
return JSON.parse(value)
} catch (e) {
// do nothing
}
}
module.exports = (value) => {
const num = _.toNumber(value)
if (_.invoke(num, 'toString') === value) {
return num
}
const bool = toBoolean(value)
if (_.invoke(bool, 'toString') === value) {
return bool
}
const obj = fromJson(value)
if (obj && typeof obj === 'object') {
return obj
}
const arr = toArray(value)
return _
.chain([num, bool, arr])
.find(isValue(value))
.defaultTo(value)
.value()
if (_.invoke(arr, 'toString') === value) {
return arr
}
return value
}

View File

@@ -48,6 +48,23 @@ describe('lib/util/coerce', () => {
expect(coerce(cypressEnvVar)).to.deep.include({ BOOLEAN: false })
})
// https://github.com/cypress-io/cypress/issues/8818
it('coerces JSON string', () => {
expect(coerce('[{"type": "foo", "value": "bar"}, {"type": "fizz", "value": "buzz"}]')).to.deep.equal(
[{ 'type': 'foo', 'value': 'bar' }, { 'type': 'fizz', 'value': 'buzz' }],
)
})
// https://github.com/cypress-io/cypress/issues/8818
it('coerces JSON string from process.env', () => {
process.env['CYPRESS_stringified_json'] = '[{"type": "foo", "value": "bar"}, {"type": "fizz", "value": "buzz"}]'
const cypressEnvVar = getProcessEnvVars(process.env)
const coercedCypressEnvVar = coerce(cypressEnvVar)
expect(coercedCypressEnvVar).to.have.keys('stringified_json')
expect(coercedCypressEnvVar['stringified_json']).to.deep.equal([{ 'type': 'foo', 'value': 'bar' }, { 'type': 'fizz', 'value': 'buzz' }])
})
it('coerces array', () => {
expect(coerce('[foo,bar]')).to.have.members(['foo', 'bar'])
})