mod common; use assert_cmd::cargo::CommandCargoExt as _; use common::TestVault; #[test] fn init_creates_expected_layout() { let v = TestVault::init(); assert!(v.path().join(".relicario/salt").exists()); assert!(v.path().join(".relicario/params.json").exists()); // devices.json removed — device key system was security theater assert!(!v.path().join(".relicario/devices.json").exists()); assert!(v.path().join("manifest.enc").exists()); assert!(v.path().join("settings.enc").exists()); assert!(v.path().join("reference.jpg").exists()); assert!(v.path().join(".gitignore").exists()); assert!(v.path().join(".git").is_dir()); } #[test] fn init_params_json_is_format_v2() { let v = TestVault::init(); let s = std::fs::read_to_string(v.path().join(".relicario/params.json")).unwrap(); let parsed: serde_json::Value = serde_json::from_str(&s).unwrap(); assert_eq!(parsed["format_version"], 2); assert_eq!(parsed["kdf"]["algorithm"], "argon2id-v0x13"); assert_eq!(parsed["aead"], "xchacha20poly1305"); } #[test] fn add_login_then_list_shows_it() { let v = TestVault::init(); let out = v.run(&[ "add", "login", "--title", "GitHub", "--username", "alice", "--url", "https://github.com", "--password", "hunter2", ]); assert!(out.status.success(), "add failed: {:?}", out); let out = v.run(&["list"]); let stdout = String::from_utf8(out.stdout).unwrap(); assert!(stdout.contains("GitHub"), "list missing GitHub: {stdout}"); } #[test] fn get_masks_by_default_shows_with_flag() { let v = TestVault::init(); v.run(&[ "add", "login", "--title", "gmail", "--username", "u", "--password", "super-secret", ]); let masked = v.run(&["get", "gmail"]); let stdout = String::from_utf8(masked.stdout).unwrap(); assert!(stdout.contains("********"), "expected masked: {stdout}"); assert!( !stdout.contains("super-secret"), "leaked plaintext: {stdout}" ); let shown = v.run(&["get", "gmail", "--show"]); let stdout = String::from_utf8(shown.stdout).unwrap(); assert!(stdout.contains("super-secret"), "expected plaintext: {stdout}"); } #[test] fn rm_restore_purge_cycle() { let v = TestVault::init(); v.run(&[ "add", "login", "--title", "target", "--username", "u", "--password", "p", ]); let rm = v.run(&["rm", "target"]); assert!(rm.status.success()); let out = v.run(&["list"]); assert!(!String::from_utf8(out.stdout).unwrap().contains("target")); let out = v.run(&["list", "--trashed"]); assert!(String::from_utf8(out.stdout).unwrap().contains("target")); let restore = v.run(&["restore", "target"]); assert!(restore.status.success()); let out = v.run(&["list"]); assert!(String::from_utf8(out.stdout).unwrap().contains("target")); let purge = v.run(&["purge", "target"]); assert!(purge.status.success()); let out = v.run(&["list"]); assert!(!String::from_utf8(out.stdout).unwrap().contains("target")); } #[test] fn generate_random_and_bip39() { let dir = tempfile::TempDir::new().unwrap(); let out = std::process::Command::cargo_bin("relicario") .unwrap() .current_dir(dir.path()) .args(["generate", "--length", "32"]) .output() .unwrap(); assert!(out.status.success()); assert_eq!( String::from_utf8(out.stdout).unwrap().trim().len(), 32 ); let out = std::process::Command::cargo_bin("relicario") .unwrap() .current_dir(dir.path()) .args(["generate", "--bip39", "--words", "5"]) .output() .unwrap(); assert!(out.status.success()); let phrase = String::from_utf8(out.stdout).unwrap(); assert_eq!(phrase.trim().split(' ').count(), 5); }