commitlint_rs/rule/
body_max_length.rs

1use crate::{message::Message, result::Violation, rule::Rule};
2use serde::{Deserialize, Serialize};
3
4use super::Level;
5
6/// BodyMaxLength represents the body-max-length rule.
7#[derive(Clone, Debug, Deserialize, Serialize)]
8#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
9pub struct BodyMaxLength {
10    /// Level represents the level of the rule.
11    ///
12    // Note that currently the default literal is not supported.
13    // See: https://github.com/serde-rs/serde/issues/368
14    level: Option<Level>,
15
16    /// Length represents the maximum length of the body.
17    length: usize,
18}
19
20/// BodyMaxLength represents the body-max-length rule.
21impl Rule for BodyMaxLength {
22    const NAME: &'static str = "body-max-length";
23    const LEVEL: Level = Level::Error;
24
25    fn message(&self, _message: &Message) -> String {
26        format!("body is longer than {} characters", self.length)
27    }
28
29    fn validate(&self, message: &Message) -> Option<Violation> {
30        if let Some(body) = &message.body {
31            if body.len() >= self.length {
32                return Some(Violation {
33                    level: self.level.unwrap_or(Self::LEVEL),
34                    message: self.message(message),
35                });
36            }
37        }
38
39        None
40    }
41}
42
43/// Default implementation of BodyMaxLength.
44impl Default for BodyMaxLength {
45    fn default() -> Self {
46        Self {
47            level: Some(Self::LEVEL),
48            length: 72,
49        }
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_long_body() {
59        let rule = BodyMaxLength {
60            length: usize::MAX, // Long length for testing
61            ..Default::default()
62        };
63        let message = Message {
64            body: Some("Hello world".to_string()),
65            description: Some("broadcast $destroy event on scope destruction".to_string()),
66            footers: None,
67            r#type: Some("feat".to_string()),
68            raw: "feat(scope): broadcast $destroy event on scope destruction
69
70Hey!"
71                .to_string(),
72            scope: Some("scope".to_string()),
73            subject: Some("feat(scope): broadcast $destroy event on scope destruction".to_string()),
74        };
75
76        assert!(rule.validate(&message).is_none());
77    }
78
79    #[test]
80    fn test_no_body() {
81        let rule = BodyMaxLength {
82            length: usize::MAX, // Long length for testing
83            ..Default::default()
84        };
85        let message = Message {
86            body: None,
87            description: Some("broadcast $destroy event on scope destruction".to_string()),
88            footers: None,
89            r#type: Some("feat".to_string()),
90            raw: "feat(scope): broadcast $destroy event on scope destruction".to_string(),
91            scope: Some("scope".to_string()),
92            subject: Some("feat(scope): broadcast $destroy event on scope destruction".to_string()),
93        };
94
95        assert!(rule.validate(&message).is_none());
96    }
97
98    #[test]
99    fn test_short_body() {
100        let rule = BodyMaxLength {
101            length: 10, // Short length for testing
102            ..Default::default()
103        };
104        let message = Message {
105            body: Some("Hello, I'm a long body".to_string()),
106            description: None,
107            footers: None,
108            r#type: Some("feat".to_string()),
109            raw: "feat(scope): broadcast $destroy event on scope destruction
110
111Hello, I'm a long body"
112                .to_string(),
113            scope: Some("scope".to_string()),
114            subject: None,
115        };
116
117        let violation = rule.validate(&message);
118        assert!(violation.is_some());
119        assert_eq!(violation.clone().unwrap().level, Level::Error);
120        assert_eq!(
121            violation.unwrap().message,
122            format!("body is longer than {} characters", rule.length)
123        );
124    }
125}