use super::*;
fn row(agent: &str, ts: &str, feedback: &str) -> FeedbackRow {
FeedbackRow {
ts: ts.to_string(),
session_id: Some("sess-1".to_string()),
agent_type: agent.to_string(),
prompt_digest: Some("0123456789abcdef0123".to_string()),
feedback: feedback.to_string(),
}
}
#[test]
fn renders_a_note_when_nothing_is_captured() {
assert_eq!(render(&[], false), "no prompt feedback captured yet\n");
assert_eq!(render(&[], true), "no prompt feedback captured yet\n");
}
#[test]
fn renders_rows_newest_first() {
let rows = vec![
row("engineer", "2026-09-12T11:00:00Z", "second"),
row("qa", "2026-09-12T10:00:00Z", "first"),
];
let out = render(&rows, false);
let second = out.find("second").expect("second present");
let first = out.find("first").expect("first present");
assert!(second < first, "the newest row must render first");
assert!(out.contains("session=sess-1"));
}
#[test]
fn renders_a_short_prompt_digest() {
let out = render(&[row("engineer", "2026-09-12T10:00:00Z", "x")], false);
assert!(out.contains("prompt=0123456789ab"), "got {out}");
assert!(!out.contains("0123456789abcdef0123"));
}
#[test]
fn renders_a_placeholder_for_a_missing_digest() {
let mut r = row("engineer", "2026-09-12T10:00:00Z", "x");
r.prompt_digest = None;
r.session_id = None;
let out = render(&[r], false);
assert!(out.contains("prompt=-"), "got {out}");
assert!(out.contains("session=-"), "got {out}");
}
#[test]
fn renders_a_summary() {
let rows = vec![
row("engineer", "2026-09-12T10:00:00Z", "a"),
row("engineer", "2026-09-12T11:00:00Z", "b"),
row("qa", "2026-09-12T12:00:00Z", "c"),
];
let out = render(&rows, true);
assert!(out.contains(" 2 engineer"), "got {out}");
assert!(out.contains(" 1 qa"), "got {out}");
assert!(out.contains(" 3 total"), "got {out}");
assert!(!out.contains('a'.to_string().as_str()) || !out.contains(" a"));
}
#[test]
fn indents_a_multi_line_body() {
let out = render(
&[row(
"engineer",
"2026-09-12T10:00:00Z",
"line one\nline two",
)],
false,
);
assert!(out.contains(" line one\n"), "got {out}");
assert!(out.contains(" line two\n"), "got {out}");
}
#[test]
fn cli_parses_prompt_feedback() {
use clap::Parser;
let cli = crate::cli::Cli::try_parse_from(["trusty-mpm", "prompt-feedback"]).unwrap();
match cli.command.unwrap() {
crate::cli::Command::PromptFeedback(args) => {
assert_eq!(args.session, None);
assert_eq!(args.agent, None);
assert_eq!(args.limit, 20, "the documented default");
assert!(!args.summary);
}
other => panic!("expected PromptFeedback, got {other:?}"),
}
let cli = crate::cli::Cli::try_parse_from([
"trusty-mpm",
"prompt-feedback",
"--session",
"sess-1",
"--agent",
"rust-engineer",
"--limit",
"3",
])
.unwrap();
match cli.command.unwrap() {
crate::cli::Command::PromptFeedback(args) => {
assert_eq!(args.session.as_deref(), Some("sess-1"));
assert_eq!(args.agent.as_deref(), Some("rust-engineer"));
assert_eq!(args.limit, 3);
}
other => panic!("expected PromptFeedback, got {other:?}"),
}
}
#[test]
fn cli_parses_prompt_feedback_summary() {
use clap::Parser;
let cli = crate::cli::Cli::try_parse_from([
"trusty-mpm",
"prompt-feedback",
"--summary",
"--agent",
"qa",
])
.unwrap();
match cli.command.unwrap() {
crate::cli::Command::PromptFeedback(args) => {
assert!(args.summary);
assert_eq!(args.agent.as_deref(), Some("qa"));
}
other => panic!("expected PromptFeedback, got {other:?}"),
}
}