use std::fs;
use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;
use tix::config::Config;
fn tix() -> Command {
Command::cargo_bin("tix").unwrap()
}
fn read_config(dir: &std::path::Path) -> Config {
Config::load_with_warning(&dir.join("tix.toml"), |_| {}).unwrap()
}
#[test]
fn init_writes_tips_on_startup_true() {
let tmp = TempDir::new().unwrap();
let dir = tmp.path();
tix().current_dir(dir).arg("init").assert().success();
let raw = fs::read_to_string(dir.join("tix.toml")).unwrap();
assert!(
raw.contains("tips_on_startup = true"),
"the generated file must name the setting:\n{raw}"
);
let key = raw.find("tips_on_startup = true").unwrap();
let first_table = raw.find("\n[").unwrap();
assert!(
key < first_table,
"the setting is a top-level key, not a table member:\n{raw}"
);
assert!(
read_config(dir).tips_on_startup,
"the generated file must load with tips on"
);
}
#[test]
fn a_legacy_config_defaults_to_on_and_gains_no_key_on_save() {
let tmp = TempDir::new().unwrap();
let dir = tmp.path();
let legacy = "issues_dir = \"docs/issues\"\n\n\
[kanban.legacy]\n\
columns = [\n \"backlog\",\n \"doing\",\n \"review\",\n \"shipped\",\n]\n\
done_column = \"shipped\"\n";
fs::write(dir.join("tix.toml"), legacy).unwrap();
let config = read_config(dir);
assert!(config.tips_on_startup, "tips are on when the key is absent");
config.save(&dir.join("tix.toml")).unwrap();
assert_eq!(
fs::read_to_string(dir.join("tix.toml")).unwrap(),
legacy,
"an absent key must not be written back"
);
}
#[test]
fn an_explicit_false_persists_and_reads_back() {
let tmp = TempDir::new().unwrap();
let dir = tmp.path();
tix().current_dir(dir).arg("init").assert().success();
let mut config = read_config(dir);
config.tips_on_startup = false;
config.save(&dir.join("tix.toml")).unwrap();
let raw = fs::read_to_string(dir.join("tix.toml")).unwrap();
assert!(
raw.contains("tips_on_startup = false"),
"the off state must be written:\n{raw}"
);
assert!(!read_config(dir).tips_on_startup);
}
#[test]
fn the_embedded_tips_are_categorized_and_plentiful() {
let tips = tix::tips::all();
assert!(
tips.len() >= 100,
"tix #1632 asks for at least 100 tips, found {}",
tips.len()
);
let categories: std::collections::BTreeSet<&str> =
tips.iter().map(|tip| tip.category.as_str()).collect();
assert!(
categories.len() >= 10,
"the tips must be categorized, found {}",
categories.len()
);
}
#[test]
fn a_launch_that_cannot_be_asked_keeps_the_contract_error() {
let tmp = TempDir::new().unwrap();
let dir = tmp.path();
tix()
.current_dir(dir)
.assert()
.failure()
.code(1)
.stderr(predicate::str::contains(
"no tix.toml found — run \"tix init\" first",
));
assert!(
!dir.join("tix.toml").exists(),
"no configuration may be created without consent"
);
}