mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
minidom: Implement PartialEq manually for Node and Element
Move the NamespaceAwareCompare implementation from xmpp-parsers as Node and Element's PartialEq implementation. Thanks Astro! It's a lot more useful in tests to use `assert_eq!` than `assert!`, so we get both items compared (left and right) instead of a "it failed." message. This "breaks" comparison for these two structs in the sense that it is not strict object comparison anymore but it ensures that namespaces are all present in the compared objects. Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
ea6e7c24a3
commit
1c5551a917
20 changed files with 65 additions and 172 deletions
|
@ -1,6 +1,8 @@
|
||||||
Version XXX, released YYY:
|
Version XXX, released YYY:
|
||||||
* Breaking
|
* Breaking
|
||||||
`Element.write_to` doesn't prepand xml prelude anymore. Use `write_to_decl`.
|
* `Element.write_to` doesn't prepand xml prelude anymore. Use `write_to_decl`.
|
||||||
|
* PartialEq implementation for Element and Node have been changed to
|
||||||
|
ensure namespaces match even if the objects are slightly different.
|
||||||
* Changes
|
* Changes
|
||||||
* Update edition to 2018
|
* Update edition to 2018
|
||||||
* Add NSChoice enum to allow comparing NSs differently
|
* Add NSChoice enum to allow comparing NSs differently
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub fn escape(raw: &[u8]) -> Cow<[u8]> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, Eq, Debug)]
|
||||||
/// A struct representing a DOM Element.
|
/// A struct representing a DOM Element.
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
|
@ -95,6 +95,31 @@ impl FromStr for Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Element {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
if self.name() == other.name() && self.ns() == other.ns() && self.attrs().eq(other.attrs())
|
||||||
|
{
|
||||||
|
let child_elems = self.children().count();
|
||||||
|
let text_is_whitespace = self
|
||||||
|
.texts()
|
||||||
|
.all(|text| text.chars().all(char::is_whitespace));
|
||||||
|
if child_elems > 0 && text_is_whitespace {
|
||||||
|
// Ignore all the whitespace text nodes
|
||||||
|
self.children()
|
||||||
|
.zip(other.children())
|
||||||
|
.all(|(node1, node2)| node1 == node2)
|
||||||
|
} else {
|
||||||
|
// Compare with text nodes
|
||||||
|
self.nodes()
|
||||||
|
.zip(other.nodes())
|
||||||
|
.all(|(node1, node2)| node1 == node2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Element {
|
impl Element {
|
||||||
fn new<NS: Into<NamespaceSet>>(
|
fn new<NS: Into<NamespaceSet>>(
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use quick_xml::events::{BytesText, Event};
|
||||||
use quick_xml::Writer as EventWriter;
|
use quick_xml::Writer as EventWriter;
|
||||||
|
|
||||||
/// A node in an element tree.
|
/// A node in an element tree.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, Eq)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
/// An `Element`.
|
/// An `Element`.
|
||||||
Element(Element),
|
Element(Element),
|
||||||
|
@ -208,3 +208,13 @@ impl From<ElementBuilder> for Node {
|
||||||
Node::Element(builder.build())
|
Node::Element(builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Node {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(&Node::Element(ref elem1), &Node::Element(ref elem2)) => elem1 == elem2,
|
||||||
|
(&Node::Text(ref text1), &Node::Text(ref text2)) => text1 == text2,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -70,7 +70,6 @@ impl Storage {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
@ -99,7 +98,7 @@ mod tests {
|
||||||
assert_eq!(storage.urls.len(), 0);
|
assert_eq!(storage.urls.len(), 0);
|
||||||
|
|
||||||
let elem2 = Element::from(Storage::new());
|
let elem2 = Element::from(Storage::new());
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -48,7 +48,6 @@ mod tests {
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
use crate::pubsub::event::PubSubEvent;
|
use crate::pubsub::event::PubSubEvent;
|
||||||
use crate::pubsub::pubsub::Item as PubSubItem;
|
use crate::pubsub::pubsub::Item as PubSubItem;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ mod tests {
|
||||||
assert_eq!(conference.password, None);
|
assert_eq!(conference.password, None);
|
||||||
|
|
||||||
let elem2 = Element::from(Conference::new());
|
let elem2 = Element::from(Conference::new());
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -232,7 +232,6 @@ impl IqResultPayload for DiscoItemsResult {}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -301,7 +300,7 @@ mod tests {
|
||||||
assert_eq!(query.extensions[0].form_type, Some(String::from("example")));
|
assert_eq!(query.extensions[0].form_type, Some(String::from("example")));
|
||||||
|
|
||||||
let elem2 = query.into();
|
let elem2 = query.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -117,7 +117,6 @@ impl From<Query> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -207,7 +206,7 @@ mod tests {
|
||||||
let form = query.form.clone().unwrap();
|
let form = query.form.clone().unwrap();
|
||||||
assert!(!form.instructions.unwrap().is_empty());
|
assert!(!form.instructions.unwrap().is_empty());
|
||||||
let elem2 = query.into();
|
let elem2 = query.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -242,6 +241,6 @@ mod tests {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let elem2 = query.into();
|
let elem2 = query.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,6 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::disco::DiscoInfoQuery;
|
use crate::disco::DiscoInfoQuery;
|
||||||
use crate::stanza_error::{DefinedCondition, ErrorType};
|
use crate::stanza_error::{DefinedCondition, ErrorType};
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -283,7 +282,7 @@ mod tests {
|
||||||
assert_eq!(iq.to, None);
|
assert_eq!(iq.to, None);
|
||||||
assert_eq!(&iq.id, "foo");
|
assert_eq!(&iq.id, "foo");
|
||||||
assert!(match iq.payload {
|
assert!(match iq.payload {
|
||||||
IqType::Get(element) => element.compare_to(&query),
|
IqType::Get(element) => element == query,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -308,7 +307,7 @@ mod tests {
|
||||||
assert_eq!(iq.to, None);
|
assert_eq!(iq.to, None);
|
||||||
assert_eq!(&iq.id, "vcard");
|
assert_eq!(&iq.id, "vcard");
|
||||||
assert!(match iq.payload {
|
assert!(match iq.payload {
|
||||||
IqType::Set(element) => element.compare_to(&vcard),
|
IqType::Set(element) => element == vcard,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -355,7 +354,7 @@ mod tests {
|
||||||
assert_eq!(iq.to, None);
|
assert_eq!(iq.to, None);
|
||||||
assert_eq!(&iq.id, "res");
|
assert_eq!(&iq.id, "res");
|
||||||
assert!(match iq.payload {
|
assert!(match iq.payload {
|
||||||
IqType::Result(Some(element)) => element.compare_to(&query),
|
IqType::Result(Some(element)) => element == query,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,7 +275,6 @@ impl From<Transport> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -327,7 +326,7 @@ mod tests {
|
||||||
payload: TransportPayload::Activated(CandidateId(String::from("coucou"))),
|
payload: TransportPayload::Activated(CandidateId(String::from("coucou"))),
|
||||||
};
|
};
|
||||||
let elem2: Element = transport.into();
|
let elem2: Element = transport.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -347,6 +346,6 @@ mod tests {
|
||||||
}]),
|
}]),
|
||||||
};
|
};
|
||||||
let elem2: Element = transport.into();
|
let elem2: Element = transport.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,6 @@ impl From<Message> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -312,7 +311,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = message.into();
|
let elem2 = message.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -326,7 +325,7 @@ mod tests {
|
||||||
.bodies
|
.bodies
|
||||||
.insert(String::from(""), Body::from_str("Hello world!").unwrap());
|
.insert(String::from(""), Body::from_str("Hello world!").unwrap());
|
||||||
let elem2 = message.into();
|
let elem2 = message.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -349,7 +348,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = message.into();
|
let elem2 = message.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -94,7 +94,6 @@ impl Muc {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use crate::util::error::Error;
|
use crate::util::error::Error;
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -161,7 +160,7 @@ mod tests {
|
||||||
assert_eq!(muc.password, Some("coucou".to_owned()));
|
assert_eq!(muc.password, Some("coucou".to_owned()));
|
||||||
|
|
||||||
let elem2 = Element::from(muc);
|
let elem2 = Element::from(muc);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -236,7 +236,6 @@ generate_element!(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -298,7 +297,7 @@ mod tests {
|
||||||
items: vec![],
|
items: vec![],
|
||||||
};
|
};
|
||||||
let elem2 = muc.into();
|
let elem2 = muc.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "disable-validation"))]
|
#[cfg(not(feature = "disable-validation"))]
|
||||||
|
|
|
@ -335,7 +335,6 @@ impl From<Presence> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use jid::{BareJid, FullJid};
|
use jid::{BareJid, FullJid};
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -382,7 +381,7 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let presence = Presence::new(Type::Unavailable);
|
let presence = Presence::new(Type::Unavailable);
|
||||||
let elem2 = presence.into();
|
let elem2 = presence.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -246,7 +246,6 @@ impl From<PubSubEvent> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -420,6 +419,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2: Element = event.into();
|
let elem2: Element = event.into();
|
||||||
assert!(elem.compare_to(&elem2));
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -518,7 +518,6 @@ impl From<PubSub> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create() {
|
fn create() {
|
||||||
|
@ -536,7 +535,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = Element::from(pubsub);
|
let elem2 = Element::from(pubsub);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
|
|
||||||
let elem: Element =
|
let elem: Element =
|
||||||
"<pubsub xmlns='http://jabber.org/protocol/pubsub'><create node='coucou'/></pubsub>"
|
"<pubsub xmlns='http://jabber.org/protocol/pubsub'><create node='coucou'/></pubsub>"
|
||||||
|
@ -553,7 +552,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = Element::from(pubsub);
|
let elem2 = Element::from(pubsub);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -573,7 +572,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = Element::from(pubsub);
|
let elem2 = Element::from(pubsub);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -596,7 +595,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = Element::from(pubsub);
|
let elem2 = Element::from(pubsub);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -616,7 +615,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem2 = Element::from(pubsub);
|
let elem2 = Element::from(pubsub);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -92,7 +92,6 @@ impl IqResultPayload for Roster {}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use crate::util::error::Error;
|
use crate::util::error::Error;
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -220,7 +219,7 @@ mod tests {
|
||||||
assert_eq!(roster.items[0].groups[0], Group::from_str("A").unwrap());
|
assert_eq!(roster.items[0].groups[0], Group::from_str("A").unwrap());
|
||||||
assert_eq!(roster.items[0].groups[1], Group::from_str("B").unwrap());
|
assert_eq!(roster.items[0].groups[1], Group::from_str("B").unwrap());
|
||||||
let elem2 = roster.into();
|
let elem2 = roster.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -174,7 +174,6 @@ impl From<SetResult> for Element {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -304,6 +303,6 @@ mod tests {
|
||||||
count: None,
|
count: None,
|
||||||
};
|
};
|
||||||
let elem2 = set2.into();
|
let elem2 = set2.into();
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
// Copyright (c) 2017 Astro <astro@spaceboyz.net>
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
use minidom::{Element, Node};
|
|
||||||
|
|
||||||
pub trait NamespaceAwareCompare {
|
|
||||||
/// Namespace-aware comparison for tests
|
|
||||||
fn compare_to(&self, other: &Self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NamespaceAwareCompare for Node {
|
|
||||||
fn compare_to(&self, other: &Self) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
(&Node::Element(ref elem1), &Node::Element(ref elem2)) => {
|
|
||||||
Element::compare_to(elem1, elem2)
|
|
||||||
}
|
|
||||||
(&Node::Text(ref text1), &Node::Text(ref text2)) => text1 == text2,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NamespaceAwareCompare for Element {
|
|
||||||
fn compare_to(&self, other: &Self) -> bool {
|
|
||||||
if self.name() == other.name() && self.ns() == other.ns() && self.attrs().eq(other.attrs())
|
|
||||||
{
|
|
||||||
let child_elems = self.children().count();
|
|
||||||
let text_is_whitespace = self
|
|
||||||
.texts()
|
|
||||||
.all(|text| text.chars().all(char::is_whitespace));
|
|
||||||
if child_elems > 0 && text_is_whitespace {
|
|
||||||
// Ignore all the whitespace text nodes
|
|
||||||
self.children()
|
|
||||||
.zip(other.children())
|
|
||||||
.all(|(node1, node2)| node1.compare_to(node2))
|
|
||||||
} else {
|
|
||||||
// Compare with text nodes
|
|
||||||
self.nodes()
|
|
||||||
.zip(other.nodes())
|
|
||||||
.all(|(node1, node2)| node1.compare_to(node2))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::Element;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple() {
|
|
||||||
let elem1: Element = "<a a='b'>x <l/> 3</a>".parse().unwrap();
|
|
||||||
let elem2: Element = "<a a='b'>x <l/> 3</a>".parse().unwrap();
|
|
||||||
assert!(elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_attr_name() {
|
|
||||||
let elem1: Element = "<a a='b'>x 3</a>".parse().unwrap();
|
|
||||||
let elem2: Element = "<a c='b'>x 3</a>".parse().unwrap();
|
|
||||||
assert!(!elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_attr_value() {
|
|
||||||
let elem1: Element = "<a a='b'>x 3</a>".parse().unwrap();
|
|
||||||
let elem2: Element = "<a a='c'>x 3</a>".parse().unwrap();
|
|
||||||
assert!(!elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attr_order() {
|
|
||||||
let elem1: Element = "<e1 a='b' c='d'/>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1 c='d' a='b'/>".parse().unwrap();
|
|
||||||
assert!(elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_texts() {
|
|
||||||
let elem1: Element = "<e1>foo</e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1>bar</e1>".parse().unwrap();
|
|
||||||
assert!(!elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn children() {
|
|
||||||
let elem1: Element = "<e1><foo/><bar/></e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1><foo/><bar/></e1>".parse().unwrap();
|
|
||||||
assert!(elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_children() {
|
|
||||||
let elem1: Element = "<e1><foo/></e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1><bar/></e1>".parse().unwrap();
|
|
||||||
assert!(!elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn xmlns_wrong() {
|
|
||||||
let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1 xmlns='ns2'><foo/></e1>".parse().unwrap();
|
|
||||||
assert!(!elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn xmlns_other_prefix() {
|
|
||||||
let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<x:e1 xmlns:x='ns1'><x:foo/></x:e1>".parse().unwrap();
|
|
||||||
assert!(elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn xmlns_dup() {
|
|
||||||
let elem1: Element = "<e1 xmlns='ns1'><foo/></e1>".parse().unwrap();
|
|
||||||
let elem2: Element = "<e1 xmlns='ns1'><foo xmlns='ns1'/></e1>".parse().unwrap();
|
|
||||||
assert!(elem1.compare_to(&elem2));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,7 +13,3 @@ pub(crate) mod helpers;
|
||||||
/// Helper macros to parse and serialise more easily.
|
/// Helper macros to parse and serialise more easily.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
/// Namespace-aware comparison for tests
|
|
||||||
pub(crate) mod compare_elements;
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ impl IqResultPayload for VersionResult {}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::compare_elements::NamespaceAwareCompare;
|
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
@ -84,6 +83,6 @@ mod tests {
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("{:?}", elem1);
|
println!("{:?}", elem1);
|
||||||
assert!(elem1.compare_to(&elem2));
|
assert_eq!(elem1, elem2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue