idle.rs

  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}