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