Files
agent-manager/tests/top_report_test.rs
T

101 lines
3.4 KiB
Rust

//! top, report and log --follow (issues #37 #38).
mod common;
use agent_manager::commands::stats_cmd;
use agent_manager::events;
fn app_with_events(tag: &str, lines: &[&str]) -> agent_manager::app::App {
let app = common::test_app(tag, &["stats"]);
let month = chrono::Utc::now().format("%Y%m").to_string();
let path = app.events_dir().join(format!("events-{month}.jsonl"));
std::fs::create_dir_all(app.events_dir()).unwrap();
let mut text = String::new();
for l in lines {
text.push_str(l);
text.push('\n');
}
std::fs::write(&path, text).unwrap();
app
}
#[test]
fn top_sorts_by_launches() {
let app = app_with_events(
"top",
&[
r#"{"ts":"2026-08-01T10:00:00Z","kind":"run","agent":"a","exit_code":0}"#,
r#"{"ts":"2026-08-02T10:00:00Z","kind":"run","agent":"a","exit_code":0}"#,
r#"{"ts":"2026-08-03T10:00:00Z","kind":"run","agent":"b","exit_code":0}"#,
],
);
let rows = stats_cmd::top(&app, None).unwrap();
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].agent, "a");
assert_eq!(rows[0].launches, 2);
}
#[test]
fn report_md_contains_numbers_and_table() {
let today = chrono::Utc::now().format("%Y-%m-%d").to_string();
let lines = [
format!(r#"{{"ts":"{today}T10:00:00Z","kind":"run","agent":"a","exit_code":0,"duration_s":10}}"#),
format!(r#"{{"ts":"{today}T10:01:00Z","kind":"run","agent":"a","exit_code":1,"duration_s":5}}"#),
format!(r#"{{"ts":"{today}T10:02:00Z","kind":"install","agent":"b"}}"#),
];
let refs: Vec<&str> = lines.iter().map(|s| s.as_str()).collect();
let app = app_with_events("report", &refs);
// Issue #74: the report follows the app language; force French so the
// assertions are deterministic whatever the host LANG says.
app.set_lang(agent_manager::i18n::Lang::Fr);
let md = stats_cmd::report_md(&app, 7);
assert!(md.contains("# Rapport agent-manager"), "md: {md}");
assert!(md.contains("Lancements : 2"));
assert!(md.contains("Échecs : 1"));
assert!(md.contains("Changements"));
assert!(md.contains("| a | 2 |"), "table top: {md}");
}
#[test]
fn report_command_writes_file() {
let app = app_with_events("reportcmd", &[]);
let out = app.events_dir().join("report-test.md");
let code = stats_cmd::run_report(&app, true, false, Some(&out)).unwrap();
assert_eq!(code, 0);
assert!(out.exists());
let _ = std::fs::remove_file(&out);
}
#[test]
fn text_after_is_utf8_safe() {
use agent_manager::commands::log_cmd;
let text = "héllo wörld
second line
";
assert_eq!(log_cmd::text_after(text, 0), text);
assert_eq!(log_cmd::text_after(text, 3), "llo wörld
second line
");
let full = text.len();
assert_eq!(log_cmd::text_after(text, full), "");
}
#[test]
fn follow_flag_parses() {
use agent_manager::cli::{Cli, Command};
use clap::Parser;
let cli = Cli::parse_from(["am", "log", "--follow"]);
match &cli.command {
Some(Command::Log { follow, .. }) => assert!(*follow),
other => panic!("unexpected: {other:?}"),
}
}
#[test]
fn journal_still_reads_after_events_api() {
let app = app_with_events("api", &[]);
let mut log = events::EventLog::new(app.events_dir());
log.append(&events::Event::now(events::EventKind::Run).with_agent("x")).unwrap();
assert_eq!(events::read_events(&app.events_dir(), 0).len(), 1);
}