Fix the PartialEq implementation for Element

Eijebong created

The order of attributes in an `Element` doesn't matter anymore.
`<elem a="b" c="d" />` and `<elem c="d" a="b" />` are now correctly
considered equal.

For that I had to derive `PartialOrd` and `Ord` for `Attribute`.
This allows us to sort cloned vectors of `Attribute` in the `PartialEq`
implementation and compare them instead of the struct `attributes`.

Fixes #3

Change summary

src/attribute.rs |  2 +-
src/element.rs   | 16 +++++++++++++++-
src/tests.rs     | 11 +++++++++++
3 files changed, 27 insertions(+), 2 deletions(-)

Detailed changes

src/attribute.rs 🔗

@@ -9,7 +9,7 @@ use std::fmt;
 /// This is of the form: `name`="`value`"
 ///
 /// This does not support prefixed/namespaced attributes yet.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
 pub struct Attribute {
     /// The name of the attribute.
     pub name: String,

src/element.rs 🔗

@@ -20,7 +20,7 @@ use std::slice;
 
 use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, Eq)]
 /// A struct representing a DOM Element.
 pub struct Element {
     name: String,
@@ -29,6 +29,20 @@ pub struct Element {
     children: Vec<Node>,
 }
 
+impl PartialEq for Element {
+    fn eq(&self, other: &Element) -> bool {
+        let mut my_attr = self.attributes.clone();
+        my_attr.sort();
+        let mut other_attr = other.attributes.clone();
+        other_attr.sort();
+
+        self.name == other.name &&
+        self.namespace == other.namespace &&
+        my_attr == other_attr &&
+        self.children == other.children
+    }
+}
+
 impl fmt::Debug for Element {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "<{}", self.name)?;

src/tests.rs 🔗

@@ -94,3 +94,14 @@ fn namespace_propagation_works() {
                    .get_child("grandchild", "root_ns").unwrap()
                    .ns(), root.ns());
 }
+
+#[test]
+fn two_elements_with_same_arguments_different_order_are_equal() {
+    let elem1: Element = "<a b='a' c=''/>".parse().unwrap();
+    let elem2: Element = "<a c='' b='a'/>".parse().unwrap();
+    assert_eq!(elem1, elem2);
+
+    let elem1: Element = "<a b='a' c=''/>".parse().unwrap();
+    let elem2: Element = "<a c='d' b='a'/>".parse().unwrap();
+    assert_ne!(elem1, elem2);
+}