fix: CLI filtering --spec when commas in glob pattern (#19557)

* Added is-glob as dependency for packages/server

* Parsed spec argv for glob patterns.

* Removed setGlob parameter.

* Updated glob implementation to revert side effects

* Removed is-glob dependency.

* Wrote parseSpecArgv method

* Added back resolvePath.

* Added unit tests.

* Added jsdoc & comments.

* pushing trivial update to kick off build

Co-authored-by: Matt Henkes <mjhenkes@gmail.com>
This commit is contained in:
Rob
2022-01-18 12:10:07 -05:00
committed by GitHub
parent 2685f82663
commit 273b7035b0
3 changed files with 130 additions and 5 deletions
+114 -2
View File
@@ -204,6 +204,118 @@ const sanitizeAndConvertNestedArgs = (str, argname) => {
}
}
/**
* Parses the '--spec' cli parameter to return an array of valid patterns.
*
* @param {Strng} pattern pattern to parse
* @returns Array of patterns
*/
const parseSpecArgv = (pattern) => {
const TOKENS = {
OPEN: ['{', '['],
CLOSE: ['}', ']'],
}
const hasToken = [...TOKENS.OPEN, ...TOKENS.CLOSE].some((t) => {
return pattern.includes(t)
})
const hasComma = pattern.includes(',')
/**
* Slice and mutate a string.
*
* @param {String} str String to slice & mutate
* @param {Number} end Index to slice to
* @returns [String, String, Number]
*/
const sliceAndMutate = (str, end) => {
return [
str.slice(0, end),
str.substring(end, str.length),
str.slice(0, end).length,
]
}
/**
* Sanitizes a path's leftover commas.
*
* @param {String} path
* @returns String
*/
const sanitizeFinalPath = (path) => {
return path.split('')[0] === ',' ? path.substring(1, path.length) : path
}
if (!hasToken) {
return [].concat(pattern.split(','))
}
if (!hasComma) {
return pattern
}
// Get comma rules.
let opens = []
let closes = []
const rules = pattern
.split('')
.map((token, index) => {
if (TOKENS.OPEN.includes(token)) {
opens.push(index)
}
if (TOKENS.CLOSE.includes(token)) {
closes.push(index)
}
if (token === ',') {
const isBreakable =
index > opens[opens.length - 1] &&
index > closes[closes.length - 1] &&
opens.length === closes.length
if (isBreakable) {
return {
comma: index,
isBreakable: true,
}
}
return {
comma: index,
isBreakable: false,
}
}
return null
})
.filter(Boolean)
// Perform comma breaking logic.
let carry = pattern
let offset = 0
const partial = rules
.map((rule) => {
if (!rule.isBreakable) {
return null
}
const [res, mutated, offsettedBy] = sliceAndMutate(
carry,
rule.comma - offset,
)
offset = offsettedBy
carry = mutated
return res
})
.filter(Boolean)
.map(sanitizeFinalPath)
// In the end, carry will be left with the last path that hasn't been cut.
return [...partial, sanitizeFinalPath(carry)]
}
module.exports = {
normalizeBackslashes,
@@ -303,12 +415,12 @@ module.exports = {
spec = spec.substring(1, spec.length - 1)
}
options.spec = strToArray(spec).map(resolvePath)
options.spec = parseSpecArgv(spec).map(resolvePath)
} else {
options.spec = spec.map(resolvePath)
}
} catch (err) {
debug('could not pass config spec value %s', spec)
debug('could not parse config spec value %s', spec)
debug('error %o', err)
return errors.throw('COULD_NOT_PARSE_ARGUMENTS', 'spec', spec, 'spec must be a string or comma-separated list')
@@ -164,6 +164,19 @@ describe('lib/util/args', () => {
return snapshot('invalid spec error', stripAnsi(err.message))
}
})
it('should be correctly parsing globs with lists & ranges', function () {
const options = this.setup('--spec', 'cypress/integration/{[!a]*.spec.js,sub1,{sub2,sub3/sub4}}/*.js')
expect(options.spec[0]).to.eq(`${cwd}/cypress/integration/{[!a]*.spec.js,sub1,{sub2,sub3/sub4}}/*.js`)
})
it('should be correctly parsing globs with a mix of lists, ranges & regular paths', function () {
const options = this.setup('--spec', 'cypress/integration/{[!a]*.spec.js,sub1,{sub2,sub3/sub4}}/*.js,cypress/integration/foo.spec.js')
expect(options.spec[0]).to.eq(`${cwd}/cypress/integration/{[!a]*.spec.js,sub1,{sub2,sub3/sub4}}/*.js`)
expect(options.spec[1]).to.eq(`${cwd}/cypress/integration/foo.spec.js`)
})
})
context('--tag', () => {
+3 -3
View File
@@ -23008,9 +23008,9 @@ is-glob@^3.0.0, is-glob@^3.1.0:
is-extglob "^2.1.0"
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"