1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use try_from::TryFrom;
8
9use minidom::Element;
10use date::DateTime;
11
12use error::Error;
13
14use ns;
15
16generate_element_with_only_attributes!(Idle, "idle", ns::IDLE, [
17 since: DateTime = "since" => required,
18]);
19
20#[cfg(test)]
21mod tests {
22 use super::*;
23 use std::str::FromStr;
24 use std::error::Error as StdError;
25
26 #[test]
27 fn test_simple() {
28 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
29 Idle::try_from(elem).unwrap();
30 }
31
32 #[test]
33 fn test_invalid_child() {
34 let elem: Element = "<idle xmlns='urn:xmpp:idle:1'><coucou/></idle>".parse().unwrap();
35 let error = Idle::try_from(elem).unwrap_err();
36 let message = match error {
37 Error::ParseError(string) => string,
38 _ => panic!(),
39 };
40 assert_eq!(message, "Unknown child in idle element.");
41 }
42
43 #[test]
44 fn test_invalid_id() {
45 let elem: Element = "<idle xmlns='urn:xmpp:idle:1'/>".parse().unwrap();
46 let error = Idle::try_from(elem).unwrap_err();
47 let message = match error {
48 Error::ParseError(string) => string,
49 _ => panic!(),
50 };
51 assert_eq!(message, "Required attribute 'since' missing.");
52 }
53
54 #[test]
55 fn test_invalid_date() {
56 // There is no thirteenth month.
57 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-13-01T12:23:34Z'/>".parse().unwrap();
58 let error = Idle::try_from(elem).unwrap_err();
59 let message = match error {
60 Error::ChronoParseError(string) => string,
61 _ => panic!(),
62 };
63 assert_eq!(message.description(), "input is out of range");
64
65 // Timezone ≥24:00 aren’t allowed.
66 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+25:00'/>".parse().unwrap();
67 let error = Idle::try_from(elem).unwrap_err();
68 let message = match error {
69 Error::ChronoParseError(string) => string,
70 _ => panic!(),
71 };
72 assert_eq!(message.description(), "input is out of range");
73
74 // Timezone without the : separator aren’t allowed.
75 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+0100'/>".parse().unwrap();
76 let error = Idle::try_from(elem).unwrap_err();
77 let message = match error {
78 Error::ChronoParseError(string) => string,
79 _ => panic!(),
80 };
81 assert_eq!(message.description(), "input contains invalid characters");
82
83 // No seconds, error message could be improved.
84 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11+01:00'/>".parse().unwrap();
85 let error = Idle::try_from(elem).unwrap_err();
86 let message = match error {
87 Error::ChronoParseError(string) => string,
88 _ => panic!(),
89 };
90 assert_eq!(message.description(), "input contains invalid characters");
91
92 // TODO: maybe we’ll want to support this one, as per XEP-0082 §4.
93 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='20170527T12:11:02+01:00'/>".parse().unwrap();
94 let error = Idle::try_from(elem).unwrap_err();
95 let message = match error {
96 Error::ChronoParseError(string) => string,
97 _ => panic!(),
98 };
99 assert_eq!(message.description(), "input contains invalid characters");
100
101 // No timezone.
102 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02'/>".parse().unwrap();
103 let error = Idle::try_from(elem).unwrap_err();
104 let message = match error {
105 Error::ChronoParseError(string) => string,
106 _ => panic!(),
107 };
108 assert_eq!(message.description(), "premature end of input");
109 }
110
111 #[test]
112 fn test_serialise() {
113 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
114 let idle = Idle { since: DateTime::from_str("2017-05-21T20:19:55+01:00").unwrap() };
115 let elem2 = idle.into();
116 assert_eq!(elem, elem2);
117 }
118}