1use covguard_render::{
7 render_annotations as render_annotations_impl, render_markdown as render_markdown_impl,
8 render_sarif as render_sarif_impl,
9};
10use covguard_types::Report;
11
12pub use covguard_output_features::{
13 DEFAULT_ANNOTATION_LIMIT, DEFAULT_MARKDOWN_LINES, DEFAULT_SARIF_RESULTS, OutputFeatureConfig,
14 OutputFeatureFlags, truncate_findings,
15};
16
17pub fn render_markdown(report: &Report) -> String {
19 render_markdown_with_limit(report, DEFAULT_MARKDOWN_LINES)
20}
21
22pub fn render_markdown_with_limit(report: &Report, max_lines: usize) -> String {
24 render_markdown_impl(report, max_lines)
25}
26
27pub fn render_annotations(report: &Report) -> String {
29 render_annotations_with_limit(report, DEFAULT_ANNOTATION_LIMIT)
30}
31
32pub fn render_annotations_with_limit(report: &Report, max_annotations: usize) -> String {
34 render_annotations_impl(report, max_annotations)
35}
36
37pub fn render_sarif(report: &Report) -> String {
39 render_sarif_with_limit(report, DEFAULT_SARIF_RESULTS)
40}
41
42pub fn render_sarif_with_limit(report: &Report, max_results: usize) -> String {
44 render_sarif_impl(report, max_results)
45}
46
47pub fn render_all(report: &Report, flags: &OutputFeatureFlags) -> (String, String, String) {
49 (
50 render_markdown_with_limit(report, flags.max_markdown_lines),
51 render_annotations_with_limit(report, flags.max_annotations),
52 render_sarif_with_limit(report, flags.max_sarif_results),
53 )
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use covguard_types::Finding;
60
61 #[test]
62 fn test_default_feature_flags() {
63 let flags = OutputFeatureFlags::default();
64 assert_eq!(flags.max_markdown_lines, DEFAULT_MARKDOWN_LINES);
65 assert_eq!(flags.max_annotations, DEFAULT_ANNOTATION_LIMIT);
66 assert_eq!(flags.max_sarif_results, DEFAULT_SARIF_RESULTS);
67 }
68
69 #[test]
70 fn test_output_feature_config_materializes_defaults() {
71 let base = OutputFeatureFlags::default();
72 let config = OutputFeatureConfig {
73 max_markdown_lines: Some(3),
74 max_annotations: None,
75 max_sarif_results: Some(5),
76 };
77 let materialized = config.materialize(base);
78
79 assert_eq!(materialized.max_markdown_lines, 3);
80 assert_eq!(materialized.max_annotations, DEFAULT_ANNOTATION_LIMIT);
81 assert_eq!(materialized.max_sarif_results, 5);
82 }
83
84 #[test]
85 fn test_output_feature_config_full_passthrough() {
86 let base = OutputFeatureFlags::default();
87 let config = OutputFeatureConfig {
88 max_markdown_lines: Some(11),
89 max_annotations: Some(22),
90 max_sarif_results: Some(33),
91 };
92 let materialized = config.materialize(base);
93
94 assert_eq!(materialized.max_markdown_lines, 11);
95 assert_eq!(materialized.max_annotations, 22);
96 assert_eq!(materialized.max_sarif_results, 33);
97 }
98
99 #[test]
100 fn test_truncate_findings_caps_results() {
101 let findings = vec![
102 Finding::uncovered_line("src/lib.rs", 1, 0),
103 Finding::uncovered_line("src/lib.rs", 2, 0),
104 ];
105 let (truncated, trunc) = truncate_findings(findings.clone(), Some(1));
106
107 assert_eq!(truncated.len(), 1);
108 assert!(trunc.is_some());
109 let trunc = trunc.expect("truncation metadata");
110 assert!(trunc.findings_truncated);
111 assert_eq!(trunc.shown, 1);
112 assert_eq!(trunc.total, findings.len() as u32);
113 }
114
115 #[test]
116 fn test_truncate_findings_passthrough_when_under_limit() {
117 let findings = vec![
118 Finding::uncovered_line("src/lib.rs", 1, 0),
119 Finding::uncovered_line("src/lib.rs", 2, 0),
120 ];
121 let (truncated, trunc) = truncate_findings(findings.clone(), Some(5));
122
123 assert_eq!(truncated.len(), findings.len());
124 assert!(trunc.is_none());
125 }
126}