garbage_code_hunter/trend/
mod.rs1pub mod display;
6pub mod history;
7
8use anyhow::Result;
9use history::{HistoryRecord, ToolScore};
10
11pub use crate::common::OutputFormat;
12
13pub fn run(last_n: usize, format: &OutputFormat) -> Result<String> {
15 let records = history::load_last(last_n)?;
16
17 let output = match format {
18 OutputFormat::Terminal => display::format_terminal(&records, last_n),
19 OutputFormat::Json => display::format_json(&records),
20 };
21
22 Ok(output)
23}
24
25pub fn save_scan(
27 project_path: &str,
28 overall_score: f64,
29 tools: Vec<ToolScore>,
30) -> Result<history::HistoryRecord> {
31 let record = HistoryRecord {
32 timestamp: history::now_timestamp(),
33 project_path: project_path.to_string(),
34 overall_score,
35 tools,
36 };
37 history::save(&record)?;
38 Ok(record)
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_run_empty_history() {
47 let result = run(10, &OutputFormat::Terminal);
49 assert!(result.is_ok());
50 }
51
52 #[test]
53 fn test_save_and_load() {
54 let tools = vec![
55 ToolScore {
56 name: "code-hunter".to_string(),
57 score: 75.0,
58 item_count: 20,
59 },
60 ToolScore {
61 name: "commit-roaster".to_string(),
62 score: 85.0,
63 item_count: 50,
64 },
65 ];
66 let record = save_scan("/tmp/test-project", 80.0, tools).unwrap();
67 assert_eq!(record.overall_score, 80.0);
68 assert_eq!(record.tools.len(), 2);
69
70 let records = history::load_all().unwrap();
72 assert!(records
73 .iter()
74 .any(|r| r.project_path == "/tmp/test-project"));
75 }
76}