Skip to content

Commit

Permalink
Declare CLI options as global
Browse files Browse the repository at this point in the history
By declaring CLI options global we allow their usage in subcommands
for the custom CLI.
  • Loading branch information
theredfish committed May 26, 2022
1 parent cf055ac commit 9e7f242
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 8 deletions.
6 changes: 4 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ where
short = 'n',
long = "name",
name = "regex",
visible_alias = "scenario-name"
visible_alias = "scenario-name",
global = true
)]
pub re_filter: Option<Regex>,

Expand All @@ -118,7 +119,8 @@ where
short = 't',
long = "tags",
name = "tagexpr",
conflicts_with = "regex"
conflicts_with = "regex",
global = true
)]
pub tags_filter: Option<TagOperation>,

Expand Down
2 changes: 1 addition & 1 deletion src/parser/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use super::{Error as ParseError, Parser};
pub struct Cli {
/// Glob pattern to look for feature files with. By default, looks for
/// `*.feature`s in the path configured tests runner.
#[clap(long = "input", short = 'i', name = "glob")]
#[clap(long = "input", short = 'i', name = "glob", global = true)]
pub features: Option<Walker>,
}

Expand Down
4 changes: 2 additions & 2 deletions src/runner/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ use crate::{
pub struct Cli {
/// Number of scenarios to run concurrently. If not specified, uses the
/// value configured in tests runner, or 64 by default.
#[clap(long, short, name = "int")]
#[clap(long, short, name = "int", global = true)]
pub concurrency: Option<usize>,

/// Run tests until the first failure.
#[clap(long)]
#[clap(long, global = true)]
pub fail_fast: bool,
}

Expand Down
9 changes: 7 additions & 2 deletions src/writer/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,16 @@ pub struct Cli {
///
/// `-v` is default verbosity, `-vv` additionally outputs world on failed
/// steps, `-vvv` additionally outputs step's doc string (if present).
#[clap(short, parse(from_occurrences))]
#[clap(short, parse(from_occurrences), global = true)]
pub verbose: u8,

/// Coloring policy for a console output.
#[clap(long, name = "auto|always|never", default_value = "auto")]
#[clap(
long,
name = "auto|always|never",
default_value = "auto",
global = true
)]
pub color: Coloring,
}

Expand Down
2 changes: 1 addition & 1 deletion src/writer/junit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct Cli {
///
/// `0` is default verbosity, `1` additionally outputs world on failed
/// steps.
#[clap(long = "junit-v", name = "0|1")]
#[clap(long = "junit-v", name = "0|1", global = true)]
pub verbose: Option<u8>,
}

Expand Down
121 changes: 121 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use std::{convert::Infallible, panic::AssertUnwindSafe};

use async_trait::async_trait;
use clap::Parser;
use cucumber::{
cli::{self, Args},
given, WorldInit,
};
use futures::FutureExt as _;

#[derive(Args)]
struct CustomCli {
#[clap(subcommand)]
command: Option<SubCommand>,
}

#[derive(clap::Subcommand)]
pub enum SubCommand {
Smoke(Smoke),
}

#[derive(Args)]
pub struct Smoke {
#[clap(long)]
report_name: String,
}

#[derive(Clone, Copy, Debug, WorldInit)]
struct World;

#[async_trait(?Send)]
impl cucumber::World for World {
type Error = Infallible;

async fn new() -> Result<Self, Self::Error> {
Ok(World)
}
}

#[given("an invalid step")]
fn invalid_step(_world: &mut World) {
assert!(false);
}

#[tokio::test]
// This test uses a subcommand with the global option --tags to filter
// on two failing tests and verifies that the error output contains
// 2 failing steps.
async fn tags_option_filter_all_with_subcommand() {
let cli = cli::Opts::<_, _, _, CustomCli>::try_parse_from(&[
"test",
"smoke",
r#"--report-name="smoke.report""#,
"--tags=@all",
])
.expect("Invalid command line");

let res = World::cucumber()
.with_cli(cli)
.run_and_exit("tests/features/cli");

let err = AssertUnwindSafe(res)
.catch_unwind()
.await
.expect_err("should err");

let err = err.downcast_ref::<String>().unwrap();

assert_eq!(err, "2 steps failed");
}

#[tokio::test]
// This test uses a subcommand with the global option --tags to filter
// on one failing test and verifies that the error output contains
// 1 failing step.
async fn tags_option_filter_scenario1_with_subcommand() {
let cli = cli::Opts::<_, _, _, CustomCli>::try_parse_from(&[
"test",
"smoke",
r#"--report-name="smoke.report""#,
"--tags=@scenario-1",
])
.expect("Invalid command line");

let res = World::cucumber()
.with_cli(cli)
.run_and_exit("tests/features/cli");

let err = AssertUnwindSafe(res)
.catch_unwind()
.await
.expect_err("should err");

let err = err.downcast_ref::<String>().unwrap();

assert_eq!(err, "1 step failed");
}

#[tokio::test]
// This test verifies that the global option --tags is still available
// without subcommands and that the error output contains 1 failing step.
async fn tags_option_filter_scenario1_without_subcommand() {
let cli = cli::Opts::<_, _, _, CustomCli>::try_parse_from(&[
"test",
"--tags=@scenario-1",
])
.expect("Invalid command line");

let res = World::cucumber()
.with_cli(cli)
.run_and_exit("tests/features/cli");

let err = AssertUnwindSafe(res)
.catch_unwind()
.await
.expect_err("should err");

let err = err.downcast_ref::<String>().unwrap();

assert_eq!(err, "1 step failed");
}
11 changes: 11 additions & 0 deletions tests/features/cli/subcomand_global_option.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: Test global option --tags with subcommands

@scenario-1 @all
Scenario: A scenario with two invalid steps
Given an invalid step
And an invalid step

@scenario-2 @all
Scenario: A scenario with one invalid step
Given an invalid step

0 comments on commit 9e7f242

Please sign in to comment.