compare_elements.rs

  1// Copyright (c) 2017 Astro <astro@spaceboyz.net>
  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 minidom::{Node, Element};
  8
  9pub trait NamespaceAwareCompare {
 10    /// Namespace-aware comparison for tests
 11    fn compare_to(&self, other: &Self) -> bool;
 12}
 13
 14impl NamespaceAwareCompare for Node {
 15    fn compare_to(&self, other: &Self) -> bool {
 16        match (self, other) {
 17            (&Node::Element(ref elem1), &Node::Element(ref elem2)) =>
 18                Element::compare_to(elem1, elem2),
 19            (&Node::Text(ref text1), &Node::Text(ref text2)) =>
 20                text1 == text2,
 21            _ => false,
 22        }
 23    }
 24}
 25
 26impl NamespaceAwareCompare for Element {
 27    fn compare_to(&self, other: &Self) -> bool {
 28        if self.name() == other.name() &&
 29            self.ns() == other.ns() &&
 30            self.attrs().eq(other.attrs())
 31        {
 32            let child_elems = self.children().count();
 33            let text_is_whitespace = self.texts()
 34                .all(|text| text.chars().all(char::is_whitespace));
 35            if child_elems > 0 && text_is_whitespace {
 36                // Ignore all the whitespace text nodes
 37                self.children().zip(other.children())
 38                    .all(|(node1, node2)| node1.compare_to(node2))
 39            } else {
 40                // Compare with text nodes
 41                self.nodes().zip(other.nodes())
 42                    .all(|(node1, node2)| node1.compare_to(node2))
 43            }
 44        } else {
 45            false
 46        }
 47    }
 48}
 49
 50#[cfg(test)]
 51mod tests {
 52    use super::*;
 53    use minidom::Element;
 54
 55    #[test]
 56    fn simple() {
 57        let elem1: Element = "<a a='b'>x <l/> 3</a>".parse().unwrap();
 58        let elem2: Element = "<a a='b'>x <l/> 3</a>".parse().unwrap();
 59        assert!(elem1.compare_to(&elem2));
 60    }
 61
 62    #[test]
 63    fn wrong_attr_name() {
 64        let elem1: Element = "<a a='b'>x 3</a>".parse().unwrap();
 65        let elem2: Element = "<a c='b'>x 3</a>".parse().unwrap();
 66        assert!(!elem1.compare_to(&elem2));
 67    }
 68
 69    #[test]
 70    fn wrong_attr_value() {
 71        let elem1: Element = "<a a='b'>x 3</a>".parse().unwrap();
 72        let elem2: Element = "<a a='c'>x 3</a>".parse().unwrap();
 73        assert!(!elem1.compare_to(&elem2));
 74    }
 75
 76    #[test]
 77    fn attr_order() {
 78        let elem1: Element = "<e1 a='b' c='d'/>".parse().unwrap();
 79        let elem2: Element = "<e1 c='d' a='b'/>".parse().unwrap();
 80        assert!(elem1.compare_to(&elem2));
 81    }
 82
 83    #[test]
 84    fn wrong_texts() {
 85        let elem1: Element = "<e1>foo</e1>".parse().unwrap();
 86        let elem2: Element = "<e1>bar</e1>".parse().unwrap();
 87        assert!(!elem1.compare_to(&elem2));
 88    }
 89
 90    #[test]
 91    fn children() {
 92        let elem1: Element = "<e1><foo/><bar/></e1>".parse().unwrap();
 93        let elem2: Element = "<e1><foo/><bar/></e1>".parse().unwrap();
 94        assert!(elem1.compare_to(&elem2));
 95    }
 96
 97    #[test]
 98    fn wrong_children() {
 99        let elem1: Element = "<e1><foo/></e1>".parse().unwrap();
100        let elem2: Element = "<e1><bar/></e1>".parse().unwrap();
101        assert!(!elem1.compare_to(&elem2));
102    }
103
104    #[test]
105    fn xmlns_wrong() {
106        let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
107        let elem2: Element = "<e1 xmlns='ns2'><foo/></e1>".parse().unwrap();
108        assert!(!elem1.compare_to(&elem2));
109    }
110
111    #[test]
112    fn xmlns_other_prefix() {
113        let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
114        let elem2: Element = "<x:e1 xmlns:x='ns1'><x:foo/></x:e1>".parse().unwrap();
115        assert!(elem1.compare_to(&elem2));
116    }
117
118    #[test]
119    fn xmlns_dup() {
120        let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
121        let elem2: Element = "<e1 xmlns='ns1'><foo  xmlns='ns1'/></e1>".parse().unwrap();
122        assert!(elem1.compare_to(&elem2));
123    }
124}