use std::{path::PathBuf, process::Command};
use assert_cmd::{assert::OutputAssertExt, cargo::CommandCargoExt};
use assert_fs::prelude::FileWriteStr;
use predicates::prelude::predicate;
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use rexpect::session::spawn_command;
use super::*;
const DIR: &str = env!("CARGO_MANIFEST_DIR");
fn get_config_path() -> String {
let mut path_buf = PathBuf::from(DIR);
path_buf.push("tests/config.toml");
path_buf.to_str().unwrap().to_string()
}
fn get_primary_test_todo_path() -> String {
let mut path_buf = PathBuf::from(DIR);
path_buf.push("tests/source1/todo.txt");
path_buf.to_str().unwrap().to_string()
}
fn get_secondary_test_todo_path() -> String {
let mut path_buf = PathBuf::from(DIR);
path_buf.push("tests/source2/todo.txt");
path_buf.to_str().unwrap().to_string()
}
fn get_tertiary_test_todo_path() -> String {
let mut path_buf = PathBuf::from(DIR);
path_buf.push("tests/source3/todo.txt");
path_buf.to_str().unwrap().to_string()
}
#[test]
fn todo_txt_file_does_not_exist() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg("test/file/does/not/exist")
.arg("-c")
.arg(get_config_path());
cmd.assert()
.failure()
.stderr(predicate::str::contains("could not read file"));
Ok(())
}
#[test]
fn task_exists() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path())
.arg("-c")
.arg(get_config_path())
.arg("projects")
.arg("alpha");
cmd.assert()
.success()
.stdout(predicate::str::contains("Project ALPHA"))
.stdout(predicate::str::contains("todo: <<< match this >>>"));
Ok(())
}
#[test]
fn tasks_exist() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path())
.arg("-c")
.arg(get_config_path())
.arg("projects")
.arg("alpha")
.arg("bravo");
cmd.assert()
.success()
.stdout(predicate::str::contains("Project ALPHA"))
.stdout(predicate::str::contains("todo: <<< match this >>>"))
.stdout(predicate::str::contains("Project BRAVO"))
.stdout(predicate::str::contains("todo: <<< match this as well >>>"));
Ok(())
}
#[test]
fn task_not_found() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path().as_str())
.arg("-c")
.arg(get_config_path())
.arg("projects")
.arg("zulu");
cmd.assert().success().stdout(predicate::str::contains(
"Project `zulu` contains no task as of now",
));
Ok(())
}
#[test]
fn no_project_name_input() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path().as_str())
.arg("-c")
.arg(get_config_path());
cmd.assert()
.success()
.stdout(predicate::str::contains("Project ALPHA"))
.stdout(predicate::str::contains("todo: <<< match this >>>"));
Ok(())
}
#[test]
fn empty_todo_list() -> Result<(), Box<dyn std::error::Error>> {
let config = assert_fs::NamedTempFile::new("config.toml")?;
let mut config_str: String = String::from("todo_files = ['");
config_str.push_str(get_primary_test_todo_path().as_str());
config_str.push_str("']");
config.write_str(&config_str)?;
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_tertiary_test_todo_path())
.arg("-c")
.arg(config.path());
cmd.assert()
.success()
.stdout(predicate::str::contains("todo list is empty!"));
Ok(())
}
#[test]
fn no_partial_project_name_match() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path().as_str())
.arg("-c")
.arg(get_config_path())
.arg("projects")
.arg("alph");
cmd.assert().success().stdout(predicate::str::contains(
"Project `alph` contains no task as of now.",
));
Ok(())
}
#[test]
fn test_configuration_input() -> Result<(), Box<dyn std::error::Error>> {
let config = assert_fs::NamedTempFile::new("config.toml")?;
let mut config_str: String = String::from("todo_files = ['");
config_str.push_str(get_primary_test_todo_path().as_str());
config_str.push_str("']");
config.write_str(&config_str)?;
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-c")
.arg(config.path())
.arg("projects")
.arg("alpha");
cmd.assert()
.success()
.stdout(predicate::str::contains("Project ALPHA"))
.stdout(predicate::str::contains("match this"));
Ok(())
}
#[test]
fn test_multiple_todos() -> Result<(), Box<dyn std::error::Error>> {
let config = assert_fs::NamedTempFile::new("config.toml")?;
let mut config_str: String = String::from("todo_files = ['");
config_str.push_str(get_primary_test_todo_path().as_str());
config_str.push_str("', '");
config_str.push_str(get_secondary_test_todo_path().as_str());
config_str.push_str("']");
config.write_str(&config_str)?;
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-c")
.arg(config.path())
.arg("projects")
.arg("charlie");
cmd.assert()
.success()
.stdout(predicate::str::contains("match this"))
.stdout(predicate::str::contains("Project CHARLIE"));
Ok(())
}
#[test]
fn test_focus_task_quit() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("toddi")?;
cmd.arg("-t")
.arg(get_primary_test_todo_path())
.arg("-c")
.arg(get_config_path())
.arg("focus");
let mut p = spawn_command(cmd, Some(5_000))?;
p.exp_string("todo: ")?;
p.exp_string("Is it done? (y/n/q): ")?;
p.send_line("q")?;
p.exp_string("Alright, we are done for now.")?;
p.exp_eof()?;
Ok(())
}
}