use btctax_cli::cmd;
use btctax_store::Passphrase;
use std::path::Path;
fn pp() -> Passphrase {
Passphrase::new("pw".into())
}
fn import_river_income(vault: &Path) -> String {
let dir = vault.parent().expect("vault must have a parent directory");
let csv_path = dir.join("river_income.csv");
std::fs::write(
&csv_path,
"Date,Sent Amount,Sent Currency,Received Amount,Received Currency,Fee Amount,Fee Currency,Tag\r\n\
2025-03-01 12:00:00,,,0.00100000,BTC,,,Income\r\n",
)
.unwrap();
cmd::import::run(vault, &pp(), &[csv_path]).unwrap();
let s = btctax_cli::Session::open(vault, &pp()).unwrap();
let events = btctax_core::persistence::load_all(s.conn()).unwrap();
events
.iter()
.find_map(|e| match &e.payload {
btctax_core::EventPayload::Income(_) => Some(e.id.canonical()),
_ => None,
})
.expect("imported River income event must exist")
}
fn run_reclassify_income(vault: &Path, args: &[&str]) -> (i32, String) {
let bin = env!("CARGO_BIN_EXE_btctax");
let output = std::process::Command::new(bin)
.arg("--vault")
.arg(vault.to_str().expect("vault path is valid UTF-8"))
.arg("reconcile")
.arg("reclassify-income")
.args(args)
.env("BTCTAX_PASSPHRASE", "pw")
.output()
.expect("btctax binary must execute successfully");
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
let code = output
.status
.code()
.expect("btctax process must exit normally (not via signal)");
(code, stderr)
}
#[test]
fn reclassify_income_business_true_is_accepted() {
let dir = tempfile::tempdir().unwrap();
let vault = dir.path().join("vault.pgp");
cmd::init::run(&vault, &pp(), &dir.path().join("k.asc")).unwrap();
let income_ref = import_river_income(&vault);
let (code, stderr) = run_reclassify_income(&vault, &[&income_ref, "--business", "true"]);
assert_eq!(
code, 0,
"reclassify-income <ref> --business true must exit 0; stderr: {stderr}"
);
}
#[test]
fn reclassify_income_bare_business_flag_is_rejected() {
let dir = tempfile::tempdir().unwrap();
let vault = dir.path().join("vault.pgp");
let (code, stderr) = run_reclassify_income(&vault, &["some-event-ref", "--business"]);
assert_ne!(
code, 0,
"reclassify-income <ref> --business (bare, no value) must exit non-zero; stderr: {stderr}"
);
}
#[test]
fn reclassify_income_omitted_business_is_rejected() {
let dir = tempfile::tempdir().unwrap();
let vault = dir.path().join("vault.pgp");
let (code, stderr) = run_reclassify_income(&vault, &["some-event-ref"]);
assert_ne!(
code, 0,
"reclassify-income <ref> (no --business) must exit non-zero; stderr: {stderr}"
);
}