//! Dashboard TUI data + non-TUI modes (issue #33). mod common; use agent_manager::commands::dashboard_cmd; use agent_manager::dashboard; use agent_manager::state::InstalledEntry; fn install(app: &agent_manager::app::App, name: &str, pid: Option) { let entry = InstalledEntry { name: name.to_string(), version: Some("1.0.0".to_string()), method: "npm".to_string(), install_dir: format!("/tmp/{name}"), bins: vec![], run: name.to_string(), installed_at: "2026-08-01T00:00:00Z".to_string(), updated_at: None, pid, started_at: pid.map(|_| chrono::Utc::now().to_rfc3339()), }; app.state.set(&entry).unwrap(); } #[test] fn dashboard_collects_overview_and_counts() { let app = common::test_app("dash", &["dashboard"]); install(&app, "claude-code", Some(4242)); let data = dashboard::collect(&app); assert_eq!(data.counts.installed, 1); assert_eq!(data.counts.running, 0, "pid 4242 is not a live process here"); let row = data.overview.iter().find(|r| r.name == "claude-code").unwrap(); assert_eq!(row.status, "installed"); assert_eq!(row.version.as_deref(), Some("1.0.0")); } #[test] fn dashboard_never_blocks_on_an_empty_journal() { let app = common::test_app("dashempty", &["dashboard"]); let data = dashboard::collect(&app); assert!(data.activity.is_empty()); assert!(data.stats.is_empty()); assert!(data.sessions.is_empty()); assert!(data.projects.is_empty()); } #[test] fn dashboard_piped_and_json_modes_return_ok() { let app = common::test_app("dashpipe", &["dashboard"]); // In tests stdout is not a terminal: the plain snapshot path runs. assert_eq!(dashboard_cmd::run(&app).unwrap(), 0); // JSON mode prints the whole snapshot as one document. let app = common::test_app("dashjson", &["dashboard", "--json"]); assert_eq!(dashboard_cmd::run(&app).unwrap(), 0); } #[test] fn dashboard_follows_the_journal() { let app = common::test_app("dashlog", &["dashboard"]); 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, concat!( "{\"ts\":\"2026-08-01T10:00:00Z\",\"kind\":\"run\",\"agent\":\"a\",\"exit_code\":0}\n", "{\"ts\":\"2026-08-02T10:00:00Z\",\"kind\":\"install\",\"agent\":\"b\"}\n", ), ) .unwrap(); let data = dashboard::collect(&app); assert_eq!(data.activity.len(), 2); assert_eq!(data.activity[0].kind, "install", "newest first"); assert_eq!(data.stats.len(), 2, "journal feeds the stats tab"); }