1// Copyright (c) 2020 lumi <lumi@pew.im>
2// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
3// Copyright (c) 2020 Bastien Orivel <eijebong+minidom@bananium.fr>
4// Copyright (c) 2020 Astro <astro@spaceboyz.net>
5// Copyright (c) 2020 Maxime “pep” Buquet <pep@bouah.net>
6// Copyright (c) 2020 Yue Liu <amznyue@amazon.com>
7// Copyright (c) 2020 Matt Bilker <me@mbilker.us>
8//
9// This Source Code Form is subject to the terms of the Mozilla Public
10// License, v. 2.0. If a copy of the MPL was not distributed with this
11// file, You can obtain one at http://mozilla.org/MPL/2.0/.
12
13use crate::element::Element;
14
15use quick_xml::Reader;
16
17const TEST_STRING: &'static str = r#"<root xmlns="root_ns" a="b" xml:lang="en">meow<child c="d"/><child xmlns="child_ns" d="e" xml:lang="fr"/>nya</root>"#;
18
19fn build_test_tree() -> Element {
20 let mut root = Element::builder("root")
21 .ns("root_ns")
22 .attr("xml:lang", "en")
23 .attr("a", "b")
24 .build();
25 root.append_text_node("meow");
26 let child = Element::builder("child").attr("c", "d").build();
27 root.append_child(child);
28 let other_child = Element::builder("child")
29 .ns("child_ns")
30 .attr("d", "e")
31 .attr("xml:lang", "fr")
32 .build();
33 root.append_child(other_child);
34 root.append_text_node("nya");
35 root
36}
37
38#[cfg(feature = "comments")]
39const COMMENT_TEST_STRING: &'static str = r#"<root><!--This is a child.--><child attr="val"><!--This is a grandchild.--><grandchild/></child></root>"#;
40
41#[cfg(feature = "comments")]
42fn build_comment_test_tree() -> Element {
43 let mut root = Element::builder("root").build();
44 root.append_comment_node("This is a child.");
45 let mut child = Element::builder("child").attr("attr", "val").build();
46 child.append_comment_node("This is a grandchild.");
47 let grand_child = Element::builder("grandchild").build();
48 child.append_child(grand_child);
49 root.append_child(child);
50 root
51}
52
53#[test]
54fn reader_works() {
55 let mut reader = Reader::from_str(TEST_STRING);
56 assert_eq!(
57 Element::from_reader(&mut reader).unwrap(),
58 build_test_tree()
59 );
60}
61
62#[test]
63fn writer_works() {
64 let root = build_test_tree();
65 let mut writer = Vec::new();
66 {
67 root.write_to(&mut writer).unwrap();
68 }
69 assert_eq!(String::from_utf8(writer).unwrap(), TEST_STRING);
70}
71
72#[test]
73fn writer_with_decl_works() {
74 let root = build_test_tree();
75 let mut writer = Vec::new();
76 {
77 root.write_to_decl(&mut writer).unwrap();
78 }
79 let result = format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, TEST_STRING);
80 assert_eq!(String::from_utf8(writer).unwrap(), result);
81}
82
83#[test]
84fn writer_escapes_attributes() {
85 let root = Element::builder("root").attr("a", "\"Air\" quotes").build();
86 let mut writer = Vec::new();
87 {
88 root.write_to(&mut writer).unwrap();
89 }
90 assert_eq!(
91 String::from_utf8(writer).unwrap(),
92 r#"<root a=""Air" quotes"/>"#
93 );
94}
95
96#[test]
97fn writer_escapes_text() {
98 let root = Element::builder("root").append("<3").build();
99 let mut writer = Vec::new();
100 {
101 root.write_to(&mut writer).unwrap();
102 }
103 assert_eq!(String::from_utf8(writer).unwrap(), r#"<root><3</root>"#);
104}
105
106#[test]
107fn builder_works() {
108 let elem = Element::builder("a")
109 .ns("b")
110 .attr("c", "d")
111 .append(Element::builder("child"))
112 .append("e")
113 .build();
114 assert_eq!(elem.name(), "a");
115 assert_eq!(elem.ns(), Some("b".to_owned()));
116 assert_eq!(elem.attr("c"), Some("d"));
117 assert_eq!(elem.attr("x"), None);
118 assert_eq!(elem.text(), "e");
119 assert!(elem.has_child("child", "b"));
120 assert!(elem.is("a", "b"));
121}
122
123#[test]
124fn children_iter_works() {
125 let root = build_test_tree();
126 let mut iter = root.children();
127 assert!(iter.next().unwrap().is("child", "root_ns"));
128 assert!(iter.next().unwrap().is("child", "child_ns"));
129 assert_eq!(iter.next(), None);
130}
131
132#[test]
133fn get_child_works() {
134 let root = build_test_tree();
135 assert_eq!(root.get_child("child", "inexistent_ns"), None);
136 assert_eq!(root.get_child("not_a_child", "root_ns"), None);
137 assert!(root
138 .get_child("child", "root_ns")
139 .unwrap()
140 .is("child", "root_ns"));
141 assert!(root
142 .get_child("child", "child_ns")
143 .unwrap()
144 .is("child", "child_ns"));
145 assert_eq!(
146 root.get_child("child", "root_ns").unwrap().attr("c"),
147 Some("d")
148 );
149 assert_eq!(
150 root.get_child("child", "child_ns").unwrap().attr("d"),
151 Some("e")
152 );
153}
154
155#[test]
156fn namespace_propagation_works() {
157 let mut root = Element::builder("root").ns("root_ns").build();
158 let mut child = Element::bare("child");
159 let grandchild = Element::bare("grandchild");
160 child.append_child(grandchild);
161 root.append_child(child);
162
163 assert_eq!(root.get_child("child", "root_ns").unwrap().ns(), root.ns());
164 assert_eq!(
165 root.get_child("child", "root_ns")
166 .unwrap()
167 .get_child("grandchild", "root_ns")
168 .unwrap()
169 .ns(),
170 root.ns()
171 );
172}
173
174#[test]
175fn two_elements_with_same_arguments_different_order_are_equal() {
176 let elem1: Element = "<a b='a' c=''/>".parse().unwrap();
177 let elem2: Element = "<a c='' b='a'/>".parse().unwrap();
178 assert_eq!(elem1, elem2);
179
180 let elem1: Element = "<a b='a' c=''/>".parse().unwrap();
181 let elem2: Element = "<a c='d' b='a'/>".parse().unwrap();
182 assert_ne!(elem1, elem2);
183}
184
185#[test]
186fn namespace_attributes_works() {
187 let mut reader = Reader::from_str(TEST_STRING);
188 let root = Element::from_reader(&mut reader).unwrap();
189 assert_eq!("en", root.attr("xml:lang").unwrap());
190 assert_eq!(
191 "fr",
192 root.get_child("child", "child_ns")
193 .unwrap()
194 .attr("xml:lang")
195 .unwrap()
196 );
197}
198
199#[test]
200fn wrongly_closed_elements_error() {
201 let elem1 = "<a></b>".parse::<Element>();
202 assert!(elem1.is_err());
203 let elem1 = "<a></c></a>".parse::<Element>();
204 assert!(elem1.is_err());
205 let elem1 = "<a><c><d/></c></a>".parse::<Element>();
206 assert!(elem1.is_ok());
207}
208
209#[test]
210fn namespace_simple() {
211 let elem: Element = "<message xmlns='jabber:client'/>".parse().unwrap();
212 assert_eq!(elem.name(), "message");
213 assert_eq!(elem.ns(), Some("jabber:client".to_owned()));
214}
215
216#[test]
217fn namespace_prefixed() {
218 let elem: Element = "<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>"
219 .parse()
220 .unwrap();
221 assert_eq!(elem.name(), "features");
222 assert_eq!(
223 elem.ns(),
224 Some("http://etherx.jabber.org/streams".to_owned())
225 );
226}
227
228#[test]
229fn namespace_inherited_simple() {
230 let elem: Element = "<stream xmlns='jabber:client'><message/></stream>"
231 .parse()
232 .unwrap();
233 assert_eq!(elem.name(), "stream");
234 assert_eq!(elem.ns(), Some("jabber:client".to_owned()));
235 let child = elem.children().next().unwrap();
236 assert_eq!(child.name(), "message");
237 assert_eq!(child.ns(), Some("jabber:client".to_owned()));
238}
239
240#[test]
241fn namespace_inherited_prefixed1() {
242 let elem: Element = "<stream:features xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'><message/></stream:features>"
243 .parse().unwrap();
244 assert_eq!(elem.name(), "features");
245 assert_eq!(
246 elem.ns(),
247 Some("http://etherx.jabber.org/streams".to_owned())
248 );
249 let child = elem.children().next().unwrap();
250 assert_eq!(child.name(), "message");
251 assert_eq!(child.ns(), Some("jabber:client".to_owned()));
252}
253
254#[test]
255fn namespace_inherited_prefixed2() {
256 let elem: Element = "<stream xmlns='http://etherx.jabber.org/streams' xmlns:jabber='jabber:client'><jabber:message/></stream>"
257 .parse().unwrap();
258 assert_eq!(elem.name(), "stream");
259 assert_eq!(
260 elem.ns(),
261 Some("http://etherx.jabber.org/streams".to_owned())
262 );
263 let child = elem.children().next().unwrap();
264 assert_eq!(child.name(), "message");
265 assert_eq!(child.ns(), Some("jabber:client".to_owned()));
266}
267
268#[cfg(feature = "comments")]
269#[test]
270fn read_comments() {
271 let mut reader = Reader::from_str(COMMENT_TEST_STRING);
272 assert_eq!(
273 Element::from_reader(&mut reader).unwrap(),
274 build_comment_test_tree()
275 );
276}
277
278#[cfg(feature = "comments")]
279#[test]
280fn write_comments() {
281 let root = build_comment_test_tree();
282 let mut writer = Vec::new();
283 {
284 root.write_to(&mut writer).unwrap();
285 }
286 assert_eq!(String::from_utf8(writer).unwrap(), COMMENT_TEST_STRING);
287}
288
289#[test]
290fn xml_error() {
291 match "<a></b>".parse::<Element>() {
292 Err(crate::error::Error::XmlError(_)) => (),
293 err => panic!("No or wrong error: {:?}", err),
294 }
295
296 match "<a></".parse::<Element>() {
297 Err(crate::error::Error::XmlError(_)) => (),
298 err => panic!("No or wrong error: {:?}", err),
299 }
300}
301
302#[test]
303fn invalid_element_error() {
304 match "<a:b:c>".parse::<Element>() {
305 Err(crate::error::Error::InvalidElement) => (),
306 err => panic!("No or wrong error: {:?}", err),
307 }
308}