use super::*;
use clap::Parser;
#[test]
fn a_silent_terminal_does_not_hold_the_first_frame() {
let (tx, rx) = std::sync::mpsc::channel::<AppEvent>();
let mut backlog = Vec::new();
let started = std::time::Instant::now();
assert_eq!(take_answer(&rx, None, &mut backlog), None);
assert!(started.elapsed() < Duration::from_millis(20));
assert!(backlog.is_empty());
drop(tx);
}
#[test]
fn an_answer_already_in_is_taken() {
use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
let (tx, rx) = std::sync::mpsc::channel::<AppEvent>();
let key = |c| {
AppEvent::Terminal(Event::Key(KeyEvent::new(
KeyCode::Char(c),
KeyModifiers::NONE,
)))
};
tx.send(key('j')).unwrap();
tx.send(AppEvent::TerminalBackground(ThemeMode::Light))
.unwrap();
tx.send(key('k')).unwrap();
let mut backlog = Vec::new();
assert_eq!(
take_answer(&rx, Some(ThemeMode::Dark), &mut backlog),
Some(ThemeMode::Light)
);
let typed: Vec<_> = backlog
.iter()
.map(|event| match event {
AppEvent::Terminal(Event::Key(key)) => key.code,
_ => KeyCode::Null,
})
.collect();
assert_eq!(typed, [KeyCode::Char('j'), KeyCode::Char('k')]);
assert_eq!(
take_answer(&rx, Some(ThemeMode::Dark), &mut Vec::new()),
Some(ThemeMode::Dark)
);
}
#[test]
fn the_mouse_flag_overrides_the_config() {
let after = |flags: &[&str], configured: bool| {
let args = Args::try_parse_from(std::iter::once("datui").chain(flags.iter().copied()))
.expect("parses");
let mut config = AppConfig::default();
config.display.mouse = configured;
apply_args(&mut config, &args);
config.display.mouse
};
assert!(!after(&["--mouse=false"], true));
assert!(after(&["--mouse"], false));
assert!(after(&["--mouse=true"], false));
assert!(after(&[], true));
assert!(!after(&[], false));
}
#[test]
fn a_flag_beats_dash_c_which_beats_the_file() {
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("config.toml");
std::fs::write(
&file,
"[analysis]\nsample_rows = 10\n[display]\nrow_numbers_start = 5\n",
)
.unwrap();
let effective = |flags: &[&str]| {
let args = Args::try_parse_from(std::iter::once("datui").chain(flags.iter().copied()))
.expect("parses");
let mut config = AppConfig::load_from_file_with(&file, &args.config).unwrap();
apply_args(&mut config, &args);
(
config.analysis.sample_rows,
config.display.row_numbers_start,
)
};
assert_eq!(effective(&[]), (10, 5));
assert_eq!(effective(&["-c", "analysis.sample_rows=20"]), (20, 5));
assert_eq!(
effective(&["-c", "analysis.sample_rows=20", "--sample-rows", "30"]),
(30, 5)
);
assert_eq!(
effective(&[
"-c",
"display.row_numbers_start=0",
"-c",
"display.row_numbers_start=2"
]),
(10, 2)
);
}
#[test]
fn a_dash_c_the_config_cannot_read_is_named() {
let args =
Args::try_parse_from(["datui", "-c", "display.number_format=[1, 2]"]).expect("parses");
let dir = tempfile::tempdir().unwrap();
let error = AppConfig::load_from_file_with(&dir.path().join("none.toml"), &args.config)
.unwrap_err()
.to_string();
assert!(error.starts_with("-c:"), "{error}");
}
#[test]
fn the_command_line_s_paths_expand_a_leading_tilde() {
let home = dirs::home_dir().expect("a home directory");
let args = Args::try_parse_from([
"datui",
"~/a.csv",
"b.csv",
"--temp-dir",
"~/scratch",
"--format",
"~/l2feed.toml",
"--dict",
"~/car.dbc",
])
.unwrap();
let RunInput::Cli(args) = expand_home(RunInput::Cli(Box::new(args))) else {
panic!("still the command line");
};
assert_eq!(args.paths, [home.join("a.csv"), PathBuf::from("b.csv")]);
assert_eq!(args.temp_dir, Some(home.join("scratch")));
assert_eq!(
args.format,
Some(crate::cli::FormatChoice::File(home.join("l2feed.toml")))
);
assert_eq!(args.dict, [home.join("car.dbc")]);
}
#[test]
fn performance_threads_caps_polars_unless_the_environment_says() {
assert_eq!(polars_threads(4, None).as_deref(), Some("4"));
assert_eq!(polars_threads(0, None), None);
let asked = std::ffi::OsString::from("2");
assert_eq!(polars_threads(4, Some(&asked)), None);
}