mod common;
use common::{init_project, normalize_output, run_commands, run_dynamic_commands, today};
use std::fs;
#[test]
fn test_delete_clause_safeguard_normative() {
let temp_dir = init_project();
let date = today();
let rfc_dir = temp_dir.path().join("gov/rfc/RFC-0001");
fs::create_dir_all(rfc_dir.join("clauses")).unwrap();
fs::write(
rfc_dir.join("rfc.toml"),
r#"#:schema ../../schema/rfc.schema.json
[govctl]
schema = 1
id = "RFC-0001"
title = "Normative RFC"
version = "1.0.0"
status = "normative"
phase = "stable"
owners = ["test@example.com"]
created = "2026-01-01"
[[sections]]
title = "Specification"
clauses = ["clauses/C-LOCKED.toml"]
[[changelog]]
version = "1.0.0"
date = "2026-01-01"
added = ["Initial release"]
"#,
)
.unwrap();
fs::write(
rfc_dir.join("clauses/C-LOCKED.toml"),
r#"#:schema ../../schema/clause.schema.json
[govctl]
schema = 1
id = "C-LOCKED"
title = "Locked Clause"
kind = "normative"
status = "active"
since = "1.0.0"
[content]
text = "This clause cannot be deleted - RFC is normative."
"#,
)
.unwrap();
let output = run_commands(
temp_dir.path(),
&[&["clause", "delete", "RFC-0001:C-LOCKED", "-f"]],
);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}
#[test]
fn test_delete_clause_success_draft() {
let temp_dir = init_project();
let date = today();
let rfc_dir = temp_dir.path().join("gov/rfc/RFC-0001");
fs::create_dir_all(rfc_dir.join("clauses")).unwrap();
fs::write(
rfc_dir.join("rfc.toml"),
r#"#:schema ../../schema/rfc.schema.json
[govctl]
schema = 1
id = "RFC-0001"
title = "Draft RFC"
version = "0.1.0"
status = "draft"
phase = "spec"
owners = ["test@example.com"]
created = "2026-01-01"
[[sections]]
title = "Specification"
clauses = ["clauses/C-KEEP.toml", "clauses/C-DELETE.toml"]
[[changelog]]
version = "0.1.0"
date = "2026-01-01"
notes = "Initial draft"
"#,
)
.unwrap();
fs::write(
rfc_dir.join("clauses/C-KEEP.toml"),
r#"#:schema ../../schema/clause.schema.json
[govctl]
schema = 1
id = "C-KEEP"
title = "Keep This Clause"
kind = "normative"
status = "active"
since = "0.1.0"
[content]
text = "This clause will remain."
"#,
)
.unwrap();
fs::write(
rfc_dir.join("clauses/C-DELETE.toml"),
r#"#:schema ../../schema/clause.schema.json
[govctl]
schema = 1
id = "C-DELETE"
title = "Delete This Clause"
kind = "normative"
status = "active"
since = "0.1.0"
[content]
text = "This clause will be deleted."
"#,
)
.unwrap();
let output = run_commands(
temp_dir.path(),
&[
&["clause", "delete", "RFC-0001:C-DELETE", "-f"],
&["clause", "list", "RFC-0001"],
&["check"],
],
);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}
#[test]
fn test_delete_work_safeguard_active() {
let temp_dir = init_project();
let date = today();
let wi1 = format!("WI-{}-001", date);
let commands: Vec<Vec<String>> = vec![
vec![
"work".to_string(),
"new".to_string(),
"Active work item".to_string(),
"--active".to_string(),
],
vec![
"work".to_string(),
"add".to_string(),
wi1.clone(),
"acceptance_criteria".to_string(),
"chore: Test criterion".to_string(),
],
vec![
"work".to_string(),
"delete".to_string(),
wi1.clone(),
"-f".to_string(),
],
];
let output = run_dynamic_commands(temp_dir.path(), &commands);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}
#[test]
fn test_delete_work_safeguard_done() {
let temp_dir = init_project();
let date = today();
let wi1 = format!("WI-{}-001", date);
let commands: Vec<Vec<String>> = vec![
vec![
"work".to_string(),
"new".to_string(),
"Completed work item".to_string(),
"--active".to_string(),
],
vec![
"work".to_string(),
"add".to_string(),
wi1.clone(),
"acceptance_criteria".to_string(),
"chore: Test criterion".to_string(),
],
vec![
"work".to_string(),
"tick".to_string(),
wi1.clone(),
"acceptance_criteria".to_string(),
"Test".to_string(),
"-s".to_string(),
"done".to_string(),
],
vec![
"work".to_string(),
"move".to_string(),
wi1.clone(),
"done".to_string(),
],
vec![
"work".to_string(),
"delete".to_string(),
wi1.clone(),
"-f".to_string(),
],
];
let output = run_dynamic_commands(temp_dir.path(), &commands);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}
#[test]
fn test_delete_work_success_queue() {
let temp_dir = init_project();
let date = today();
let wi1 = format!("WI-{}-001", date);
let commands: Vec<Vec<String>> = vec![
vec![
"work".to_string(),
"new".to_string(),
"Keep this work item".to_string(),
],
vec![
"work".to_string(),
"new".to_string(),
"Delete this work item".to_string(),
],
vec!["work".to_string(), "list".to_string()],
vec![
"work".to_string(),
"delete".to_string(),
wi1.clone(),
"-f".to_string(),
],
vec!["work".to_string(), "list".to_string()],
vec!["check".to_string()],
];
let output = run_dynamic_commands(temp_dir.path(), &commands);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}
#[test]
fn test_delete_work_safeguard_referenced() {
let temp_dir = init_project();
let date = today();
let wi1 = format!("WI-{}-001", date);
let wi2 = format!("WI-{}-002", date);
let setup_commands: Vec<Vec<String>> = vec![
vec![
"work".to_string(),
"new".to_string(),
"Referenced work item".to_string(),
],
vec![
"work".to_string(),
"new".to_string(),
"Work item with reference".to_string(),
],
vec![
"work".to_string(),
"add".to_string(),
wi2.clone(),
"refs".to_string(),
wi1.clone(),
],
];
let _ = run_dynamic_commands(temp_dir.path(), &setup_commands);
let delete_commands: Vec<Vec<String>> = vec![vec![
"work".to_string(),
"delete".to_string(),
wi1.clone(),
"-f".to_string(),
]];
let output = run_dynamic_commands(temp_dir.path(), &delete_commands);
insta::assert_snapshot!(normalize_output(&output, temp_dir.path(), &date));
}