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