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 presence::PresencePayload;
  8use date::DateTime;
  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: DateTime = "since" => required,
 16    ]
 17);
 18
 19impl PresencePayload for Idle {}
 20
 21#[cfg(test)]
 22mod tests {
 23    use super::*;
 24    use try_from::TryFrom;
 25    use minidom::Element;
 26    use error::Error;
 27    use std::str::FromStr;
 28    use std::error::Error as StdError;
 29
 30    #[test]
 31    fn test_size() {
 32        assert_size!(Idle, 16);
 33    }
 34
 35    #[test]
 36    fn test_simple() {
 37        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
 38        Idle::try_from(elem).unwrap();
 39    }
 40
 41    #[test]
 42    fn test_invalid_child() {
 43        let elem: Element = "<idle xmlns='urn:xmpp:idle:1'><coucou/></idle>".parse().unwrap();
 44        let error = Idle::try_from(elem).unwrap_err();
 45        let message = match error {
 46            Error::ParseError(string) => string,
 47            _ => panic!(),
 48        };
 49        assert_eq!(message, "Unknown child in idle element.");
 50    }
 51
 52    #[test]
 53    fn test_invalid_id() {
 54        let elem: Element = "<idle xmlns='urn:xmpp:idle:1'/>".parse().unwrap();
 55        let error = Idle::try_from(elem).unwrap_err();
 56        let message = match error {
 57            Error::ParseError(string) => string,
 58            _ => panic!(),
 59        };
 60        assert_eq!(message, "Required attribute 'since' missing.");
 61    }
 62
 63    #[test]
 64    fn test_invalid_date() {
 65        // There is no thirteenth month.
 66        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-13-01T12:23:34Z'/>".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 ≥24:00 aren’t allowed.
 75        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+25:00'/>".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 is out of range");
 82
 83        // Timezone without the : separator aren’t allowed.
 84        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+0100'/>".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        // No seconds, error message could be improved.
 93        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11+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        // TODO: maybe we’ll want to support this one, as per XEP-0082 §4.
102        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='20170527T12:11:02+01:00'/>".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(), "input contains invalid characters");
109
110        // No timezone.
111        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02'/>".parse().unwrap();
112        let error = Idle::try_from(elem).unwrap_err();
113        let message = match error {
114            Error::ChronoParseError(string) => string,
115            _ => panic!(),
116        };
117        assert_eq!(message.description(), "premature end of input");
118    }
119
120    #[test]
121    fn test_serialise() {
122        let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
123        let idle = Idle { since: DateTime::from_str("2017-05-21T20:19:55+01:00").unwrap() };
124        let elem2 = idle.into();
125        assert_eq!(elem, elem2);
126    }
127}