1use xso::{AsXml, FromXml};
8
9use crate::date::DateTime;
10use crate::ns;
11use crate::presence::PresencePayload;
12
13#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
15#[xml(namespace = ns::IDLE, name = "idle")]
16pub struct Idle {
17 #[xml(attribute)]
19 pub since: DateTime,
20}
21
22impl PresencePayload for Idle {}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use core::str::FromStr;
28 use minidom::Element;
29 use xso::error::{Error, FromElementError};
30
31 #[test]
32 fn test_size() {
33 assert_size!(Idle, 16);
34 }
35
36 #[test]
37 fn test_simple() {
38 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>"
39 .parse()
40 .unwrap();
41 Idle::try_from(elem).unwrap();
42 }
43
44 #[test]
45 #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
46 fn test_invalid_child() {
47 let elem: Element =
48 "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'><coucou/></idle>"
49 .parse()
50 .unwrap();
51 let error = Idle::try_from(elem).unwrap_err();
52 let message = match error {
53 FromElementError::Invalid(Error::Other(string)) => string,
54 other => panic!("unexpected result: {:?}", other),
55 };
56 assert_eq!(message, "Unknown child in Idle element.");
57 }
58
59 #[test]
60 fn test_invalid_id() {
61 let elem: Element = "<idle xmlns='urn:xmpp:idle:1'/>".parse().unwrap();
62 let error = Idle::try_from(elem).unwrap_err();
63 let message = match error {
64 FromElementError::Invalid(Error::Other(string)) => string,
65 _ => panic!(),
66 };
67 assert_eq!(
68 message,
69 "Required attribute field 'since' on Idle element missing."
70 );
71 }
72
73 #[test]
74 fn test_invalid_date() {
75 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-13-01T12:23:34Z'/>"
77 .parse()
78 .unwrap();
79 let error = Idle::try_from(elem).unwrap_err();
80 let message = match error {
81 FromElementError::Invalid(Error::TextParseError(string))
82 if string.is::<chrono::ParseError>() =>
83 {
84 string
85 }
86 other => panic!("unexpected result: {:?}", other),
87 };
88 assert_eq!(message.to_string(), "input is out of range");
89
90 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+25:00'/>"
92 .parse()
93 .unwrap();
94 let error = Idle::try_from(elem).unwrap_err();
95 let message = match error {
96 FromElementError::Invalid(Error::TextParseError(string))
97 if string.is::<chrono::ParseError>() =>
98 {
99 string
100 }
101 _ => panic!(),
102 };
103 assert_eq!(message.to_string(), "input is out of range");
104
105 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+0100'/>"
107 .parse()
108 .unwrap();
109 let error = Idle::try_from(elem).unwrap_err();
110 let message = match error {
111 FromElementError::Invalid(Error::TextParseError(string))
112 if string.is::<chrono::ParseError>() =>
113 {
114 string
115 }
116 _ => panic!(),
117 };
118 assert_eq!(message.to_string(), "input contains invalid characters");
119
120 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11+01:00'/>"
122 .parse()
123 .unwrap();
124 let error = Idle::try_from(elem).unwrap_err();
125 let message = match error {
126 FromElementError::Invalid(Error::TextParseError(string))
127 if string.is::<chrono::ParseError>() =>
128 {
129 string
130 }
131 _ => panic!(),
132 };
133 assert_eq!(message.to_string(), "input contains invalid characters");
134
135 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='20170527T12:11:02+01:00'/>"
137 .parse()
138 .unwrap();
139 let error = Idle::try_from(elem).unwrap_err();
140 let message = match error {
141 FromElementError::Invalid(Error::TextParseError(string))
142 if string.is::<chrono::ParseError>() =>
143 {
144 string
145 }
146 _ => panic!(),
147 };
148 assert_eq!(message.to_string(), "input contains invalid characters");
149
150 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02'/>"
152 .parse()
153 .unwrap();
154 let error = Idle::try_from(elem).unwrap_err();
155 let message = match error {
156 FromElementError::Invalid(Error::TextParseError(string))
157 if string.is::<chrono::ParseError>() =>
158 {
159 string
160 }
161 _ => panic!(),
162 };
163 assert_eq!(message.to_string(), "premature end of input");
164 }
165
166 #[test]
167 fn test_serialise() {
168 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>"
169 .parse()
170 .unwrap();
171 let idle = Idle {
172 since: DateTime::from_str("2017-05-21T20:19:55+01:00").unwrap(),
173 };
174 let elem2 = idle.into();
175 assert_eq!(elem, elem2);
176 }
177}