use clap::Parser;
use console::Term;
use eyre::OptionExt;
use itertools::Itertools;
use std::str::FromStr;
use tanu_core::Filter;
use crate::{get_tanu_config, ListReporter, NullReporter, ReporterType, TableReporter};
#[derive(Default)]
pub struct App;
impl App {
pub fn new() -> App {
App
}
pub async fn run(self, mut runner: crate::Runner) -> eyre::Result<()> {
let args = Args::parse();
color_eyre::install().unwrap();
let cfg = get_tanu_config();
let term = Term::stdout();
match args.command {
Command::Test {
capture_rust,
capture_http,
projects,
modules,
tests,
reporter,
concurrency,
color: color_command,
} => {
if capture_http {
runner.capture_http();
}
if capture_rust {
runner.capture_rust();
}
if let Some(concurrency) = concurrency {
runner.set_concurrency(concurrency);
}
runner.terminate_channel();
match reporter.unwrap_or_default() {
ReporterType::Table => runner.add_reporter(TableReporter::new(capture_http)),
ReporterType::List => runner.add_reporter(ListReporter::new(capture_http)),
ReporterType::Null => runner.add_reporter(NullReporter),
}
let color_env = std::env::var("CARGO_TERM_COLOR");
let color = match (color_command, color_env) {
(color @ Some(Color::Always), _) => color,
(color @ Some(Color::Never), _) => color,
(None, Ok(color)) => Color::from_str(&color).ok(),
_ => None,
};
match color {
Some(Color::Always) => {
console::set_colors_enabled(true);
console::set_colors_enabled_stderr(true);
}
Some(Color::Never) => {
console::set_colors_enabled(false);
console::set_colors_enabled_stderr(false);
}
_ => {}
}
runner.run(&projects, &modules, &tests).await
}
Command::Tui {
log_level,
tanu_log_level,
concurrency,
} => {
if let Some(concurrency) = concurrency {
runner.set_concurrency(concurrency);
} else {
runner.set_concurrency(num_cpus::get());
}
tanu_tui::run(runner, log_level, tanu_log_level).await
}
Command::Ls {} => {
let filter = tanu_core::runner::TestIgnoreFilter::default();
let list = runner.list();
let test_case_by_module = list.iter().into_group_map_by(|test| test.module.clone());
for module in test_case_by_module.keys() {
term.write_line(&format!("* {module}"))?;
for project in &cfg.projects {
for test_case in test_case_by_module
.get(module)
.ok_or_eyre("module not found")?
{
if !filter.filter(project, test_case) {
continue;
}
term.write_line(&format!(
" - [{}] {}",
project.name,
test_case.full_name()
))?;
}
}
}
Ok(())
}
}
}
}
#[derive(clap::Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Clone, Default, strum::EnumString)]
#[strum(serialize_all = "lowercase")]
pub enum Color {
#[default]
Auto,
Always,
Never,
}
#[derive(clap::Subcommand, Debug)]
pub enum Command {
Test {
#[arg(long)]
capture_http: bool,
#[arg(long)]
capture_rust: bool,
#[arg(short, long)]
projects: Vec<String>,
#[arg(short, long)]
modules: Vec<String>,
#[arg(short, long)]
tests: Vec<String>,
#[arg(long)]
reporter: Option<ReporterType>,
#[arg(short, long)]
concurrency: Option<usize>,
#[arg(long)]
color: Option<Color>,
},
Tui {
#[arg(long, default_value = "Info")]
log_level: log::LevelFilter,
#[arg(long, default_value = "Info")]
tanu_log_level: log::LevelFilter,
#[arg(short, long)]
concurrency: Option<usize>,
},
Ls {},
}