1use std::borrow::Borrow;
16use std::fmt::{Debug, Formatter};
17use std::hash::Hash;
18
19use crate::assertions::basic::EqualityAssertion;
20use crate::assertions::iterator::{
21 check_contains, check_does_not_contain, check_is_empty, check_is_not_empty,
22};
23use crate::base::{AssertionApi, AssertionResult, AssertionStrategy, Subject};
24use crate::diff::iter::SequenceOrderComparison;
25use crate::diff::map::{MapComparison, MapLike, MapValueDiff, OrderedMapLike};
26
27pub trait MapAssertion<'a, K: 'a + Eq, V, ML, R>
46where
47 AssertionResult: AssertionStrategy<R>,
48 ML: MapLike<K, V>,
49{
50 fn has_length(&self, length: usize) -> R;
52
53 fn is_empty(&self) -> R
55 where
56 K: Debug;
57
58 fn is_not_empty(&self) -> R
60 where
61 K: Debug;
62
63 fn contains_key<BK>(&self, key: BK) -> R
65 where
66 BK: Borrow<K>,
67 K: Eq + Hash + Debug;
68
69 fn does_not_contain_key<BK>(&self, key: BK) -> R
71 where
72 BK: Borrow<K>,
73 K: Eq + Hash + Debug;
74
75 fn contains_entry<BK, BV>(&self, key: BK, value: BV) -> R
77 where
78 BK: Borrow<K>,
79 BV: Borrow<V>,
80 K: Eq + Hash + Debug,
81 V: Eq + Debug;
82
83 fn does_not_contain_entry<BK, BV>(&self, key: BK, value: BV) -> R
85 where
86 BK: Borrow<K>,
87 BV: Borrow<V>,
88 K: Eq + Hash + Debug,
89 V: Eq + Debug;
90
91 fn contains_at_least<BM: 'a, OML: 'a>(&self, expected: BM) -> R
93 where
94 K: Eq + Hash + Debug,
95 V: Eq + Debug,
96 OML: MapLike<K, V> + 'a,
97 BM: Borrow<OML> + 'a;
98
99 fn does_not_contain_any<BM: 'a, OML: 'a>(&self, expected: BM) -> R
101 where
102 K: Eq + Hash + Debug,
103 V: Eq + Debug,
104 OML: MapLike<K, V> + 'a,
105 BM: Borrow<OML> + 'a;
106
107 fn contains_exactly<BM, OML>(&self, expected: BM) -> R
109 where
110 K: Eq + Hash + Debug,
111 V: Eq + Debug,
112 OML: MapLike<K, V> + 'a,
113 BM: Borrow<OML> + 'a;
114
115 fn key_set<'b>(&'b self) -> Subject<ML::It<'b>, (), R>
133 where
134 K: 'b;
135}
136
137pub trait OrderedMapAssertion<'a, K: 'a + Ord + Eq, V, ML, R>:
157 MapAssertion<'a, K, V, ML, R>
158where
159 AssertionResult: AssertionStrategy<R>,
160 ML: OrderedMapLike<K, V>,
161{
162 fn contains_exactly_in_order<BM, OML>(&self, expected: BM) -> R
164 where
165 K: Eq + Ord + Debug,
166 V: Eq + Debug,
167 OML: OrderedMapLike<K, V> + 'a,
168 BM: Borrow<OML> + 'a;
169
170 fn contains_all_of_in_order<BM, OML>(&self, expected: BM) -> R
172 where
173 K: Eq + Ord + Debug,
174 V: Eq + Debug,
175 OML: OrderedMapLike<K, V> + 'a,
176 BM: Borrow<OML> + 'a;
177}
178
179impl<'a, K, V, ML, R> MapAssertion<'a, K, V, ML, R> for Subject<'a, ML, (), R>
180where
181 AssertionResult: AssertionStrategy<R>,
182 K: 'a + Eq,
183 ML: MapLike<K, V>,
184{
185 fn has_length(&self, length: usize) -> R {
186 self.new_subject(
187 &self.actual().len(),
188 Some(format!("{}.len()", self.description_or_expr())),
189 (),
190 )
191 .is_equal_to(length)
192 }
193
194 fn is_empty(&self) -> R
195 where
196 K: Debug,
197 {
198 check_is_empty(self.new_result(), self.actual().keys().into_iter())
199 }
200
201 fn is_not_empty(&self) -> R
202 where
203 K: Debug,
204 {
205 check_is_not_empty(self.new_result(), self.actual().keys().into_iter())
206 }
207
208 fn contains_key<BK>(&self, key: BK) -> R
209 where
210 BK: Borrow<K>,
211 K: Eq + Hash + Debug,
212 {
213 check_contains(
214 self.new_result(),
215 self.actual().keys().into_iter(),
216 &key.borrow(),
217 )
218 }
219
220 fn does_not_contain_key<BK>(&self, key: BK) -> R
221 where
222 BK: Borrow<K>,
223 K: Eq + Hash + Debug,
224 {
225 check_does_not_contain(
226 self.new_result(),
227 self.actual().keys().into_iter(),
228 &key.borrow(),
229 )
230 }
231
232 fn contains_entry<BK, BV>(&self, key: BK, value: BV) -> R
233 where
234 BK: Borrow<K>,
235 BV: Borrow<V>,
236 K: Eq + Hash + Debug,
237 V: Eq + Debug,
238 {
239 let actual_value = self.actual().get(key.borrow());
240 if Some(value.borrow()) == actual_value {
241 self.new_result().do_ok()
242 } else if actual_value.is_none() {
243 self.new_result()
244 .add_formatted_fact(
245 "expected key to be mapped to value",
246 MapEntry::new(key.borrow(), value.borrow()),
247 )
248 .add_fact("but key was not found", format!("{:?}", key.borrow()))
249 .add_splitter()
250 .add_fact(
251 "though it did contain keys",
252 format!("{:?}", self.actual().keys()),
253 )
254 .do_fail()
255 } else {
256 self.new_result()
257 .add_formatted_fact(
258 "expected key to be mapped to value",
259 MapEntry::new(key.borrow(), value.borrow()),
260 )
261 .add_fact(
262 "but key was mapped to a different value",
263 format!("{:?}", actual_value.unwrap().borrow()),
264 )
265 .add_splitter()
266 .add_fact(
267 "though it did contain keys",
268 format!("{:?}", self.actual().keys()),
269 )
270 .do_fail()
271 }
272 }
273
274 fn does_not_contain_entry<BK, BV>(&self, key: BK, value: BV) -> R
275 where
276 BK: Borrow<K>,
277 BV: Borrow<V>,
278 K: Eq + Hash + Debug,
279 V: Eq + Debug,
280 {
281 let actual_value = self.actual().get(key.borrow());
282 if Some(value.borrow()) == actual_value {
283 self.new_result()
284 .add_formatted_fact(
285 "expected to not contain entry",
286 MapEntry::new(key.borrow(), value.borrow()),
287 )
288 .add_simple_fact("but entry was found")
289 .add_splitter()
290 .add_fact(
292 "though it did contain",
293 format!("{:?}", self.actual().keys()),
294 )
295 .do_fail()
296 } else {
297 self.new_result().do_ok()
298 }
299 }
300
301 fn contains_at_least<BM, OML>(&self, expected: BM) -> R
302 where
303 K: Eq + Hash + Debug,
304 V: Eq + Debug,
305 OML: MapLike<K, V> + 'a,
306 BM: Borrow<OML> + 'a,
307 {
308 let expected_map = expected.borrow();
309 let diff = MapComparison::from_map_like(self.actual(), expected_map, None);
310 if diff.common.len() == expected_map.len() {
311 return self.new_result().do_ok();
312 }
313 let (result, splitter) = feed_missing_entries_facts(
314 "at least",
315 self.new_result(),
316 &diff,
317 expected_map.len(),
318 false,
319 );
320 feed_different_values_facts(result, &diff, splitter)
321 .0
322 .do_fail()
323 }
324
325 fn does_not_contain_any<BM: 'a, OML: 'a>(&self, expected: BM) -> R
326 where
327 K: Eq + Hash + Debug,
328 V: Eq + Debug,
329 OML: MapLike<K, V> + 'a,
330 BM: Borrow<OML> + 'a,
331 {
332 let expected_map = expected.borrow();
333 let diff = MapComparison::from_map_like(self.actual(), expected_map, None);
334 if !diff.common.is_empty() {
335 let mut result = self
336 .new_result()
337 .add_simple_fact(format!("found {} unexpected entries", diff.common.len()))
338 .add_splitter();
339 for (key, value) in diff.common {
340 result = result.add_simple_formatted_fact(MapEntry::new(key, value));
341 }
342 return result.do_fail();
343 }
344 return self.new_result().do_ok();
345 }
346
347 fn contains_exactly<BM, OML>(&self, expected: BM) -> R
348 where
349 K: Eq + Hash + Debug,
350 V: Eq + Debug,
351 OML: MapLike<K, V> + 'a,
352 BM: Borrow<OML> + 'a,
353 {
354 let expected_map = expected.borrow();
355 let diff = MapComparison::from_map_like(self.actual(), expected_map, None);
356 if diff.extra.is_empty() && diff.missing.is_empty() && diff.different_values.is_empty() {
357 return self.new_result().do_ok();
358 }
359 let (result, splitter) = feed_missing_entries_facts(
360 "exactly",
361 self.new_result(),
362 &diff,
363 expected_map.len(),
364 false,
365 );
366 let (result, splitter) = feed_extra_entries_facts(result, &diff, splitter);
367 feed_different_values_facts(result, &diff, splitter)
368 .0
369 .do_fail()
370 }
371
372 fn key_set<'b>(&'b self) -> Subject<ML::It<'b>, (), R>
373 where
374 K: 'b,
375 {
376 self.new_owned_subject(
377 self.actual().keys_iter(),
378 Some(format!("{}.keys()", self.description_or_expr())),
379 (),
380 )
381 }
382}
383
384impl<'a, K, V, ML, R> OrderedMapAssertion<'a, K, V, ML, R> for Subject<'a, ML, (), R>
385where
386 AssertionResult: AssertionStrategy<R>,
387 K: 'a + Eq + Ord,
388 ML: OrderedMapLike<K, V>,
389{
390 fn contains_exactly_in_order<BM, OML>(&self, expected: BM) -> R
391 where
392 K: Eq + Ord + Debug,
393 V: Eq + Debug,
394 OML: OrderedMapLike<K, V> + 'a,
395 BM: Borrow<OML> + 'a,
396 {
397 let map_diff = MapComparison::from_map_like(
398 self.actual(),
399 expected.borrow(),
400 Some(SequenceOrderComparison::Strict),
401 );
402 let (values_assertion_result, values_different) =
403 feed_different_values_facts(self.new_result(), &map_diff, false);
404 let key_order_comparison = map_diff.key_order_comparison.unwrap();
405 let (order_assertion_result, order_ok) = super::iterator::check_contains_exactly_in_order(
406 key_order_comparison,
407 self.actual().keys().into_iter(),
408 expected.borrow().keys().into_iter(),
409 values_assertion_result,
410 );
411
412 if order_ok && !values_different {
413 order_assertion_result.do_ok()
414 } else {
415 order_assertion_result.do_fail()
416 }
417 }
418
419 fn contains_all_of_in_order<BM, OML>(&self, expected: BM) -> R
420 where
421 K: Eq + Ord + Debug,
422 V: Eq + Debug,
423 OML: OrderedMapLike<K, V> + 'a,
424 BM: Borrow<OML> + 'a,
425 {
426 let map_diff = MapComparison::from_map_like(
427 self.actual(),
428 expected.borrow(),
429 Some(SequenceOrderComparison::Relative),
430 );
431 let (values_assertion_result, values_different) =
432 feed_different_values_facts(self.new_result(), &map_diff, false);
433 let key_order_comparison = map_diff.key_order_comparison.unwrap();
434 let (order_assertion_result, order_ok) = super::iterator::check_contains_all_of_in_order(
435 key_order_comparison,
436 self.actual().keys().into_iter(),
437 expected.borrow().keys().into_iter(),
438 values_assertion_result,
439 );
440
441 if order_ok && !values_different {
442 order_assertion_result.do_ok()
443 } else {
444 order_assertion_result.do_fail()
445 }
446 }
447}
448
449fn pluralize<'a>(count: usize, single: &'a str, plural: &'a str) -> &'a str {
450 if count == 1 {
451 single
452 } else {
453 plural
454 }
455}
456
457fn feed_different_values_facts<K: Eq + Debug, V: Eq + Debug>(
458 mut result: AssertionResult,
459 diff: &MapComparison<&K, &V>,
460 splitter: bool,
461) -> (AssertionResult, bool) {
462 let has_diffs = !diff.different_values.is_empty();
463 if has_diffs {
464 if splitter {
465 result = result.add_splitter();
466 }
467 result = result
468 .add_fact(
469 "expected to contain the same entries",
470 format!(
471 "but found {} {} different",
472 diff.different_values.len(),
473 pluralize(
474 diff.different_values.len(),
475 "entry that is",
476 "entries that are",
477 )
478 ),
479 )
480 .add_splitter();
481 let mut ordered_diffs: Vec<_> = diff.different_values.iter().collect();
482 ordered_diffs.sort_by(|d1, d2| format!("{:?}", d1.key).cmp(&format!("{:?}", d2.key)));
483 result = result.add_formatted_values_fact(
484 format!(
485 "{} mapped to unexpected {}",
486 pluralize(diff.different_values.len(), "key was", "keys were"),
487 pluralize(diff.different_values.len(), "value", "values")
488 ),
489 ordered_diffs,
490 );
491 }
492 (result, has_diffs)
493}
494
495fn feed_missing_entries_facts<K: Eq + Debug, V: Eq + Debug>(
496 containment_spec: &str,
497 mut result: AssertionResult,
498 diff: &MapComparison<&K, &V>,
499 expected_length: usize,
500 splitter: bool,
501) -> (AssertionResult, bool) {
502 let has_diffs = !diff.missing.is_empty();
503 if has_diffs {
504 if splitter {
505 result = result.add_splitter();
506 }
507 result = result
508 .add_fact(
509 format!(
510 "expected to contain {} {} provided {}",
511 containment_spec,
512 expected_length,
513 pluralize(expected_length, "entry", "entries")
514 ),
515 format!(
516 "but {} {} not found",
517 diff.missing.len(),
518 pluralize(diff.missing.len(), "entry", "entries")
519 ),
520 )
521 .add_splitter();
522 result = result.add_formatted_values_fact(
523 format!(
524 "{} not found",
525 pluralize(diff.missing.len(), "entry was", "entries were")
526 ),
527 (&diff.missing)
528 .into_iter()
529 .map(|(k, v)| MapEntry::new(k, v))
530 .collect(),
531 );
532 }
533 (result, has_diffs)
534}
535
536fn feed_extra_entries_facts<K: Eq + Debug, V: Eq + Debug>(
537 mut result: AssertionResult,
538 diff: &MapComparison<&K, &V>,
539 splitter: bool,
540) -> (AssertionResult, bool) {
541 let has_diffs = !diff.extra.is_empty();
542 if has_diffs {
543 if splitter {
544 result = result.add_splitter();
545 }
546 result = result
547 .add_fact(
548 "expected to not contain additional entries".to_string(),
549 format!(
550 "but {} additional {} found",
551 diff.extra.len(),
552 pluralize(diff.extra.len(), "entry was", "entries were")
553 ),
554 )
555 .add_splitter();
556 result = result.add_formatted_values_fact(
557 format!(
558 "unexpected {} found",
559 pluralize(diff.extra.len(), "entry was", "entries were")
560 ),
561 (&diff.extra)
562 .into_iter()
563 .map(|(k, v)| MapEntry::new(k, v))
564 .collect(),
565 );
566 }
567 (result, has_diffs)
568}
569
570struct MapEntry<'a, K: Debug, V: Debug> {
571 key: &'a K,
572 value: &'a V,
573}
574
575impl<'a, K: Debug, V: Debug> MapEntry<'a, K, V> {
576 fn new(key: &'a K, value: &'a V) -> MapEntry<'a, K, V> {
577 Self { key, value }
578 }
579}
580
581impl<'a, K: Debug, V: Debug> Debug for MapEntry<'a, K, V> {
582 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
583 f.write_str(format!("{:?} ⟶ {:?}", self.key, self.value).as_str())
584 }
585}
586
587impl<K: Debug, V: PartialEq + Debug> Debug for MapValueDiff<&K, &V> {
588 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
589 f.write_str(
590 format!(
591 r#"{{ key: {:?}, expected: {:?}, actual: {:?} }}"#,
592 self.key, self.actual_value, self.expected_value
593 )
594 .as_str(),
595 )
596 }
597}
598
599#[cfg(test)]
600mod tests {
601 use crate::testing::*;
602 use crate::{assert_that, check_that, Fact, IteratorAssertion, SetAssertion};
603 use std::collections::{BTreeMap, HashMap};
604
605 use super::*;
606
607 #[test]
608 fn has_length() {
609 let map_empty: HashMap<&str, &str> = HashMap::new();
610 assert_that!(map_empty).has_length(0);
611
612 let mut map_with_two_entry = HashMap::new();
613 map_with_two_entry.insert("1", "y");
614 map_with_two_entry.insert("2", "z");
615 assert_that!(map_with_two_entry).has_length(2);
616
617 assert_that!(check_that!(map_empty).has_length(1)).facts_are(vec![
619 Fact::new("value of", "map_empty.len()"),
620 Fact::new("expected", "1"),
621 Fact::new("actual", "0"),
622 ])
623 }
624
625 #[test]
626 fn is_empty() {
627 let map_empty: HashMap<&str, &str> = HashMap::new();
628 assert_that!(map_empty).is_empty();
629
630 assert_that!(check_that!(HashMap::from([("a", "b")])).is_empty()).facts_are(vec![
632 Fact::new_simple_fact("expected to be empty"),
633 Fact::new_splitter(),
634 Fact::new_multi_value_fact("actual", vec![r#""a""#]),
635 ])
636 }
637
638 #[test]
639 fn is_not_empty() {
640 let non_empty: HashMap<&str, &str> = HashMap::from([("a", "b")]);
641 assert_that!(non_empty).is_not_empty();
642
643 let empty_map: HashMap<&str, &str> = HashMap::new();
645 assert_that!(check_that!(empty_map).is_not_empty()).facts_are(vec![
646 Fact::new_simple_fact("expected to be non-empty"),
647 Fact::new_splitter(),
648 Fact::new("actual", "[]"),
649 ])
650 }
651
652 #[test]
653 fn contains_key() {
654 let mut map_abc: HashMap<&str, &str> = HashMap::new();
655 map_abc.insert("a", "1");
656 map_abc.insert("b", "2");
657 map_abc.insert("c", "3");
658 assert_that!(map_abc).contains_key("a");
659 assert_that!(map_abc).contains_key("b");
660 assert_that!(map_abc).contains_key("c");
661
662 let result = check_that!(map_abc).contains_key("not exist");
664 assert_that!(result).facts_are_at_least(vec![
665 Fact::new("expected to contain", r#""not exist""#),
666 Fact::new_simple_fact("but did not"),
667 ]);
668 assert_that!(result)
669 .fact_keys()
670 .contains(&"though it did contain".to_string());
671 }
673
674 #[test]
675 fn does_not_contain_key() {
676 let mut map_abc: HashMap<&str, &str> = HashMap::new();
677 map_abc.insert("a", "1");
678 map_abc.insert("b", "2");
679 map_abc.insert("c", "3");
680 assert_that!(map_abc).does_not_contain_key("x");
681 assert_that!(map_abc).does_not_contain_key("y");
682
683 let result = check_that!(map_abc).does_not_contain_key("a");
685 assert_that!(result).facts_are_at_least(vec![
686 Fact::new("expected to not contain", r#""a""#),
687 Fact::new_simple_fact("but element was found"),
688 ]);
689 assert_that!(result)
690 .fact_keys()
691 .contains(&"though it did contain".to_string());
692 }
694
695 #[test]
696 fn key_set() {
697 let mut map_abc: HashMap<&str, &str> = HashMap::new();
698 map_abc.insert("a", "1");
699 map_abc.insert("b", "2");
700 map_abc.insert("c", "3");
701 assert_that!(map_abc).key_set().contains(&"a");
702 assert_that!(map_abc).key_set().contains(&"b");
703 assert_that!(map_abc).key_set().contains(&"c");
704
705 let result = check_that!(map_abc).key_set().contains(&"not exist");
707 assert_that!(result).facts_are_at_least(vec![
708 Fact::new("value of", "map_abc.keys()"),
709 Fact::new("expected to contain", r#""not exist""#),
710 Fact::new_simple_fact("but did not"),
711 ]);
714 assert_that!(result)
715 .fact_keys()
716 .contains(&"though it did contain".to_string());
717 }
719
720 #[test]
721 fn contains_entry() {
722 let mut map_abc: HashMap<&str, &str> = HashMap::new();
723 map_abc.insert("a", "1");
724 map_abc.insert("b", "2");
725 map_abc.insert("c", "3");
726 assert_that!(map_abc).contains_entry("a", "1");
727 assert_that!(map_abc).contains_entry("b", "2");
728 assert_that!(map_abc).contains_entry("c", "3");
729
730 let result = check_that!(map_abc).contains_entry("not exist", "1");
732 assert_that!(result).facts_are_at_least(vec![
733 Fact::new("expected key to be mapped to value", r#""not exist" ⟶ "1""#),
734 Fact::new("but key was not found", r#""not exist""#),
735 Fact::new_splitter(),
736 ]);
737 assert_that!(result)
738 .fact_keys()
739 .contains(&"though it did contain keys".to_string());
740 let result = check_that!(map_abc).contains_entry("a", "2");
744 assert_that!(result).facts_are_at_least(vec![
745 Fact::new("expected key to be mapped to value", r#""a" ⟶ "2""#),
746 Fact::new("but key was mapped to a different value", r#""1""#),
747 Fact::new_splitter(),
748 ]);
749 assert_that!(result)
750 .fact_keys()
751 .contains(&"though it did contain keys".to_string());
752 }
754
755 #[test]
756 fn does_not_contain_entry() {
757 let mut map_abc: HashMap<&str, &str> = HashMap::new();
758 map_abc.insert("a", "1");
759 map_abc.insert("b", "2");
760 map_abc.insert("c", "3");
761
762 assert_that!(map_abc).does_not_contain_entry("x", "1");
764 assert_that!(map_abc).does_not_contain_entry("a", "2");
766 assert_that!(map_abc).does_not_contain_entry("b", "3");
767 assert_that!(map_abc).does_not_contain_entry("c", "4");
768
769 let result = check_that!(map_abc).does_not_contain_entry("a", "1");
771 assert_that!(result).facts_are_at_least(vec![
772 Fact::new("expected to not contain entry", r#""a" ⟶ "1""#),
773 Fact::new_simple_fact("but entry was found"),
774 Fact::new_splitter(),
775 ]);
776 assert_that!(result)
777 .fact_keys()
778 .contains(&"though it did contain".to_string());
779 }
780
781 #[test]
782 fn contains_at_least() {
783 let mut map_abc: HashMap<&str, &str> = HashMap::new();
784 map_abc.insert("a", "1");
785 map_abc.insert("b", "2");
786 map_abc.insert("c", "3");
787 assert_that!(map_abc).contains_at_least(HashMap::from([("a", "1")]));
788 assert_that!(map_abc).contains_at_least(HashMap::from([("a", "1"), ("b", "2")]));
789
790 let result = check_that!(map_abc).contains_at_least(HashMap::from([("not exist", "1")]));
792 assert_that!(result).facts_are_at_least(vec![
793 Fact::new(
794 "expected to contain at least 1 provided entry",
795 "but 1 entry not found",
796 ),
797 Fact::new_splitter(),
798 Fact::new_multi_value_fact("entry was not found", vec![r#""not exist" ⟶ "1""#]),
799 ]);
800
801 let result = check_that!(map_abc).contains_at_least(HashMap::from([("c", "5")]));
803 assert_that!(result).facts_are_at_least(vec![
804 Fact::new(
805 "expected to contain the same entries",
806 "but found 1 entry that is different",
807 ),
808 Fact::new_splitter(),
809 Fact::new_multi_value_fact(
810 r#"key was mapped to unexpected value"#,
811 vec![r#"{ key: "c", expected: "3", actual: "5" }"#],
812 ),
813 ]);
814
815 let result =
817 check_that!(map_abc).contains_at_least(HashMap::from([("not exist", "1"), ("c", "5")]));
818 assert_that!(result).facts_are_at_least(vec![
819 Fact::new(
820 "expected to contain at least 2 provided entries",
821 "but 1 entry not found",
822 ),
823 Fact::new_splitter(),
824 Fact::new_multi_value_fact("entry was not found", vec![r#""not exist" ⟶ "1""#]),
825 Fact::new_splitter(),
826 Fact::new(
827 "expected to contain the same entries",
828 "but found 1 entry that is different",
829 ),
830 Fact::new_splitter(),
831 Fact::new_multi_value_fact(
832 r#"key was mapped to unexpected value"#,
833 vec![r#"{ key: "c", expected: "3", actual: "5" }"#],
834 ),
835 ]);
836 }
837
838 #[test]
839 fn contains_exactly() {
840 let mut map_abc: HashMap<&str, &str> = HashMap::new();
841 map_abc.insert("a", "1");
842 map_abc.insert("b", "2");
843 map_abc.insert("c", "3");
844 assert_that!(map_abc).contains_exactly(HashMap::from([("a", "1"), ("c", "3"), ("b", "2")]));
845
846 let result = check_that!(map_abc).contains_exactly(HashMap::from([("not exist", "1")]));
848 assert_that!(result).facts_are_at_least(vec![
849 Fact::new(
850 "expected to contain exactly 1 provided entry",
851 "but 1 entry not found",
852 ),
853 Fact::new_splitter(),
854 Fact::new_multi_value_fact("entry was not found", vec![r#""not exist" ⟶ "1""#]),
855 ]);
856
857 let result = check_that!(HashMap::from([
859 ("a", "1"),
860 ("c", "3"),
861 ("b", "2"),
862 ("ex", "1")
863 ]))
864 .contains_exactly(map_abc);
865 assert_that!(result).facts_are_at_least(vec![
866 Fact::new(
867 "expected to not contain additional entries",
868 "but 1 additional entry was found",
869 ),
870 Fact::new_splitter(),
871 Fact::new_multi_value_fact("unexpected entry was found", vec![r#""ex" ⟶ "1""#]),
872 ]);
873
874 let result = check_that!(HashMap::from([("a", "1"), ("b", "f")]))
876 .contains_at_least(HashMap::from([("a", "2"), ("b", "g")]));
877 assert_that!(result).facts_are_at_least(vec![
878 Fact::new(
879 "expected to contain the same entries",
880 "but found 2 entries that are different",
881 ),
882 Fact::new_splitter(),
883 Fact::new_multi_value_fact(
884 r#"keys were mapped to unexpected values"#,
885 vec![
886 r#"{ key: "a", expected: "1", actual: "2" }"#,
887 r#"{ key: "b", expected: "f", actual: "g" }"#,
888 ],
889 ),
890 ]);
891
892 let result = check_that!(HashMap::from([("a", "1"), ("b", "2")]))
894 .contains_exactly(HashMap::from([("a", "2"), ("c", "2")]));
895 assert_that!(result).facts_are_at_least(vec![
896 Fact::new(
897 "expected to contain exactly 2 provided entries",
898 "but 1 entry not found",
899 ),
900 Fact::new_splitter(),
901 Fact::new_multi_value_fact("entry was not found", vec![r#""c" ⟶ "2""#]),
902 Fact::new_splitter(),
903 Fact::new(
904 "expected to not contain additional entries",
905 "but 1 additional entry was found",
906 ),
907 Fact::new_splitter(),
908 Fact::new_multi_value_fact("unexpected entry was found", vec![r#""b" ⟶ "2""#]),
909 Fact::new_splitter(),
910 Fact::new(
911 "expected to contain the same entries",
912 "but found 1 entry that is different",
913 ),
914 Fact::new_splitter(),
915 Fact::new_multi_value_fact(
916 r#"key was mapped to unexpected value"#,
917 vec![r#"{ key: "a", expected: "1", actual: "2" }"#],
918 ),
919 ]);
920 }
921
922 #[test]
923 fn does_not_contain_any() {
924 let mut map_abc: HashMap<&str, &str> = HashMap::new();
925 map_abc.insert("a", "1");
926 map_abc.insert("b", "2");
927 map_abc.insert("c", "3");
928
929 assert_that!(map_abc).does_not_contain_any(HashMap::from([
930 ("a", "2"),
931 ("b", "3"),
932 ("x", "1"),
933 ]));
934
935 let result = check_that!(map_abc).does_not_contain_any(HashMap::from([
936 ("a", "1"),
937 ("c", "3"),
938 ("x", "g"),
939 ]));
940 assert_that!(result).facts_are_at_least(vec![
941 Fact::new_simple_fact("found 2 unexpected entries"),
942 Fact::new_splitter(),
943 ]);
944 assert_that!(result).facts_are_at_least(vec![Fact::new_simple_fact(r#""c" ⟶ "3""#)]);
945 assert_that!(result).facts_are_at_least(vec![Fact::new_simple_fact(r#""a" ⟶ "1""#)]);
946 }
947
948 #[test]
949 fn supports_any_map() {
950 let empty: BTreeMap<String, String> = BTreeMap::new();
951 let tree_map = BTreeMap::from([("hello", "sorted_map"), ("world", "in")]);
952 assert_that!(tree_map).has_length(2);
953 assert_that!(empty).is_empty();
954 assert_that!(tree_map).is_not_empty();
955 assert_that!(tree_map).contains_key("hello");
956 assert_that!(tree_map).does_not_contain_key(&"key");
957 assert_that!(tree_map).key_set().contains(&"hello");
958 assert_that!(tree_map).contains_entry("hello", "sorted_map");
959 assert_that!(tree_map).does_not_contain_entry("hello", "other");
960 assert_that!(tree_map).contains_at_least(BTreeMap::from([("world", "in")]));
961 assert_that!(tree_map).contains_at_least(HashMap::from([("world", "in")]));
962 assert_that!(tree_map)
963 .contains_exactly(BTreeMap::from([("hello", "sorted_map"), ("world", "in")]));
964 assert_that!(tree_map)
965 .contains_exactly(HashMap::from([("hello", "sorted_map"), ("world", "in")]));
966 assert_that!(tree_map).does_not_contain_any(BTreeMap::from([("world", "nope")]));
967 assert_that!(tree_map).does_not_contain_any(HashMap::from([("world", "nope")]));
968 }
969
970 #[test]
971 fn contains_exactly_in_order() {
972 let tree_map = BTreeMap::from([("hello", "sorted_map"), ("world", "in")]);
973 assert_that!(tree_map)
974 .contains_exactly_in_order(BTreeMap::from([("hello", "sorted_map"), ("world", "in")]));
975
976 let result = check_that!(tree_map)
978 .contains_exactly_in_order(BTreeMap::from([("hello", "wrong"), ("world", "in")]));
979 assert_that!(result).facts_are_at_least(vec![
980 Fact::new(
981 "expected to contain the same entries",
982 "but found 1 entry that is different",
983 ),
984 Fact::new_splitter(),
985 Fact::new_multi_value_fact(
986 r#"key was mapped to unexpected value"#,
987 vec![r#"{ key: "hello", expected: "sorted_map", actual: "wrong" }"#],
988 ),
989 ]);
990
991 let result = check_that!(tree_map)
993 .contains_exactly_in_order(BTreeMap::from([("hello", "sorted_map"), ("was", "at")]));
994 assert_that!(result).facts_are(vec![
995 Fact::new("missing (1)", r#"["was"]"#),
996 Fact::new("unexpected (1)", r#"["world"]"#),
997 Fact::new_splitter(),
998 Fact::new_multi_value_fact("expected", vec![r#""hello""#, r#""was""#]),
999 Fact::new_multi_value_fact("actual", vec![r#""hello""#, r#""world""#]),
1000 ]);
1001
1002 let result = check_that!(tree_map)
1004 .contains_exactly_in_order(BTreeMap::from([("hello", "wrong"), ("was", "at")]));
1005 assert_that!(result).facts_are(vec![
1006 Fact::new(
1007 "expected to contain the same entries",
1008 "but found 1 entry that is different",
1009 ),
1010 Fact::new_splitter(),
1011 Fact::new_multi_value_fact(
1012 r#"key was mapped to unexpected value"#,
1013 vec![r#"{ key: "hello", expected: "sorted_map", actual: "wrong" }"#],
1014 ),
1015 Fact::new("missing (1)", r#"["was"]"#),
1016 Fact::new("unexpected (1)", r#"["world"]"#),
1017 Fact::new_splitter(),
1018 Fact::new_multi_value_fact("expected", vec![r#""hello""#, r#""was""#]),
1019 Fact::new_multi_value_fact("actual", vec![r#""hello""#, r#""world""#]),
1020 ]);
1021 }
1022
1023 #[test]
1024 fn contains_all_of_in_order() {
1025 let tree_map = BTreeMap::from([("hello", "sorted_map"), ("lang", "en"), ("world", "in")]);
1026 assert_that!(tree_map)
1027 .contains_all_of_in_order(BTreeMap::from([("hello", "sorted_map"), ("world", "in")]));
1028
1029 let result = check_that!(tree_map)
1031 .contains_exactly_in_order(BTreeMap::from([("hello", "wrong"), ("ww", "w")]));
1032 assert_that!(result).facts_are(vec![
1033 Fact::new(
1034 "expected to contain the same entries",
1035 "but found 1 entry that is different",
1036 ),
1037 Fact::new_splitter(),
1038 Fact::new_multi_value_fact(
1039 r#"key was mapped to unexpected value"#,
1040 vec![r#"{ key: "hello", expected: "sorted_map", actual: "wrong" }"#],
1041 ),
1042 Fact::new("missing (1)", r#"["ww"]"#),
1043 Fact::new("unexpected (2)", r#"["lang", "world"]"#),
1044 Fact::new_splitter(),
1045 Fact::new_multi_value_fact("expected", vec![r#""hello""#, r#""ww""#]),
1046 Fact::new_multi_value_fact("actual", vec![r#""hello""#, r#""lang""#, r#""world""#]),
1047 ]);
1048 }
1049}