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 crate::date::DateTime;
8use crate::presence::PresencePayload;
9
10generate_element!(
11 /// Represents the last time the user interacted with their system.
12 Idle, "idle", IDLE,
13 attributes: [
14 /// The time at which the user stopped interacting.
15 since: Required<DateTime> = "since",
16 ]
17);
18
19impl PresencePayload for Idle {}
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24 use crate::util::error::Error;
25 use crate::Element;
26 use std::convert::TryFrom;
27 use std::str::FromStr;
28
29 #[test]
30 fn test_size() {
31 assert_size!(Idle, 16);
32 }
33
34 #[test]
35 fn test_simple() {
36 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>"
37 .parse()
38 .unwrap();
39 Idle::try_from(elem).unwrap();
40 }
41
42 #[test]
43 fn test_invalid_child() {
44 let elem: Element = "<idle xmlns='urn:xmpp:idle:1'><coucou/></idle>"
45 .parse()
46 .unwrap();
47 let error = Idle::try_from(elem).unwrap_err();
48 let message = match error {
49 Error::ParseError(string) => string,
50 _ => panic!(),
51 };
52 assert_eq!(message, "Unknown child in idle element.");
53 }
54
55 #[test]
56 fn test_invalid_id() {
57 let elem: Element = "<idle xmlns='urn:xmpp:idle:1'/>".parse().unwrap();
58 let error = Idle::try_from(elem).unwrap_err();
59 let message = match error {
60 Error::ParseError(string) => string,
61 _ => panic!(),
62 };
63 assert_eq!(message, "Required attribute 'since' missing.");
64 }
65
66 #[test]
67 fn test_invalid_date() {
68 // There is no thirteenth month.
69 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-13-01T12:23:34Z'/>"
70 .parse()
71 .unwrap();
72 let error = Idle::try_from(elem).unwrap_err();
73 let message = match error {
74 Error::ChronoParseError(string) => string,
75 _ => panic!(),
76 };
77 assert_eq!(message.to_string(), "input is out of range");
78
79 // Timezone ≥24:00 aren’t allowed.
80 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+25:00'/>"
81 .parse()
82 .unwrap();
83 let error = Idle::try_from(elem).unwrap_err();
84 let message = match error {
85 Error::ChronoParseError(string) => string,
86 _ => panic!(),
87 };
88 assert_eq!(message.to_string(), "input is out of range");
89
90 // Timezone without the : separator aren’t allowed.
91 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+0100'/>"
92 .parse()
93 .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.to_string(), "input contains invalid characters");
100
101 // No seconds, error message could be improved.
102 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11+01:00'/>"
103 .parse()
104 .unwrap();
105 let error = Idle::try_from(elem).unwrap_err();
106 let message = match error {
107 Error::ChronoParseError(string) => string,
108 _ => panic!(),
109 };
110 assert_eq!(message.to_string(), "input contains invalid characters");
111
112 // TODO: maybe we’ll want to support this one, as per XEP-0082 §4.
113 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='20170527T12:11:02+01:00'/>"
114 .parse()
115 .unwrap();
116 let error = Idle::try_from(elem).unwrap_err();
117 let message = match error {
118 Error::ChronoParseError(string) => string,
119 _ => panic!(),
120 };
121 assert_eq!(message.to_string(), "input contains invalid characters");
122
123 // No timezone.
124 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02'/>"
125 .parse()
126 .unwrap();
127 let error = Idle::try_from(elem).unwrap_err();
128 let message = match error {
129 Error::ChronoParseError(string) => string,
130 _ => panic!(),
131 };
132 assert_eq!(message.to_string(), "premature end of input");
133 }
134
135 #[test]
136 fn test_serialise() {
137 let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>"
138 .parse()
139 .unwrap();
140 let idle = Idle {
141 since: DateTime::from_str("2017-05-21T20:19:55+01:00").unwrap(),
142 };
143 let elem2 = idle.into();
144 assert_eq!(elem, elem2);
145 }
146}