#![cfg(feature = "mem-repo")]
use std::fs;
use assert_cmd::Command;
use predicates::str::contains;
use tempfile::TempDir;
fn memstead() -> Command {
Command::cargo_bin("memstead").expect("memstead binary must be built by cargo")
}
#[test]
fn mem_repo_init_json_stdout_is_single_document() {
let tmp = TempDir::new().unwrap();
fs::create_dir_all(tmp.path().join(".git")).unwrap();
let workspace = tmp.path().join("ws");
let output = memstead()
.args(["--json", "mem-repo", "init", workspace.to_str().unwrap()])
.assert()
.success()
.get_output()
.clone();
let stdout = std::str::from_utf8(&output.stdout).expect("stdout must be UTF-8");
let parsed: serde_json::Value = serde_json::from_str(stdout.trim()).unwrap_or_else(|e| {
panic!("--json stdout must be exactly one JSON document: {e}; stdout:\n{stdout}")
});
assert!(
parsed
.get("mem_repo_dir")
.and_then(|v| v.as_str())
.is_some(),
"--json envelope must carry `mem_repo_dir`, got: {parsed}",
);
let stderr = std::str::from_utf8(&output.stderr).expect("stderr must be UTF-8");
assert!(
stderr.contains("outer:"),
"outer-repo provenance must appear on stderr, got stderr:\n{stderr}",
);
}
#[test]
fn mem_repo_init_followed_by_stats_succeeds() {
let tmp = TempDir::new().unwrap();
let workspace = tmp.path().join("ws");
memstead()
.args([
"mem-repo",
"init",
workspace.to_str().unwrap(),
"--no-gitignore",
])
.assert()
.success();
memstead()
.current_dir(&workspace)
.arg("stats")
.assert()
.success()
.stdout(contains("# Graph stats"));
}
#[test]
fn missing_workspace_emits_typed_envelope_json() {
let tmp = TempDir::new().unwrap();
let output = memstead()
.current_dir(tmp.path())
.args(["--json", "stats"])
.assert()
.failure()
.get_output()
.stdout
.clone();
let body = std::str::from_utf8(&output).expect("stdout must be UTF-8");
let parsed: serde_json::Value =
serde_json::from_str(body.trim()).expect("--json error envelope must parse as JSON");
assert_eq!(
parsed["code"], "WORKSPACE_NOT_INITIALISED",
"envelope must carry the symbolic workspace-not-init code, got: {parsed}",
);
let expected_command = "memstead mem-repo init";
assert_eq!(
parsed["details"]["hint"]["recovery_command"], expected_command,
"details.hint.recovery_command must name the bootstrap command for this flavour, got: {parsed}",
);
assert!(
parsed["message"]
.as_str()
.unwrap_or("")
.contains(".memstead/workspace.toml"),
"human-readable prose must still name the workspace marker, got: {parsed}",
);
}
#[test]
fn missing_workspace_prints_prose_to_stderr() {
let tmp = TempDir::new().unwrap();
memstead()
.current_dir(tmp.path())
.arg("stats")
.assert()
.failure()
.stderr(contains(".memstead/workspace.toml"));
}