use std::path::PathBuf;
use std::process::Command;
use tempfile::TempDir;
fn setup_workspace() -> (TempDir, PathBuf) {
let tmp = TempDir::new().expect("tempdir");
let dir = tmp.path().to_path_buf();
Command::new("git")
.args(["init", "-q"])
.current_dir(&dir)
.output()
.expect("git init");
Command::new("git")
.args(["config", "user.email", "test@test.com"])
.current_dir(&dir)
.output()
.unwrap();
Command::new("git")
.args(["config", "user.name", "Test"])
.current_dir(&dir)
.output()
.unwrap();
std::fs::write(dir.join("README.md"), "# test\n").unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(&dir)
.output()
.unwrap();
Command::new("git")
.args(["commit", "-q", "-m", "init"])
.current_dir(&dir)
.output()
.unwrap();
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.args(["init", "--force"])
.current_dir(&dir)
.output()
.expect("decapod init");
assert!(out.status.success(), "decapod init --force failed");
let session = Command::new(env!("CARGO_BIN_EXE_decapod"))
.args(["session", "acquire"])
.current_dir(&dir)
.output()
.expect("decapod session acquire");
assert!(
session.status.success(),
"decapod session acquire failed:\n{}\n{}",
String::from_utf8_lossy(&session.stdout),
String::from_utf8_lossy(&session.stderr)
);
(tmp, dir)
}
fn run(dir: &PathBuf, args: &[&str]) -> (bool, String) {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.args(args)
.current_dir(dir)
.env("DECAPOD_VALIDATE_SKIP_GIT_GATES", "1")
.output()
.expect("failed to run decapod");
let combined = format!(
"{}\n{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
(out.status.success(), combined)
}
fn ok(dir: &PathBuf, args: &[&str]) {
let (success, output) = run(dir, args);
assert!(
success,
"expected success for `decapod {}` but got failure:\n{}",
args.join(" "),
output
);
}
fn fail(dir: &PathBuf, args: &[&str]) {
let (success, output) = run(dir, args);
assert!(
!success,
"expected failure for `decapod {}` but got success:\n{}",
args.join(" "),
output
);
}
fn extract_task_id(dir: &PathBuf) -> String {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.args(["todo", "--format", "json", "list"])
.current_dir(dir)
.output()
.expect("failed to run decapod");
let stdout = String::from_utf8_lossy(&out.stdout);
if let Ok(v) = serde_json::from_str::<serde_json::Value>(stdout.trim())
&& let Some(items) = v.get("items").and_then(|i| i.as_array())
&& let Some(first) = items.first()
&& let Some(id) = first.get("id").and_then(|i| i.as_str())
{
return id.to_string();
}
let re = regex::Regex::new(r"R_[0-9A-Z]{26}").unwrap();
if let Some(m) = re.find(&stdout) {
return m.as_str().to_string();
}
let stderr = String::from_utf8_lossy(&out.stderr);
panic!(
"could not extract task ID.\nstdout:\n{}\nstderr:\n{}",
stdout, stderr
);
}
#[test]
fn t001_version() {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.arg("--version")
.output()
.unwrap();
assert!(
!out.status.success(),
"--version flag should be rejected; use `decapod version`"
);
let s = String::from_utf8_lossy(&out.stderr);
assert!(
s.contains("unexpected argument '--version'") || s.contains("Usage: decapod <COMMAND>"),
"expected clap argument rejection for --version, got:\n{}",
s
);
}
#[test]
fn t002_help() {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.arg("--help")
.output()
.unwrap();
assert!(out.status.success());
}
#[test]
fn t003_no_args_errors() {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.output()
.unwrap();
assert!(!out.status.success());
}
#[test]
fn t004_version_command_works() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(&dir, &["version"]);
assert!(success, "version command should succeed, got:\n{}", output);
assert!(
output.contains(env!("CARGO_PKG_VERSION")),
"expected version string in output:\n{}",
output
);
}
#[test]
fn t010_init_lifecycle() {
let tmp = TempDir::new().unwrap();
let dir = tmp.path().to_path_buf();
Command::new("git")
.args(["init", "-q"])
.current_dir(&dir)
.output()
.unwrap();
Command::new("git")
.args(["config", "user.email", "t@t"])
.current_dir(&dir)
.output()
.unwrap();
Command::new("git")
.args(["config", "user.name", "t"])
.current_dir(&dir)
.output()
.unwrap();
std::fs::write(dir.join("README.md"), "# t\n").unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(&dir)
.output()
.unwrap();
Command::new("git")
.args(["commit", "-q", "-m", "init"])
.current_dir(&dir)
.output()
.unwrap();
ok(&dir, &["init"]);
ok(&dir, &["init", "--force"]);
ok(&dir, &["init", "--dry-run"]);
ok(&dir, &["init", "--all"]);
ok(&dir, &["init", "--claude"]);
ok(&dir, &["init", "--gemini"]);
ok(&dir, &["init", "--agents"]);
ok(&dir, &["init", "clean"]);
ok(&dir, &["init", "--force"]);
ok(&dir, &["i"]);
}
#[test]
fn t020_setup_hooks() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["setup", "hook", "--commit-msg"]);
ok(&dir, &["setup", "hook", "--pre-commit"]);
ok(&dir, &["setup", "hook", "--uninstall"]);
ok(&dir, &["setup", "--help"]);
}
#[test]
fn t030_docs() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["docs", "show", "core/DECAPOD.md"]);
ok(&dir, &["docs", "show", "specs/INTENT.md"]);
ok(&dir, &["docs", "show", "plugins/TODO.md"]);
ok(&dir, &["docs", "ingest"]);
ok(&dir, &["docs", "override"]);
ok(&dir, &["docs", "--help"]);
ok(&dir, &["d", "show", "core/DECAPOD.md"]);
fail(&dir, &["docs", "show", "nonexistent.md"]);
}
#[test]
fn t040_todo_lifecycle() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&["todo", "add", "Test task 1", "--description", "A test task"],
);
ok(&dir, &["todo", "add", "Test task 2"]);
ok(&dir, &["todo", "list"]);
ok(&dir, &["todo", "--format", "json", "list"]);
ok(&dir, &["todo", "--format", "text", "list"]);
let id = extract_task_id(&dir);
ok(&dir, &["todo", "get", "--id", &id]);
ok(
&dir,
&["todo", "claim", "--id", &id, "--agent", "test-agent"],
);
ok(
&dir,
&["todo", "comment", "--id", &id, "--comment", "Test comment"],
);
ok(
&dir,
&[
"todo",
"add-owner",
"--id",
&id,
"--agent",
"test-reviewer",
"--claim-type",
"secondary",
],
);
ok(&dir, &["todo", "list-owners", "--id", &id]);
ok(
&dir,
&[
"todo",
"remove-owner",
"--id",
&id,
"--agent",
"test-reviewer",
],
);
ok(
&dir,
&["todo", "edit", "--id", &id, "--title", "Updated title"],
);
ok(&dir, &["todo", "release", "--id", &id]);
ok(&dir, &["todo", "done", "--id", &id]);
ok(&dir, &["todo", "categories"]);
ok(&dir, &["t", "list"]);
ok(&dir, &["todo", "--help"]);
}
#[test]
fn t057_todo_add_all_opts() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"todo",
"add",
"Full task",
"--description",
"desc",
"--priority",
"high",
"--tags",
"bug,ux",
"--owner",
"dev1",
],
);
}
#[test]
fn t058_todo_get_nonexistent() {
let (_tmp, dir) = setup_workspace();
let (_, _) = run(&dir, &["todo", "get", "--id", "NONEXISTENT_ID_12345"]);
}
#[test]
fn t059_todo_add_relationships() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["todo", "add", "Parent task"]);
let parent_id = extract_task_id(&dir);
ok(&dir, &["todo", "add", "Ref task", "--ref", "issue#42"]);
ok(&dir, &["todo", "add", "Child task", "--parent", &parent_id]);
ok(
&dir,
&["todo", "add", "Dep task", "--depends-on", &parent_id],
);
ok(&dir, &["todo", "add", "Block task", "--blocks", &parent_id]);
}
#[test]
fn t051_todo_done_validated() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["todo", "add", "Validated task"]);
let id = extract_task_id(&dir);
ok(&dir, &["todo", "done", "--id", &id, "--validated"]);
}
#[test]
#[ignore] fn t053_todo_rebuild() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["todo", "add", "Rebuild test"]);
let id = extract_task_id(&dir);
ok(&dir, &["todo", "edit", "--id", &id, "--title", "Edited"]);
ok(&dir, &["todo", "claim", "--id", &id, "--agent", "a"]);
ok(&dir, &["todo", "release", "--id", &id]);
ok(&dir, &["todo", "rebuild"]);
}
#[test]
fn t060_validate() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["validate"]);
ok(&dir, &["validate", "--store", "user"]);
ok(&dir, &["validate", "--store", "repo"]);
ok(&dir, &["validate", "--format", "json"]);
ok(&dir, &["validate", "--format", "text"]);
ok(&dir, &["v"]);
}
#[test]
fn t066_validate_errors() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["validate", "--store", "invalid"]);
ok(&dir, &["validate", "--format", "invalid"]);
}
#[test]
fn t070_policy() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"govern",
"policy",
"eval",
"--command",
"rm -rf /",
"--path",
"/tmp/test",
],
);
ok(
&dir,
&["govern", "policy", "eval", "--command", "ls", "--path", "."],
);
ok(&dir, &["govern", "policy", "riskmap", "init"]);
ok(&dir, &["govern", "policy", "riskmap", "verify"]);
ok(&dir, &["govern", "policy", "--help"]);
ok(
&dir,
&["govern", "policy", "approve", "--id", "TEST_APPROVAL_123"],
);
}
#[test]
fn t080_health() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"govern",
"health",
"claim",
"--id",
"test-claim-1",
"--subject",
"System is healthy",
"--kind",
"assertion",
],
);
ok(
&dir,
&[
"govern",
"health",
"proof",
"--claim-id",
"test-claim-1",
"--surface",
"manual check",
"--result",
"pass",
],
);
ok(&dir, &["govern", "health", "get", "--id", "test-claim-1"]);
ok(&dir, &["govern", "health", "summary"]);
ok(&dir, &["govern", "health", "autonomy"]);
ok(&dir, &["govern", "health", "--help"]);
ok(
&dir,
&[
"govern",
"health",
"claim",
"--id",
"test-claim-2",
"--subject",
"Has tests",
"--kind",
"proof",
"--provenance",
"test suite",
],
);
}
#[test]
fn t090_proof() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["govern", "proof", "run"]);
fail(&dir, &["govern", "proof", "test", "--name", "schema-check"]);
ok(&dir, &["govern", "proof", "list"]);
ok(&dir, &["govern", "proof", "--help"]);
}
#[test]
fn t100_watcher() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["govern", "watcher", "run"]);
ok(&dir, &["govern", "watcher", "--help"]);
}
#[test]
fn t110_feedback() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"govern",
"feedback",
"add",
"--source",
"test-agent",
"--text",
"Test feedback",
],
);
ok(
&dir,
&[
"govern",
"feedback",
"add",
"--source",
"test-agent",
"--text",
"Feedback with link",
"--links",
"specs/INTENT.md",
],
);
ok(&dir, &["govern", "feedback", "propose"]);
ok(&dir, &["govern", "feedback", "--help"]);
}
#[test]
fn t120_archive() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["data", "archive", "list"]);
ok(&dir, &["data", "archive", "verify"]);
ok(&dir, &["data", "archive", "--help"]);
}
#[test]
fn t130_knowledge() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"data",
"knowledge",
"add",
"--id",
"kb-001",
"--title",
"Test entry",
"--text",
"Some knowledge text",
"--provenance",
"cmd:manual-entry",
],
);
ok(
&dir,
&[
"data",
"knowledge",
"add",
"--id",
"kb-002",
"--title",
"Linked entry",
"--text",
"Knowledge with claim",
"--provenance",
"cmd:manual-entry",
"--claim-id",
"test-claim-1",
],
);
ok(&dir, &["data", "knowledge", "search", "--query", "test"]);
ok(&dir, &["data", "knowledge", "--help"]);
}
#[test]
fn t140_context() {
let (_tmp, dir) = setup_workspace();
let test_file = dir.join("test_file.txt");
std::fs::write(&test_file, "some content\n").unwrap();
let test_file_str = test_file.to_str().unwrap();
ok(
&dir,
&[
"data",
"context",
"audit",
"--profile",
"main",
"--files",
test_file_str,
],
);
ok(
&dir,
&[
"data",
"context",
"pack",
"--path",
test_file_str,
"--summary",
"Test context pack",
],
);
fail(
&dir,
&[
"data",
"context",
"restore",
"--id",
"ctx-001",
"--profile",
"main",
"--current-files",
test_file_str,
],
);
ok(&dir, &["data", "context", "--help"]);
}
#[test]
fn t150_schema() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["data", "schema"]);
ok(&dir, &["data", "schema", "--format", "json"]);
ok(&dir, &["data", "schema", "--format", "md"]);
ok(&dir, &["data", "schema", "--deterministic"]);
ok(&dir, &["data", "schema", "--subsystem", "todo"]);
ok(&dir, &["data", "schema", "--subsystem", "health"]);
ok(&dir, &["data", "schema", "--subsystem", "policy"]);
ok(&dir, &["data", "schema", "--subsystem", "nonexistent"]);
}
#[test]
fn t160_repo() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["data", "repo", "map"]);
ok(&dir, &["data", "repo", "graph"]);
ok(&dir, &["data", "repo", "--help"]);
}
#[test]
fn t170_broker() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["data", "broker", "audit"]);
ok(&dir, &["data", "broker", "--help"]);
}
#[test]
fn t180_aptitude() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"data",
"aptitude",
"add",
"--category",
"style",
"--key",
"theme",
"--value",
"dark mode",
],
);
ok(
&dir,
&[
"data",
"aptitude",
"add",
"--category",
"workflow",
"--key",
"editor",
"--value",
"neovim",
"--context",
"coding sessions",
"--source",
"user_request",
],
);
ok(&dir, &["data", "aptitude", "list"]);
ok(
&dir,
&[
"data",
"aptitude",
"get",
"--category",
"style",
"--key",
"theme",
],
);
ok(
&dir,
&[
"data",
"aptitude",
"observe",
"--content",
"User prefers concise responses",
],
);
ok(
&dir,
&[
"data",
"aptitude",
"observe",
"--content",
"Always uses dark mode",
"--category",
"style",
],
);
ok(&dir, &["data", "aptitude", "prompt"]);
ok(
&dir,
&["data", "aptitude", "prompt", "--context", "code review"],
);
ok(&dir, &["data", "aptitude", "prompt", "--format", "json"]);
ok(&dir, &["data", "aptitude", "--help"]);
}
#[test]
fn t190_cron() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"auto",
"cron",
"add",
"--name",
"test-cron",
"--schedule",
"0 * * * *",
"--command",
"echo hello",
],
);
ok(
&dir,
&[
"auto",
"cron",
"add",
"--name",
"full-cron",
"--schedule",
"*/5 * * * *",
"--command",
"echo world",
"--description",
"A test cron",
"--tags",
"test,dev",
],
);
ok(&dir, &["auto", "cron", "list"]);
let (_, out) = run(&dir, &["auto", "cron", "list"]);
let cron_id = extract_ulid_from(&out);
ok(&dir, &["auto", "cron", "get", "--id", &cron_id]);
ok(
&dir,
&[
"auto",
"cron",
"update",
"--id",
&cron_id,
"--schedule",
"*/10 * * * *",
],
);
ok(&dir, &["auto", "cron", "list", "--status", "active"]);
ok(&dir, &["auto", "cron", "list", "--name-search", "test"]);
ok(&dir, &["auto", "cron", "delete", "--id", &cron_id]);
ok(&dir, &["auto", "cron", "--help"]);
}
#[test]
fn t200_reflex() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"auto",
"reflex",
"add",
"--name",
"test-reflex",
"--trigger-type",
"event",
"--action-type",
"command",
"--action-config",
"echo done",
],
);
ok(
&dir,
&[
"auto",
"reflex",
"add",
"--name",
"full-reflex",
"--trigger-type",
"event",
"--action-type",
"command",
"--action-config",
"echo world",
"--description",
"A test reflex",
"--tags",
"test",
],
);
ok(&dir, &["auto", "reflex", "list"]);
let (_, out) = run(&dir, &["auto", "reflex", "list"]);
let reflex_id = extract_ulid_from(&out);
ok(&dir, &["auto", "reflex", "get", "--id", &reflex_id]);
ok(
&dir,
&[
"auto",
"reflex",
"update",
"--id",
&reflex_id,
"--name",
"updated-reflex",
],
);
ok(&dir, &["auto", "reflex", "list", "--status", "active"]);
ok(&dir, &["auto", "reflex", "delete", "--id", &reflex_id]);
ok(&dir, &["auto", "reflex", "--help"]);
}
#[test]
fn t208_container_surface() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["auto", "container", "--help"]);
ok(&dir, &["auto", "container", "run", "--help"]);
ok(&dir, &["data", "schema", "--subsystem", "container"]);
}
#[test]
fn t210_verify() {
let (_tmp, dir) = setup_workspace();
ok(
&dir,
&[
"todo",
"add",
"Verify test task",
"--description",
"For QA verify",
],
);
let id = extract_task_id(&dir);
ok(&dir, &["qa", "verify", "todo", &id]);
ok(&dir, &["qa", "verify", "--stale"]);
ok(&dir, &["qa", "verify", "--json"]);
ok(&dir, &["qa", "verify", "--help"]);
}
#[test]
fn t220_check() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["qa", "check"]);
ok(&dir, &["qa", "check", "--help"]);
}
#[test]
fn t240_group_help() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["govern", "--help"]);
ok(&dir, &["g", "--help"]);
ok(&dir, &["data", "--help"]);
ok(&dir, &["auto", "--help"]);
ok(&dir, &["a", "--help"]);
ok(&dir, &["qa", "--help"]);
ok(&dir, &["q", "--help"]);
}
#[test]
fn t280_invalid_subcommand() {
let out = Command::new(env!("CARGO_BIN_EXE_decapod"))
.arg("notacommand")
.output()
.unwrap();
assert!(!out.status.success());
}
#[test]
fn t281_todo_add_empty_string() {
let (_tmp, dir) = setup_workspace();
ok(&dir, &["todo", "add", ""]);
}
#[test]
fn t282_todo_get_missing_id() {
let (_tmp, dir) = setup_workspace();
fail(&dir, &["todo", "get"]);
}
#[test]
fn t283_docs_show_empty_path() {
let (_tmp, dir) = setup_workspace();
fail(&dir, &["docs", "show", ""]);
}
#[test]
fn t284_knowledge_add_missing_fields() {
let (_tmp, dir) = setup_workspace();
fail(&dir, &["data", "knowledge", "add", "--id", "kb-only"]);
}
#[test]
fn t285_cron_add_missing_schedule() {
let (_tmp, dir) = setup_workspace();
fail(
&dir,
&["auto", "cron", "add", "--name", "bad", "--command", "echo"],
);
}
#[test]
fn t286_reflex_add_missing_trigger() {
let (_tmp, dir) = setup_workspace();
fail(
&dir,
&[
"auto",
"reflex",
"add",
"--name",
"bad",
"--action-type",
"command",
"--action-config",
"echo",
],
);
}
#[test]
fn t287_aptitude_get_missing_key() {
let (_tmp, dir) = setup_workspace();
fail(&dir, &["data", "aptitude", "get", "--category", "style"]);
}
#[test]
fn t288_health_claim_missing_fields() {
let (_tmp, dir) = setup_workspace();
fail(&dir, &["govern", "health", "claim", "--id", "only-id"]);
}
#[test]
fn t290_decide_trees() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(&dir, &["decide", "trees"]);
assert!(success, "decide trees failed:\n{}", output);
assert!(output.contains("web-app"));
assert!(output.contains("microservice"));
assert!(output.contains("cli-tool"));
assert!(output.contains("library"));
}
#[test]
fn t291_decide_suggest() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(
&dir,
&["decide", "suggest", "--prompt", "build a web application"],
);
assert!(success, "decide suggest failed:\n{}", output);
assert!(output.contains("web-app"));
}
#[test]
fn t292_decide_session_lifecycle() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(
&dir,
&[
"decide",
"start",
"--tree",
"cli-tool",
"--title",
"Gatling CLI Test",
],
);
assert!(success, "decide start failed:\n{}", output);
assert!(output.contains("DS_"));
let re = regex::Regex::new(r"DS_[0-9A-Z]{26}").unwrap();
let session_id = re
.find(&output)
.map(|m| m.as_str().to_string())
.expect("no session ID found");
let (success, output) = run(&dir, &["decide", "next", "--session", &session_id]);
assert!(success, "decide next failed:\n{}", output);
assert!(output.contains("language"));
let (success, output) = run(
&dir,
&[
"decide",
"record",
"--session",
&session_id,
"--question",
"language",
"--value",
"rust",
],
);
assert!(success, "decide record failed:\n{}", output);
assert!(output.contains("DD_"));
assert!(output.contains("Rust"));
let (success, output) = run(&dir, &["decide", "list", "--session", &session_id]);
assert!(success, "decide list failed:\n{}", output);
assert!(output.contains("rust"));
let (success, output) = run(&dir, &["decide", "session", "list"]);
assert!(success, "decide session list failed:\n{}", output);
assert!(output.contains(&session_id));
let (success, output) = run(&dir, &["decide", "session", "get", "--id", &session_id]);
assert!(success, "decide session get failed:\n{}", output);
assert!(output.contains("Gatling CLI Test"));
let (success, output) = run(&dir, &["decide", "complete", "--session", &session_id]);
assert!(success, "decide complete failed:\n{}", output);
assert!(output.contains("completed"));
}
#[test]
fn t293_decide_invalid_tree() {
let (_tmp, dir) = setup_workspace();
fail(
&dir,
&["decide", "start", "--tree", "nonexistent", "--title", "Bad"],
);
}
#[test]
fn t294_decide_invalid_option() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(
&dir,
&[
"decide",
"start",
"--tree",
"cli-tool",
"--title",
"Bad Option Test",
],
);
assert!(success);
let re = regex::Regex::new(r"DS_[0-9A-Z]{26}").unwrap();
let session_id = re.find(&output).unwrap().as_str();
fail(
&dir,
&[
"decide",
"record",
"--session",
session_id,
"--question",
"language",
"--value",
"cobol",
],
);
}
#[test]
fn t295_decide_schema() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(&dir, &["decide", "schema"]);
assert!(success, "decide schema failed:\n{}", output);
assert!(output.contains("decide"));
assert!(output.contains("decisions.db"));
}
#[test]
fn t296_decide_init() {
let (_tmp, dir) = setup_workspace();
let (success, output) = run(&dir, &["decide", "init"]);
assert!(success, "decide init failed:\n{}", output);
assert!(output.contains("initialized"));
}
fn extract_ulid_from(text: &str) -> String {
let re = regex::Regex::new(r"[0-9A-Z]{26}").unwrap();
re.find(text)
.map(|m| m.as_str().to_string())
.unwrap_or_else(|| panic!("no ULID found in output:\n{}", text))
}