Skip to content

Commit

Permalink
Support --tag argument (cypress-io#5164)
Browse files Browse the repository at this point in the history
* Alphabetize cli options for my own sanity

* begin added tag flag

* Fix some minor grammar in cli help output + be more specific for specs description

* update snapshot based on alphabetization change

* update snapshot to include --tag in help output

* update logic for pulling out space delimited args to look through --tag and --spec flags dynamically

* Support and pass along tag flag to run and record

- show err if passed without record flag
- sanitize args into comma separated string
- display tag in record errors

* fix some tests/snapshots where 'tag' was missing

* Actually try passing in tag through tests to ensure it prints.

* Merge branch 'develop' into issue-2561-tags

# Conflicts:
#	cli/__snapshots__/cli_spec.js
#	cli/lib/cli.js
#	cli/lib/exec/run.js
#	packages/server/lib/modes/run.js
#	packages/server/lib/util/args.js

* Send 'tags' as an array to backend API

* Update json-schemas to query against 2.2.0 of postRun

- this will require a bump to json-schemas repo

* update test to reflect tags array

* update snapshot to display nightly tag

* rearrange args to alphabetical order in specs

* Add tags to runResponses / remove tag from incorrect instance post

* Fix failing specs / snapshots

* Update error messages + snapshots

* Fix snapshot that no longer displays tag arg

* fix args unit test

* remove extra slash

* add a few more cli tests

* another test just in case

* a quick unit test for displayFlags utility


Co-authored-by: Gleb Bahmutov <[email protected]>
  • Loading branch information
2 people authored and termcaps committed Dec 10, 2019
1 parent c439c60 commit 44134a2
Show file tree
Hide file tree
Showing 23 changed files with 614 additions and 426 deletions.
356 changes: 184 additions & 172 deletions cli/__snapshots__/cli_spec.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions cli/__snapshots__/run_spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
exports['exec run .processRunOptions does not remove --record option when using --browser 1'] = [
"--run-project",
null,
"--record",
"foo",
"--browser",
"test browser"
"test browser",
"--record",
"foo"
]

exports['exec run .processRunOptions passes --browser option 1'] = [
Expand Down
168 changes: 87 additions & 81 deletions cli/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,99 +25,107 @@ const coerceFalse = (arg) => {
return arg !== 'false'
}

const spaceDelimitedSpecsMsg = (files) => {
logger.log()
logger.warn(stripIndent`
${
logSymbols.warning
} Warning: It looks like you're passing --spec a space-separated list of files:
const spaceDelimitedArgsMsg = (flag, args) => {
let msg = `
${logSymbols.warning} Warning: It looks like you're passing --${flag} a space-separated list of arguments:
"${files.join(' ')}"
"${args.join(' ')}"
This will work, but it's not recommended.
If you are trying to pass multiple arguments, separate them with commas instead:
cypress run --${flag} arg1,arg2,arg3
`

if (flag === 'spec') {
msg += `
The most common cause of this warning is using an unescaped glob pattern. If you are
trying to pass a glob pattern, escape it using quotes:
cypress run --spec "**/*.spec.js"
`
}

If you are trying to pass multiple spec filenames, separate them by commas instead:
cypress run --spec spec1,spec2,spec3
`)

logger.log()
logger.warn(stripIndent(msg))
logger.log()
}

const parseVariableOpts = (fnArgs, args) => {
const opts = fnArgs.pop()

if (fnArgs.length && opts.spec) {
// this will capture space-delimited specs after --spec spec1 but before the next option

const argIndex = _.indexOf(args, '--spec') + 2
const nextOptOffset = _.findIndex(_.slice(args, argIndex), (arg) => {
return _.startsWith(arg, '--')
if (fnArgs.length && (opts.spec || opts.tag)) {
// this will capture space-delimited args after
// flags that could have possible multiple args
// but before the next option
// --spec spec1 spec2 or --tag foo bar

const multiArgFlags = _.compact([
opts.spec ? 'spec' : opts.spec,
opts.tag ? 'tag' : opts.tag,
])

_.forEach(multiArgFlags, (flag) => {
const argIndex = _.indexOf(args, `--${flag}`) + 2
const nextOptOffset = _.findIndex(_.slice(args, argIndex), (arg) => {
return _.startsWith(arg, '--')
})
const endIndex = nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length

const maybeArgs = _.slice(args, argIndex, endIndex)
const extraArgs = _.intersection(maybeArgs, fnArgs)

if (extraArgs.length) {
opts[flag] = [opts[flag]].concat(extraArgs)
spaceDelimitedArgsMsg(flag, opts[flag])
opts[flag] = opts[flag].join(',')
}
})
const endIndex =
nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length

const maybeSpecs = _.slice(args, argIndex, endIndex)
const extraSpecs = _.intersection(maybeSpecs, fnArgs)

if (extraSpecs.length) {
opts.spec = [opts.spec].concat(extraSpecs)
spaceDelimitedSpecsMsg(opts.spec)
opts.spec = opts.spec.join(',')
}
}

return util.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.',
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"',
reporterOptions: 'options for the mocha reporter. defaults to "null"',
port: 'runs Cypress on a specific port. overrides any value in the configuration file.',
env: 'sets environment variables. separate multiple values with a comma. overrides any value in the configuration file or cypress.env.json',
config: 'sets configuration values. separate multiple values with a comma. overrides any value in the configuration file.',
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',
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.',
cacheClear: 'delete all cached binaries',
cacheList: 'list cached binary versions',
cachePath: 'print the path to the binary cache',
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',
config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.json.',
configFile: 'path to JSON file where configuration values are set. defaults to "cypress.json". pass "false" to disable.',
version: 'prints Cypress version',
headed: 'displays the Electron browser instead of running headlessly',
detached: 'runs Cypress application in detached mode',
dev: 'runs cypress in development and bypasses binary check',
forceInstall: 'force install the Cypress binary',
env: 'sets environment variables. separate multiple values with a comma. overrides any value in cypress.json or cypress.env.json',
exit: 'keep the browser open after tests finish',
cachePath: 'print the path to the binary cache',
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',
forceInstall: 'force install the Cypress binary',
global: 'force Cypress into global mode as if its globally installed',
group: 'a named group for recorded runs in the Cypress Dashboard',
headed: 'displays the Electron browser instead of running headlessly',
key: 'your secret Record Key. you can omit this if you set a CYPRESS_RECORD_KEY environment variable.',
parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
port: 'runs Cypress on a specific port. overrides any value in cypress.json.',
project: 'path to the project',
record: 'records the run. sends test results, screenshots and videos to your Cypress Dashboard.',
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"',
spec: 'runs specific spec file(s). defaults to "all"',
tag: 'named tag(s) for recorded runs in the Cypress Dashboard',
version: 'prints Cypress version',
}

const knownCommands = [
'version',
'run',
'open',
'cache',
'help',
'-h',
'--help',
'install',
'open',
'run',
'verify',
'-v',
'--version',
'help',
'-h',
'--help',
'cache',
'version',
]

const text = (description) => {
Expand Down Expand Up @@ -165,7 +173,7 @@ module.exports = {

const program = new commander.Command()

// bug in commaner not printing name
// bug in commander not printing name
// in usage help docs
program._name = 'cypress'

Expand All @@ -188,25 +196,23 @@ module.exports = {
.command('run')
.usage('[options]')
.description('Runs Cypress tests from the CLI without the GUI')
.option('--record [bool]', text('record'), coerceFalse)
.option('--headed', text('headed'))
.option('-k, --key <record-key>', text('key'))
.option('-s, --spec <spec>', text('spec'))
.option('-r, --reporter <reporter>', text('reporter'))
.option(
'-o, --reporter-options <reporter-options>',
text('reporterOptions')
)
.option('-p, --port <port>', text('port'))
.option('-e, --env <env>', text('env'))
.option('-b, --browser <browser-name-or-path>', text('browserRunMode'))
.option('--ci-build-id <id>', text('ciBuildId'))
.option('-c, --config <config>', text('config'))
.option('-C, --config-file <config-file>', text('configFile'))
.option('-b, --browser <browser-name-or-path>', text('browserRunMode'))
.option('-P, --project <project-path>', text('project'))
.option('--parallel', text('parallel'))
.option('-e, --env <env>', text('env'))
.option('--group <name>', text('group'))
.option('--ci-build-id <id>', text('ciBuildId'))
.option('-k, --key <record-key>', text('key'))
.option('--headed', text('headed'))
.option('--no-exit', text('exit'))
.option('--parallel', text('parallel'))
.option('-p, --port <port>', text('port'))
.option('-P, --project <project-path>', text('project'))
.option('--record [bool]', text('record'), coerceFalse)
.option('-r, --reporter <reporter>', text('reporter'))
.option('-o, --reporter-options <reporter-options>', text('reporterOptions'))
.option('-s, --spec <spec>', text('spec'))
.option('-t, --tag <tag>', text('tag'))
.option('--dev', text('dev'), coerceFalse)
.action((...fnArgs) => {
debug('running Cypress')
Expand All @@ -220,14 +226,14 @@ module.exports = {
.command('open')
.usage('[options]')
.description('Opens Cypress in the interactive GUI.')
.option('-p, --port <port>', text('port'))
.option('-e, --env <env>', text('env'))
.option('-b, --browser <browser-path>', text('browserOpenMode'))
.option('-c, --config <config>', text('config'))
.option('-C, --config-file <config-file>', text('configFile'))
.option('-d, --detached [bool]', text('detached'), coerceFalse)
.option('-b, --browser <browser-path>', text('browserOpenMode'))
.option('-P, --project <project-path>', text('project'))
.option('-e, --env <env>', text('env'))
.option('--global', text('global'))
.option('-p, --port <port>', text('port'))
.option('-P, --project <project-path>', text('project'))
.option('--dev', text('dev'), coerceFalse)
.action((opts) => {
debug('opening Cypress')
Expand Down
8 changes: 4 additions & 4 deletions cli/lib/exec/open.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ module.exports = {

const args = []

if (options.env) {
args.push('--env', options.env)
}

if (options.config) {
args.push('--config', options.config)
}
Expand All @@ -27,6 +23,10 @@ module.exports = {
args.push('--browser', options.browser)
}

if (options.env) {
args.push('--env', options.env)
}

if (options.port) {
args.push('--port', options.port)
}
Expand Down
Loading

0 comments on commit 44134a2

Please sign in to comment.