use super::*;
const FOOTER: &str = "🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools";
fn full_stats() -> CommitStats {
CommitStats {
tokens_in: Some(1_234_567),
tokens_out: Some(8_901),
tokens_window_bytes: None,
savings_percent: Some(42),
model_id: Some("claude-opus-4-1-20250805".to_string()),
}
}
fn message_with_footer() -> String {
format!(
"feat(trusty-mpm): a thing (Refs #7074)\n\nWhat changed and why.\n\n{FOOTER}\nClaude-Session: https://claude.ai/code/session_01\n"
)
}
#[test]
fn render_omits_absent_fields() {
let stats = CommitStats {
tokens_in: Some(10),
tokens_out: None,
tokens_window_bytes: None,
savings_percent: Some(7),
model_id: None,
};
assert_eq!(
render_trailers(&stats).as_deref(),
Some("Tokens-In: 10\nSavings: 7%")
);
}
#[test]
fn render_states_the_window_when_the_fold_was_truncated() {
let stats = CommitStats {
tokens_in: Some(10),
tokens_out: Some(4),
tokens_window_bytes: Some(8 * 1024 * 1024),
..CommitStats::default()
};
assert_eq!(
render_trailers(&stats).as_deref(),
Some("Tokens-In: 10\nTokens-Out: 4\nTokens-Window: last 8 MiB of a larger transcript")
);
}
#[test]
fn render_omits_the_window_when_the_fold_read_everything() {
let whole = CommitStats {
tokens_in: Some(10),
tokens_window_bytes: None,
..CommitStats::default()
};
assert_eq!(render_trailers(&whole).as_deref(), Some("Tokens-In: 10"));
let window_only = CommitStats {
tokens_window_bytes: Some(8 * 1024 * 1024),
savings_percent: Some(7),
..CommitStats::default()
};
assert_eq!(
render_trailers(&window_only).as_deref(),
Some("Savings: 7%")
);
}
#[test]
fn window_label_falls_back_to_bytes_off_a_mib_boundary() {
assert_eq!(window_label(1500), "last 1500 bytes of a larger transcript");
assert_eq!(
window_label(3 * 1024 * 1024),
"last 3 MiB of a larger transcript"
);
}
#[test]
fn render_is_none_when_nothing_is_known() {
assert_eq!(render_trailers(&CommitStats::default()), None);
assert!(CommitStats::default().is_empty());
}
#[test]
fn render_rejects_a_multiline_model_id() {
let stats = CommitStats {
model_id: Some("claude-opus\nSavings: 99%".to_string()),
..CommitStats::default()
};
assert_eq!(render_trailers(&stats), None);
}
#[test]
fn git_interpret_trailers_parses_the_appended_block() {
let trailers = render_trailers(&full_stats()).expect("trailers");
let message = append_trailers(&message_with_footer(), &trailers);
let dir = tempfile::tempdir().expect("temp dir");
let path = dir.path().join("COMMIT_EDITMSG");
std::fs::write(&path, &message).expect("write message");
let out = std::process::Command::new("git")
.args(["interpret-trailers", "--parse"])
.arg(&path)
.output()
.expect("run git interpret-trailers");
assert!(out.status.success(), "git interpret-trailers failed");
let parsed = String::from_utf8_lossy(&out.stdout);
for expected in [
"Tokens-In: 1234567",
"Tokens-Out: 8901",
"Savings: 42%",
"Model: claude-opus-4-1-20250805",
] {
assert!(
parsed.lines().any(|line| line == expected),
"git did not parse `{expected}` out of:\n{message}\n--- parsed ---\n{parsed}"
);
}
}
#[test]
fn append_goes_above_a_trailing_comment_block() {
let message = format!(
"feat: x\n\n{FOOTER}\n\n# Please enter the commit message for your changes.\n# On branch main\n"
);
let out = append_trailers(&message, "Tokens-In: 5");
let lines: Vec<&str> = out.lines().collect();
let trailer_at = lines
.iter()
.position(|l| *l == "Tokens-In: 5")
.expect("trailer present");
let comment_at = lines
.iter()
.position(|l| l.starts_with("# Please enter"))
.expect("comment present");
assert!(
trailer_at < comment_at,
"the trailer must sit above the comment block:\n{out}"
);
assert_eq!(lines[trailer_at - 1], "", "one blank line above the block");
}
#[test]
fn append_stays_above_the_scissors_line() {
let message = format!(
"feat: x\n\n{FOOTER}\n\n{SCISSORS}\n# Do not modify or remove the line above.\ndiff --git a/x b/x\n+Tokens-In: 999\n"
);
let out = append_trailers(&message, "Tokens-In: 5");
let lines: Vec<&str> = out.lines().collect();
let trailer_at = lines
.iter()
.position(|l| *l == "Tokens-In: 5")
.expect("trailer present");
let scissors_at = lines
.iter()
.position(|l| *l == SCISSORS)
.expect("scissors present");
assert!(
trailer_at < scissors_at,
"trailer below the scissors:\n{out}"
);
}
#[test]
fn append_is_idempotent() {
let trailers = render_trailers(&full_stats()).expect("trailers");
let once = append_trailers(&message_with_footer(), &trailers);
let twice = append_trailers(&once, &trailers);
assert_eq!(once, twice);
assert_eq!(
twice.matches("Tokens-In:").count(),
1,
"exactly one stats block"
);
}
#[test]
fn append_preserves_the_attribution_footer() {
let trailers = render_trailers(&full_stats()).expect("trailers");
let out = append_trailers(&message_with_footer(), &trailers);
assert!(out.contains(FOOTER), "attribution footer lost:\n{out}");
assert!(
out.contains("Claude-Session: https://claude.ai/code/session_01"),
"session link lost:\n{out}"
);
}
#[test]
fn stamp_policy_skips_merge_and_squash() {
assert_eq!(stamp_policy("merge"), StampPolicy::Skip);
assert_eq!(stamp_policy("squash"), StampPolicy::Skip);
}
#[test]
fn stamp_policy_restamps_a_reused_message() {
assert_eq!(stamp_policy("commit"), StampPolicy::Restamp);
}
#[test]
fn stamp_policy_stamps_a_new_message() {
assert_eq!(stamp_policy(""), StampPolicy::Stamp);
assert_eq!(stamp_policy("message"), StampPolicy::Stamp);
assert_eq!(stamp_policy("template"), StampPolicy::Stamp);
assert_eq!(stamp_policy("something-git-adds-later"), StampPolicy::Stamp);
}
#[test]
fn strip_removes_an_inherited_block() {
let stamped = append_trailers(
&message_with_footer(),
&render_trailers(&full_stats()).expect("trailers"),
);
let stripped = strip_trailers(&stamped);
assert_eq!(stripped, message_with_footer(), "{stripped}");
}
#[test]
fn strip_leaves_a_message_that_has_none() {
assert_eq!(
strip_trailers(&message_with_footer()),
message_with_footer()
);
}
#[test]
fn strip_keeps_a_trailing_comment_block() {
let message = "feat: x\n\nTokens-In: 5\nSavings: 3%\n\n# Please enter the commit message.\n#\n";
assert_eq!(
strip_trailers(message),
"feat: x\n\n# Please enter the commit message.\n#\n"
);
}
#[test]
fn strip_leaves_a_paragraph_that_is_not_only_trailers() {
let message = "feat: x\n\nModel: the T-800 is not a trailer.\nIt sits in prose.\n";
assert_eq!(strip_trailers(message), message);
}