Skip to main content

jscpd_rs/report/
threshold.rs

1use std::error::Error;
2use std::fmt;
3
4use anyhow::Result;
5
6use crate::cli::Options;
7use crate::detector::DetectionResult;
8
9pub(super) fn write(result: &DetectionResult, options: &Options) -> Result<()> {
10    let Some(threshold) = options.threshold else {
11        return Ok(());
12    };
13    if threshold < result.statistics.total.percentage {
14        return Err(ThresholdExceeded::new(format!(
15            "ERROR: jscpd found too many duplicates ({}%) over threshold ({}%)",
16            result.statistics.total.percentage, threshold,
17        ))
18        .into());
19    }
20    Ok(())
21}
22
23#[derive(Debug)]
24pub struct ThresholdExceeded {
25    message: String,
26}
27
28impl ThresholdExceeded {
29    fn new(message: String) -> Self {
30        Self { message }
31    }
32
33    pub fn message(&self) -> &str {
34        &self.message
35    }
36}
37
38impl fmt::Display for ThresholdExceeded {
39    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
40        formatter.write_str(&self.message)
41    }
42}
43
44impl Error for ThresholdExceeded {}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::report::test_support::make_test_result_with_clone;
50    use crate::report::write_reports;
51
52    #[test]
53    fn threshold_reporter_uses_strictly_greater_percentage_like_upstream() {
54        let mut result = make_test_result_with_clone("src/a.js", "src/b.js");
55        result.statistics.total.percentage = 25.0;
56
57        let equal = Options {
58            threshold: Some(25.0),
59            reporters: vec!["threshold".to_string()],
60            ..Options::default()
61        };
62        assert!(write_reports(&result, &equal).is_ok());
63
64        let below = Options {
65            threshold: Some(24.9),
66            reporters: vec!["threshold".to_string()],
67            ..Options::default()
68        };
69        let error = write_reports(&result, &below).unwrap_err();
70        assert!(error.downcast_ref::<ThresholdExceeded>().is_some());
71        assert_eq!(
72            error.to_string(),
73            "ERROR: jscpd found too many duplicates (25%) over threshold (24.9%)"
74        );
75    }
76}