#![allow(clippy::panic)]
use cucumber::gherkin::Step;
use cucumber::{World as _, given, then, when};
use tokio::process::Command;
#[derive(Debug, Default, cucumber::World)]
struct World {
workspace: Option<tempfile::TempDir>,
output: Option<std::process::Output>,
want_stdout: Vec<String>,
want_stderr: Vec<String>,
}
#[given("I'm in an empty folder")]
fn in_empty_folder(world: &mut World) {
world.workspace = Some(tempfile::tempdir().unwrap());
}
#[when(expr = "I run {string}")]
async fn i_run(world: &mut World, command: String) {
let mut args = shellwords::split(&command).unwrap().into_iter();
let mut executable = args.next().unwrap();
if executable == "conc" {
let cwd = std::env::current_dir().unwrap();
let conc_path = cwd.join("target/debug/conc");
executable = conc_path.to_string_lossy().to_string();
}
let mut command = Command::new(executable);
command.args(args);
if let Some(workspace) = &world.workspace {
command.current_dir(workspace);
}
world.output = Some(command.output().await.unwrap());
}
#[then(expr = "the exit code is {int}")]
fn the_exit_code_is(world: &mut World, expected: i32) {
let Some(output) = world.output.as_ref() else {
panic!("No command ran");
};
assert_eq!(output.status.code().unwrap(), expected);
}
#[then("STDOUT contains:")]
fn stdout_contains(world: &mut World, step: &Step) {
let want_block = step.docstring().unwrap().trim();
world.want_stdout.push(want_block.to_owned());
}
#[then("STDERR contains:")]
fn stderr_contains(world: &mut World, step: &Step) {
let want_block = step.docstring().unwrap().trim();
world.want_stderr.push(want_block.to_owned());
}
#[then("the output is empty")]
fn the_output_is_empty(world: &mut World) {
let Some(output) = world.output.as_ref() else {
panic!("No command ran");
};
assert!(output.stdout.is_empty());
assert!(output.stderr.is_empty());
}
#[then("STDERR is empty")]
fn stderr_is_empty(world: &mut World) {
let Some(output) = world.output.as_ref() else {
panic!("No command ran");
};
assert!(
output.stderr.is_empty(),
"Expected stderr to be empty but got: {}",
String::from_utf8_lossy(&output.stderr)
);
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
World::cucumber()
.after(|_feature, _rule, _scenario, _ev, world| {
Box::pin(async move {
let Some(world) = world else {
panic!("No world");
};
let Some(output) = world.output.as_ref() else {
panic!("No command ran");
};
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
test_helpers::verify_output("stdout", stdout, &world.want_stdout);
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
test_helpers::verify_output("stderr", stderr, &world.want_stderr);
})
})
.run_and_exit("features")
.await;
}