Skip to main content

muffy_validation/
lib.rs

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