Skip to main content

muffy_validation/
lib.rs

1//! Document validation.
2
3use muffy_document::html::Element;
4use muffy_validation_macro::html;
5
6html! {}
7
8/// A validation error.
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub enum ValidationError {
11    /// An invalid attribute.
12    InvalidAttribute(String),
13    /// An invalid child.
14    InvalidChild(String),
15    /// An invalid element.
16    InvalidElement(String),
17}
18
19#[cfg(test)]
20mod tests {
21    use super::*;
22    use muffy_document::html::Node;
23    use std::sync::Arc;
24
25    fn create_element(
26        name: &str,
27        attributes: Vec<(&str, &str)>,
28        children: Vec<Element>,
29    ) -> Element {
30        Element::new(
31            name.to_owned(),
32            attributes
33                .into_iter()
34                .map(|(k, v)| (k.to_owned(), v.to_owned()))
35                .collect(),
36            children
37                .into_iter()
38                .map(|e| Arc::new(Node::Element(e)))
39                .collect(),
40        )
41    }
42
43    #[test]
44    fn validate_invalid_element_name() {
45        let element = create_element("invalid", vec![], vec![]);
46
47        assert_eq!(
48            validate_element(&element),
49            Err(ValidationError::InvalidElement("invalid".to_owned()))
50        );
51    }
52
53    mod div {
54        use super::*;
55
56        #[test]
57        fn validate_valid_element() {
58            let element = create_element("div", vec![], vec![]);
59
60            assert_eq!(validate_element(&element), Ok(()));
61        }
62
63        #[test]
64        fn validate_valid_attributes() {
65            let element = create_element("div", vec![("id", "foo"), ("class", "bar")], vec![]);
66
67            assert_eq!(validate_element(&element), Ok(()));
68        }
69
70        #[test]
71        fn validate_invalid_attribute() {
72            let element = create_element("div", vec![("invalid", "foo")], vec![]);
73
74            assert_eq!(
75                validate_element(&element),
76                Err(ValidationError::InvalidAttribute("invalid".to_owned()))
77            );
78        }
79
80        #[test]
81        fn validate_valid_child() {
82            let element = create_element("div", vec![], vec![create_element("p", vec![], vec![])]);
83
84            assert_eq!(validate_element(&element), Ok(()));
85        }
86    }
87
88    mod p {
89        use super::*;
90
91        #[test]
92        fn validate_valid_element() {
93            let element = create_element("p", vec![], vec![]);
94
95            assert_eq!(validate_element(&element), Ok(()));
96        }
97
98        #[test]
99        fn validate_invalid_child() {
100            let element = create_element("p", vec![], vec![create_element("div", vec![], vec![])]);
101
102            assert_eq!(
103                validate_element(&element),
104                Err(ValidationError::InvalidChild("div".to_owned()))
105            );
106        }
107    }
108
109    mod html {
110        use super::*;
111
112        #[test]
113        fn validate_valid_element() {
114            let element = create_element("html", vec![], vec![]);
115
116            assert_eq!(validate_element(&element), Ok(()));
117        }
118
119        #[test]
120        fn validate_valid_children() {
121            let element = create_element(
122                "html",
123                vec![],
124                vec![
125                    create_element("head", vec![], vec![]),
126                    create_element("body", vec![], vec![]),
127                ],
128            );
129
130            assert_eq!(validate_element(&element), Ok(()));
131        }
132    }
133
134    mod head {
135        use super::*;
136
137        #[test]
138        fn validate_valid_child() {
139            let element = create_element(
140                "head",
141                vec![],
142                vec![create_element("title", vec![], vec![])],
143            );
144
145            assert_eq!(validate_element(&element), Ok(()));
146        }
147
148        #[test]
149        fn validate_invalid_child() {
150            let element = create_element("head", vec![], vec![create_element("p", vec![], vec![])]);
151
152            assert_eq!(
153                validate_element(&element),
154                Err(ValidationError::InvalidChild("p".to_owned()))
155            );
156        }
157    }
158
159    mod title {
160        use super::*;
161
162        #[test]
163        fn validate_invalid_child() {
164            let element =
165                create_element("title", vec![], vec![create_element("div", vec![], vec![])]);
166
167            assert_eq!(
168                validate_element(&element),
169                Err(ValidationError::InvalidChild("div".to_owned()))
170            );
171        }
172    }
173
174    mod ul {
175        use super::*;
176
177        #[test]
178        fn validate_valid_child() {
179            let element = create_element("ul", vec![], vec![create_element("li", vec![], vec![])]);
180
181            assert_eq!(validate_element(&element), Ok(()));
182        }
183
184        #[test]
185        fn validate_invalid_child() {
186            let element = create_element("ul", vec![], vec![create_element("p", vec![], vec![])]);
187
188            assert_eq!(
189                validate_element(&element),
190                Err(ValidationError::InvalidChild("p".to_owned()))
191            );
192        }
193    }
194
195    mod table {
196        use super::*;
197
198        #[test]
199        fn validate_valid_child() {
200            let element =
201                create_element("table", vec![], vec![create_element("tr", vec![], vec![])]);
202
203            assert_eq!(validate_element(&element), Ok(()));
204        }
205
206        #[test]
207        fn validate_invalid_child() {
208            let element =
209                create_element("table", vec![], vec![create_element("p", vec![], vec![])]);
210
211            assert_eq!(
212                validate_element(&element),
213                Err(ValidationError::InvalidChild("p".to_owned()))
214            );
215        }
216    }
217
218    mod tr {
219        use super::*;
220
221        #[test]
222        fn validate_valid_children() {
223            let element = create_element(
224                "tr",
225                vec![],
226                vec![
227                    create_element("th", vec![], vec![]),
228                    create_element("td", vec![], vec![]),
229                ],
230            );
231
232            assert_eq!(validate_element(&element), Ok(()));
233        }
234    }
235
236    mod form {
237        use super::*;
238
239        #[test]
240        fn validate_valid_attributes() {
241            let element = create_element("form", vec![("action", "/"), ("method", "post")], vec![]);
242
243            assert_eq!(validate_element(&element), Ok(()));
244        }
245
246        #[test]
247        fn validate_valid_child() {
248            let element = create_element(
249                "form",
250                vec![],
251                vec![create_element("input", vec![], vec![])],
252            );
253
254            assert_eq!(validate_element(&element), Ok(()));
255        }
256    }
257
258    mod img {
259        use super::*;
260
261        #[test]
262        fn validate_valid_attributes() {
263            let element = create_element(
264                "img",
265                vec![("src", "img.png"), ("alt", "description")],
266                vec![],
267            );
268
269            assert_eq!(validate_element(&element), Ok(()));
270        }
271    }
272
273    mod video {
274        use super::*;
275
276        #[test]
277        fn validate_valid_attributes() {
278            let element =
279                create_element("video", vec![("src", "vid.mp4"), ("controls", "")], vec![]);
280
281            assert_eq!(validate_element(&element), Ok(()));
282        }
283
284        #[test]
285        fn validate_valid_child() {
286            let element = create_element(
287                "video",
288                vec![],
289                vec![create_element("track", vec![], vec![])],
290            );
291
292            assert_eq!(validate_element(&element), Ok(()));
293        }
294    }
295
296    mod meta {
297        use super::*;
298
299        #[test]
300        fn validate_valid_name_content() {
301            let element = create_element(
302                "meta",
303                vec![("name", "description"), ("content", "stuff")],
304                vec![],
305            );
306
307            assert_eq!(validate_element(&element), Ok(()));
308        }
309
310        #[test]
311        fn validate_valid_charset() {
312            let element = create_element("meta", vec![("charset", "utf-8")], vec![]);
313
314            assert_eq!(validate_element(&element), Ok(()));
315        }
316    }
317
318    mod link {
319        use super::*;
320
321        #[test]
322        fn validate_valid_attributes() {
323            let element = create_element(
324                "link",
325                vec![("rel", "stylesheet"), ("href", "style.css")],
326                vec![],
327            );
328
329            assert_eq!(validate_element(&element), Ok(()));
330        }
331    }
332}