Files
agent-manager/tests/projects_test.rs
T

93 lines
3.5 KiB
Rust

//! projects: aggregation from the journal, profiles from the config.
mod common;
use agent_manager::commands::projects_cmd;
use agent_manager::projects;
#[test]
fn aggregates_projects_from_fixture_events() {
let app = common::test_app("proj", &["projects"]);
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();
std::fs::write(
&path,
[
r#"{"ts":"2026-08-01T10:00:00Z","kind":"run","agent":"claude-code","project":"/home/x/api","session":"s1","duration_s":10,"exit_code":0}"#,
r#"{"ts":"2026-08-02T10:00:00Z","kind":"run","agent":"claude-code","project":"/home/x/api","session":"s2","duration_s":20,"exit_code":0}"#,
r#"{"ts":"2026-08-03T10:00:00Z","kind":"run","agent":"aider","project":"/home/x/api","session":"s3","duration_s":5,"exit_code":0}"#,
r#"{"ts":"2026-08-04T10:00:00Z","kind":"run","agent":"smelt","project":"/home/x/rusty","session":"s4","duration_s":7,"exit_code":0}"#,
]
.join("
"),
)
.unwrap();
let out = projects::aggregate(&app);
assert_eq!(out.len(), 2);
let api = out.iter().find(|s| s.root == "/home/x/api").unwrap();
assert_eq!(api.agents, vec!["aider".to_string(), "claude-code".to_string()]);
assert_eq!(api.dominant.as_deref(), Some("claude-code"));
assert_eq!(api.sessions, 3);
assert_eq!(api.launches, 3);
assert_eq!(api.total_duration_s, 35);
assert!(projects::cache_file(&app).exists());
// La commande tourne (table + detail).
assert_eq!(projects_cmd::run(&app, None).unwrap(), 0);
assert_eq!(projects_cmd::run(&app, Some("api")).unwrap(), 0);
assert!(projects_cmd::run(&app, Some("inconnu")).is_err());
}
#[test]
fn profile_config_parses_and_resolves() {
let dir = std::env::temp_dir().join(format!("am-prof-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let root = dir.join("api");
std::fs::create_dir_all(&root).unwrap();
let cfg = common::write_config(
&dir,
&format!(
r#"
projects:
api:
root: '{}'
default_agent: claude-code
env:
FOO: bar
"#,
root.display()
),
);
use agent_manager::cli::Cli;
use clap::Parser;
let cli = Cli::parse_from(["am", "--config", cfg.to_str().unwrap(), "projects"]);
let mut app = agent_manager::app::App::from_cli(cli).unwrap();
common::isolate(&mut app, &dir);
assert_eq!(app.config.projects.len(), 1);
let sub = root.join("src");
std::fs::create_dir_all(&sub).unwrap();
let (name, profile) = projects::profile_for(&app, &sub).unwrap();
assert_eq!(name, "api");
assert_eq!(profile.default_agent.as_deref(), Some("claude-code"));
assert_eq!(
projects::default_agent_for_dir(&app, &sub).as_deref(),
Some("claude-code")
);
// Hors du projet : pas de profil.
assert!(projects::default_agent_for_dir(&app, &std::env::temp_dir()).is_none());
// am start contextuel (issue #30) : résolution pure sans changer de cwd.
use agent_manager::commands::run_cmd;
assert_eq!(
run_cmd::resolve_start_target(&app, &sub, None).unwrap(),
"claude-code"
);
assert_eq!(
run_cmd::resolve_start_target(&app, &sub, Some("aider")).unwrap(),
"aider"
);
assert!(run_cmd::resolve_start_target(&app, &std::env::temp_dir(), None).is_err());
let _ = std::fs::remove_dir_all(&dir);
}