mockforge_reporting/
lib.rs

1//! MockForge Reporting
2//!
3//! Comprehensive reporting capabilities including PDF generation,
4//! email notifications, trend analysis, comparison reports, CSV export,
5//! flamegraph visualization, and custom dashboard layouts.
6
7pub mod comparison;
8pub mod csv_export;
9pub mod dashboard_layouts;
10pub mod email;
11pub mod flamegraph;
12pub mod pdf;
13pub mod trend_analysis;
14
15pub use comparison::{ComparisonReport, ComparisonReportGenerator};
16pub use csv_export::{CsvBatchExporter, CsvExportConfig, CsvExporter};
17pub use dashboard_layouts::{
18    DashboardLayout, DashboardLayoutBuilder, DashboardLayoutManager, DashboardTemplates,
19    DataSource, GridConfig, Widget, WidgetType,
20};
21pub use email::{EmailConfig, EmailNotifier, EmailReport};
22pub use flamegraph::{FlamegraphGenerator, FlamegraphStats, TraceData, TraceSpan};
23pub use pdf::{PdfConfig, PdfReportGenerator};
24pub use trend_analysis::{TrendAnalyzer, TrendDirection, TrendReport};
25
26use thiserror::Error;
27
28#[derive(Error, Debug)]
29pub enum ReportingError {
30    #[error("PDF generation error: {0}")]
31    Pdf(String),
32
33    #[error("Email sending error: {0}")]
34    Email(String),
35
36    #[error("Analysis error: {0}")]
37    Analysis(String),
38
39    #[error("IO error: {0}")]
40    Io(#[from] std::io::Error),
41
42    #[error("Serialization error: {0}")]
43    Serialization(#[from] serde_json::Error),
44}
45
46pub type Result<T> = std::result::Result<T, ReportingError>;
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_reporting_error_pdf() {
54        let error = ReportingError::Pdf("font not found".to_string());
55        assert_eq!(error.to_string(), "PDF generation error: font not found");
56    }
57
58    #[test]
59    fn test_reporting_error_email() {
60        let error = ReportingError::Email("SMTP connection failed".to_string());
61        assert_eq!(error.to_string(), "Email sending error: SMTP connection failed");
62    }
63
64    #[test]
65    fn test_reporting_error_analysis() {
66        let error = ReportingError::Analysis("insufficient data".to_string());
67        assert_eq!(error.to_string(), "Analysis error: insufficient data");
68    }
69
70    #[test]
71    fn test_reporting_error_from_io() {
72        let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
73        let error: ReportingError = io_error.into();
74        assert!(matches!(error, ReportingError::Io(_)));
75        assert!(error.to_string().contains("IO error"));
76    }
77
78    #[test]
79    fn test_reporting_error_from_serde_json() {
80        let json_error = serde_json::from_str::<serde_json::Value>("invalid").unwrap_err();
81        let error: ReportingError = json_error.into();
82        assert!(matches!(error, ReportingError::Serialization(_)));
83        assert!(error.to_string().contains("Serialization error"));
84    }
85
86    #[test]
87    fn test_reporting_error_debug() {
88        let error = ReportingError::Pdf("test".to_string());
89        let debug = format!("{:?}", error);
90        assert!(debug.contains("Pdf"));
91    }
92
93    #[test]
94    fn test_result_ok() {
95        let result: Result<i32> = Ok(42);
96        assert!(result.is_ok());
97        assert_eq!(result.unwrap(), 42);
98    }
99
100    #[test]
101    fn test_result_err() {
102        let result: Result<i32> = Err(ReportingError::Pdf("test".to_string()));
103        assert!(result.is_err());
104    }
105}