From c8e1fbab70ffc452b53f396c1fe35c18d04d2870 Mon Sep 17 00:00:00 2001 From: Bryan Swift Date: Mon, 13 Apr 2020 22:44:23 -0400 Subject: [PATCH 1/3] Add tests for current behavior of `Classes` --- src/virtual_dom/mod.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs index e788d50d547..5aed1a34f2e 100644 --- a/src/virtual_dom/mod.rs +++ b/src/virtual_dom/mod.rs @@ -228,3 +228,47 @@ pub trait Transformer { /// Transforms one type to another. fn transform(from: FROM) -> TO; } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_is_initially_empty() { + let subject = Classes::new(); + assert!(subject.is_empty()); + } + + #[test] + fn it_pushes_value() { + let mut subject = Classes::new(); + subject.push("foo"); + assert!(!subject.is_empty()); + assert!(subject.contains("foo")); + } + + #[test] + fn it_adds_values_via_extend() { + let mut other = Classes::new(); + other.push("bar"); + let subject = Classes::new().extend(other); + assert!(subject.contains("bar")); + } + + #[test] + fn it_contains_both_values() { + let mut other = Classes::new(); + other.push("bar"); + let mut subject = Classes::new().extend(other); + subject.push("foo"); + assert!(subject.contains("foo")); + assert!(subject.contains("bar")); + } + + #[test] + fn it_splits_class_with_spaces() { + let mut subject = Classes::new(); + subject.push("foo bar"); + assert!(subject.contains("foo bar")); + } +} From 14b00b671a101ec715670d4f6a148239d759f557 Mon Sep 17 00:00:00 2001 From: Bryan Swift Date: Mon, 13 Apr 2020 22:44:50 -0400 Subject: [PATCH 2/3] Change `Classes::push` to split incoming class on whitespace --- src/virtual_dom/mod.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs index 5aed1a34f2e..8ff63a98d0d 100644 --- a/src/virtual_dom/mod.rs +++ b/src/virtual_dom/mod.rs @@ -76,10 +76,8 @@ impl Classes { /// /// Prevents duplication of class names. pub fn push(&mut self, class: &str) { - let class = class.trim(); - if !class.is_empty() { - self.set.insert(class.into()); - } + let classes_to_add: Classes = class.into(); + self.set.extend(classes_to_add.set); } /// Check the set contains a class. @@ -269,6 +267,7 @@ mod tests { fn it_splits_class_with_spaces() { let mut subject = Classes::new(); subject.push("foo bar"); - assert!(subject.contains("foo bar")); + assert!(subject.contains("foo")); + assert!(subject.contains("bar")); } } From ccca233ca1c6b852c10254ae8b977d77a267a1b0 Mon Sep 17 00:00:00 2001 From: Bryan Swift Date: Mon, 13 Apr 2020 23:37:47 -0400 Subject: [PATCH 3/3] Split each item in `Vec` on whitespace in `From> for Classes` When creating a `VTag` with `class` assigned from a `Vec` the items in `Vec` were not split on whitespace and so were not enforced as unique in the same way a `VTag` with `class` assigned from `tuple`. --- src/virtual_dom/mod.rs | 4 +++- src/virtual_dom/vtag.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs index 8ff63a98d0d..b20042d2fe6 100644 --- a/src/virtual_dom/mod.rs +++ b/src/virtual_dom/mod.rs @@ -146,7 +146,9 @@ impl> From> for Classes { fn from(t: Vec) -> Self { let set = t .iter() - .map(|x| x.as_ref().to_string()) + .map(|x| x.as_ref()) + .flat_map(|s| s.split_whitespace()) + .map(String::from) .filter(|c| !c.is_empty()) .collect(); Self { set } diff --git a/src/virtual_dom/vtag.rs b/src/virtual_dom/vtag.rs index d79953d4815..5d6ca89ca33 100644 --- a/src/virtual_dom/vtag.rs +++ b/src/virtual_dom/vtag.rs @@ -755,6 +755,22 @@ mod tests { assert_eq!(a, c); } + #[test] + fn supports_multiple_non_unique_classes_tuple() { + let a = html! { +
+ }; + + if let VNode::VTag(vtag) = a { + println!("{:?}", vtag.classes); + assert!(vtag.classes.contains("class-1")); + assert!(vtag.classes.contains("class-2")); + assert!(!vtag.classes.contains("class-3")); + } else { + panic!("vtag expected"); + } + } + #[test] fn supports_multiple_classes_string() { let a = html! { @@ -795,6 +811,23 @@ mod tests { } } + #[test] + fn supports_multiple_classes_one_value_vec() { + let classes = vec!["class-1 class-2", "class-1"]; + let a = html! { +
+ }; + + if let VNode::VTag(vtag) = a { + println!("{:?}", vtag.classes); + assert!(vtag.classes.contains("class-1")); + assert!(vtag.classes.contains("class-2")); + assert!(!vtag.classes.contains("class-3")); + } else { + panic!("vtag expected"); + } + } + #[test] fn filter_empty_string_classes_vec() { let mut classes = vec![""];