1use crate::JsonType;
2use crate::expect::ExpectObject;
3use crate::expect::ops::expect_array::ExpectArraySubOp;
4use crate::expect_core::Context;
5use crate::expect_core::ExpectOp;
6use crate::expect_core::ExpectOpResult;
7use crate::expect_core::expect_op;
8use serde_json::Value;
9use std::fmt::Debug;
10
11#[expect_op(internal, name = "array")]
12#[derive(Debug, Clone, Default, PartialEq)]
13pub struct ExpectArray {
14 sub_ops: Vec<ExpectArraySubOp>,
15}
16
17impl ExpectArray {
18 pub(crate) fn new() -> Self {
19 Self { sub_ops: vec![] }
20 }
21
22 pub fn empty(mut self) -> Self {
23 self.sub_ops.push(ExpectArraySubOp::Empty);
24 self
25 }
26
27 pub fn not_empty(mut self) -> Self {
28 self.sub_ops.push(ExpectArraySubOp::NotEmpty);
29 self
30 }
31
32 pub fn len(mut self, len: usize) -> Self {
33 self.sub_ops.push(ExpectArraySubOp::Len(len));
34 self
35 }
36
37 pub fn min_len(mut self, min_len: usize) -> Self {
38 self.sub_ops.push(ExpectArraySubOp::MinLen(min_len));
39 self
40 }
41
42 pub fn max_len(mut self, max_len: usize) -> Self {
43 self.sub_ops.push(ExpectArraySubOp::MaxLen(max_len));
44 self
45 }
46
47 pub fn contains<I, V>(mut self, expected_values: I) -> Self
48 where
49 I: IntoIterator<Item = V>,
50 V: Into<Value>,
51 {
52 let inner_expected_values = expected_values
53 .into_iter()
54 .map(Into::into)
55 .collect::<Vec<_>>();
56 self.sub_ops
57 .push(ExpectArraySubOp::Contains(inner_expected_values));
58 self
59 }
60
61 pub fn eq_unordered<I, V>(mut self, expected_values: I) -> Self
65 where
66 I: IntoIterator<Item = V>,
67 V: Into<Value>,
68 {
69 let inner_expected_values = expected_values
70 .into_iter()
71 .map(Into::into)
72 .collect::<Vec<_>>();
73 self.sub_ops
74 .push(ExpectArraySubOp::EqUnordered(inner_expected_values));
75 self
76 }
77
78 pub fn all<V>(mut self, expected: V) -> Self
110 where
111 V: Into<Value>,
112 {
113 self.sub_ops
114 .push(ExpectArraySubOp::AllEqual(expected.into()));
115 self
116 }
117
118 pub fn all_contains<V>(mut self, expected: V) -> Self
176 where
177 V: Into<Value>,
178 {
179 let obj_contains = ExpectObject::new().contains(expected);
180 self.sub_ops
181 .push(ExpectArraySubOp::AllEqual(obj_contains.into()));
182
183 self
184 }
185
186 pub fn unique(mut self) -> Self {
215 self.sub_ops.push(ExpectArraySubOp::AllUnique);
216 self
217 }
218}
219
220impl ExpectOp for ExpectArray {
221 fn on_array(&self, context: &mut Context, received: &[Value]) -> ExpectOpResult<()> {
222 for sub_op in &self.sub_ops {
223 sub_op.on_array(self, context, received)?;
224 }
225
226 Ok(())
227 }
228
229 fn debug_supported_types(&self) -> &'static [JsonType] {
230 &[JsonType::Array]
231 }
232}
233
234#[cfg(test)]
235mod test_contains {
236 use crate::expect;
237 use crate::expect_json_eq;
238 use pretty_assertions::assert_eq;
239 use serde_json::json;
240
241 #[test]
242 fn it_should_be_equal_for_identical_numeric_arrays() {
243 let left = json!([1, 2, 3]);
244 let right = json!(expect::array().contains([1, 2, 3]));
245
246 let output = expect_json_eq(&left, &right);
247 assert!(output.is_ok());
248 }
249
250 #[test]
251 fn it_should_be_equal_for_reversed_identical_numeric_arrays() {
252 let left = json!([1, 2, 3]);
253 let right = json!(expect::array().contains([3, 2, 1]));
254
255 let output = expect_json_eq(&left, &right);
256 assert!(output.is_ok());
257 }
258
259 #[test]
260 fn it_should_be_equal_for_partial_contains() {
261 let left = json!([0, 1, 2, 3, 4, 5]);
262 let right = json!(expect::array().contains([1, 2, 3]));
263
264 let output = expect_json_eq(&left, &right);
265 assert!(output.is_ok());
266 }
267
268 #[test]
269 fn it_should_error_for_totall_different_values() {
270 let left = json!([0, 1, 2, 3]);
271 let right = json!(expect::array().contains([4, 5, 6]));
272
273 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
274 assert_eq!(
275 output,
276 r#"Json array at root does not contain expected value:
277 expected array to contain 4, but it was not found.
278 received [0, 1, 2, 3]"#
279 );
280 }
281
282 #[test]
283 fn it_should_be_ok_for_empty_contains() {
284 let left = json!([0, 1, 2, 3]);
285 let right = json!(expect::array().contains([] as [u32; 0]));
286
287 let output = expect_json_eq(&left, &right);
288 assert!(output.is_ok());
289 }
290
291 #[test]
292 fn it_should_error_if_used_against_the_wrong_type() {
293 let left = json!("🦊");
294 let right = json!(expect::array().contains([4, 5, 6]));
295
296 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
297 assert_eq!(
298 output,
299 r#"Json expect::array() at root, received wrong type:
300 expected array
301 received string "🦊""#
302 );
303 }
304
305 #[test]
306 fn it_should_handle_nested_contains() {
307 let left = json!([
308 {
309 "text": "Hello",
310 "author": "Jane Candle"
311 },
312 {
313 "text": "Goodbye",
314 "author": "John Lighthouse"
315 }
316 ]);
317
318 let right = json!(expect::array().contains([json!({
319 "text": "Hello",
320 "author": expect::string().contains("Jane"),
321 }),]));
322
323 let output = expect_json_eq(&left, &right);
324 assert!(output.is_ok(), "{}", output.unwrap_err().to_string());
325 }
326
327 #[test]
328 fn it_should_fail_nested_contains_that_do_not_match() {
329 let left = json!([
330 {
331 "text": "Hello",
332 "author": "Jane Candle"
333 },
334 {
335 "text": "Goodbye",
336 "author": "John Lighthouse"
337 }
338 ]);
339
340 let right = json!(expect::array().contains([json!({
341 "text": "Hello",
342 "author": expect::string().contains("🦊"),
343 }),]));
344
345 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
346 assert_eq!(
347 output,
348 r#"Json array at root does not contain expected value:
349 expected array to contain {
350 "author": expect::string(),
351 "text": "Hello"
352 }, but it was not found.
353 received [
354 {
355 "author": "Jane Candle",
356 "text": "Hello"
357 },
358 {
359 "author": "John Lighthouse",
360 "text": "Goodbye"
361 }
362 ]"#
363 );
364 }
365}
366
367#[cfg(test)]
368mod test_empty {
369 use crate::expect;
370 use crate::expect_json_eq;
371 use pretty_assertions::assert_eq;
372 use serde_json::json;
373
374 #[test]
375 fn it_should_pass_when_array_is_empty() {
376 let left = json!([]);
377 let right = json!(expect::array().empty());
378
379 let output = expect_json_eq(&left, &right);
380 assert!(output.is_ok(), "assertion error: {output:#?}");
381 }
382
383 #[test]
384 fn it_should_fail_when_array_is_not_empty() {
385 let left = json!([1, 2, 3]);
386 let right = json!(expect::array().empty());
387
388 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
389 assert_eq!(
390 output,
391 r#"Json expect::array() error at root:
392 expected empty array
393 received [1, 2, 3]"#
394 );
395 }
396}
397
398#[cfg(test)]
399mod test_not_empty {
400 use crate::expect;
401 use crate::expect_json_eq;
402 use pretty_assertions::assert_eq;
403 use serde_json::json;
404
405 #[test]
406 fn it_should_pass_when_array_is_not_empty() {
407 let left = json!([1]);
408 let right = json!(expect::array().not_empty());
409
410 let output = expect_json_eq(&left, &right);
411 assert!(output.is_ok(), "assertion error: {output:#?}");
412 }
413
414 #[test]
415 fn it_should_fail_when_array_is_empty() {
416 let left = json!([]);
417 let right = json!(expect::array().not_empty());
418
419 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
420 assert_eq!(
421 output,
422 r#"Json expect::array() error at root:
423 expected non-empty array
424 received []"#
425 );
426 }
427}
428
429#[cfg(test)]
430mod test_min_len {
431 use crate::expect;
432 use crate::expect_json_eq;
433 use pretty_assertions::assert_eq;
434 use serde_json::json;
435
436 #[test]
437 fn it_should_pass_when_array_has_exactly_enough_elements() {
438 let left = json!([1, 2, 3]);
439 let right = json!(expect::array().min_len(3));
440
441 let output = expect_json_eq(&left, &right);
442 assert!(output.is_ok(), "assertion error: {output:#?}");
443 }
444
445 #[test]
446 fn it_should_pass_when_array_has_more_than_enough_elements() {
447 let left = json!([1, 2, 3, 4, 5]);
448 let right = json!(expect::array().min_len(3));
449
450 let output = expect_json_eq(&left, &right);
451 assert!(output.is_ok(), "assertion error: {output:#?}");
452 }
453
454 #[test]
455 fn it_should_fail_when_array_has_too_few_elements() {
456 let left = json!([1, 2, 3]);
457 let right = json!(expect::array().min_len(4));
458
459 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
460 assert_eq!(
461 output,
462 r#"Json expect::array() error at root:
463 expected array to have at least 4 elements, but it has 3.
464 received [1, 2, 3]"#
465 );
466 }
467}
468
469#[cfg(test)]
470mod test_len {
471 use crate::expect;
472 use crate::expect_json_eq;
473 use pretty_assertions::assert_eq;
474 use serde_json::json;
475
476 #[test]
477 fn it_should_pass_when_array_has_exactly_enough_elements() {
478 let left = json!([1, 2, 3]);
479 let right = json!(expect::array().len(3));
480
481 let output = expect_json_eq(&left, &right);
482 assert!(output.is_ok(), "assertion error: {output:#?}");
483 }
484
485 #[test]
486 fn it_should_fail_when_array_has_more_than_enough_elements() {
487 let left = json!([1, 2, 3, 4, 5]);
488 let right = json!(expect::array().len(3));
489
490 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
491 assert_eq!(
492 output,
493 r#"Json expect::array() error at root:
494 expected array to have 3 elements, but it has 5.
495 received [1, 2, 3, 4, 5]"#
496 );
497 }
498
499 #[test]
500 fn it_should_fail_when_array_has_too_few_elements() {
501 let left = json!([1, 2, 3]);
502 let right = json!(expect::array().len(4));
503
504 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
505 assert_eq!(
506 output,
507 r#"Json expect::array() error at root:
508 expected array to have 4 elements, but it has 3.
509 received [1, 2, 3]"#
510 );
511 }
512}
513
514#[cfg(test)]
515mod test_max_len {
516 use crate::expect;
517 use crate::expect_json_eq;
518 use pretty_assertions::assert_eq;
519 use serde_json::json;
520
521 #[test]
522 fn it_should_pass_when_array_has_exactly_enough_elements() {
523 let left = json!([1, 2, 3]);
524 let right = json!(expect::array().max_len(3));
525
526 let output = expect_json_eq(&left, &right);
527 assert!(output.is_ok(), "assertion error: {output:#?}");
528 }
529
530 #[test]
531 fn it_should_pass_when_array_has_less_than_enough_elements() {
532 let left = json!([1, 2]);
533 let right = json!(expect::array().max_len(6));
534
535 let output = expect_json_eq(&left, &right);
536 assert!(output.is_ok(), "assertion error: {output:#?}");
537 }
538
539 #[test]
540 fn it_should_fail_when_array_has_too_few_elements() {
541 let left = json!([1, 2, 3, 4]);
542 let right = json!(expect::array().max_len(3));
543
544 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
545 assert_eq!(
546 output,
547 r#"Json expect::array() error at root:
548 expected array to have at most 3 elements, but it has 4.
549 received [1, 2, 3, 4]"#
550 );
551 }
552}
553
554#[cfg(test)]
555mod test_eq_unordered {
556 use crate::expect;
557 use crate::expect_json_eq;
558 use pretty_assertions::assert_eq;
559 use serde_json::json;
560
561 #[test]
562 fn it_should_pass_when_arrays_match_unordered() {
563 let left = json!([1, 2, 3]);
564 let right = json!(expect::array().eq_unordered([3, 2, 1]));
565
566 let output = expect_json_eq(&left, &right);
567 assert!(output.is_ok(), "assertion error: {output:#?}");
568 }
569
570 #[test]
571 fn it_should_fail_when_arrays_do_not_match_unordered() {
572 let left = json!([1, 2, 3]);
573 let right = json!(expect::array().eq_unordered([4, 5, 6]));
574
575 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
576 assert_eq!(
577 output,
578 r#"Json expect::array() error at root, mismatch:
579 expected array (up to order): [4, 5, 6],
580 received array: [1, 2, 3]"#
581 );
582 }
583
584 #[test]
585 fn it_should_fail_when_arrays_have_different_lengths() {
586 let left = json!([1, 2, 3]);
587 let right = json!(expect::array().eq_unordered([1, 2, 3, 4]));
588 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
589 assert_eq!(
590 output,
591 r#"Json expect::array() error at root, mismatch:
592 expected array (up to order): [1, 2, 3, 4],
593 received array: [1, 2, 3]"#
594 );
595 }
596
597 #[test]
598 fn it_should_pass_with_complex_matches() {
599 let left = json!(["Alice", "Bob", "Charlie"]);
600 let right = json!(expect::array().eq_unordered([
601 expect::string().contains("C"),
602 expect::string().contains("A"),
603 expect::string().contains("B"),
604 ]));
605 let output = expect_json_eq(&left, &right);
606 assert!(output.is_ok(), "assertion error: {output:#?}");
607 }
608
609 #[test]
610 fn it_should_pass_not_using_greedy_matching() {
611 let left = json!(["Alice", "Bob", "Charlie"]);
614 let right = json!(expect::array().eq_unordered([
615 expect::string(),
616 expect::string().contains("B"),
617 expect::string().contains("A"),
618 ]));
619 let output = expect_json_eq(&left, &right);
620 assert!(output.is_ok(), "assertion error: {output:#?}");
621 }
622
623 #[test]
624 fn it_should_pass_with_equal_elements() {
625 let left = json!(["Alice", "Alice", "Alice"]);
626 let right = json!(expect::array().eq_unordered([
627 expect::string().contains("A"),
628 expect::string().contains("A"),
629 expect::string().contains("A"),
630 ]));
631 let output = expect_json_eq(&left, &right);
632 assert!(output.is_ok(), "assertion error: {output:#?}");
633 }
634
635 #[test]
636 fn it_should_pass_on_a_multiset_with_bijection() {
637 let left = json!(["Alice", "Alice", "Bob"]);
638 let right = json!(expect::array().eq_unordered(["Bob", "Alice", "Alice"]));
639 let output = expect_json_eq(&left, &right);
640 assert!(output.is_ok(), "assertion error: {output:#?}");
641 }
642
643 #[test]
644 fn it_should_fail_when_there_is_no_bijection() {
645 let left = json!(["Alice", "Bob", "Boris"]);
648 let right = json!(expect::array().eq_unordered([
649 expect::string().contains("A"),
650 expect::string().contains("A"),
651 expect::string().contains("B"),
652 ]));
653 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
654 assert_eq!(
655 output,
656 r#"Json expect::array() error at root, mismatch:
657 expected array (up to order): [
658 expect::string(),
659 expect::string(),
660 expect::string()
661 ],
662 received array: ["Alice", "Bob", "Boris"]"#
663 );
664 }
665}
666
667#[cfg(test)]
668mod test_all {
669 use crate::expect;
670 use crate::expect_json_eq;
671 use pretty_assertions::assert_eq;
672 use serde_json::json;
673
674 #[test]
675 fn it_should_pass_when_array_is_empty() {
676 let left = json!([]);
677 let right = json!(expect::array().all(expect::string()));
678
679 let output = expect_json_eq(&left, &right);
680 assert!(output.is_ok(), "assertion error: {output:#?}");
681 }
682
683 #[test]
684 fn it_should_pass_with_mix_of_operations() {
685 let left = json!([
686 "123e4567-e89b-12d3-a456-426614174000",
687 "123e4567-e89b-12d3-a456-426614174001",
688 "123e4567-e89b-12d3-a456-426614174002",
689 ]);
690 let right = json!(expect::array().all(expect::uuid()).len(3).unique());
691
692 let output = expect_json_eq(&left, &right);
693 assert!(output.is_ok(), "assertion error: {output:#?}");
694 }
695
696 #[test]
697 fn it_should_fail_with_mix_of_operations() {
698 let left = json!([
699 "123e4567-e89b-12d3-a456-426614174000",
700 "123e4567-e89b-12d3-a456-426614174001",
701 "123e4567-e89b-12d3-a456-426614174002",
702 "123e4567-e89b-12d3-a456-426614174003",
703 ]);
704 let right = json!(expect::array().all(expect::uuid()).len(3).unique());
705
706 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
707 assert_eq!(
708 output,
709 r#"Json expect::array() error at root:
710 expected array to have 3 elements, but it has 4.
711 received ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001", "123e4567-e89b-12d3-a456-426614174002", "123e4567-e89b-12d3-a456-426614174003"]"#
712 );
713 }
714
715 #[test]
716 fn it_should_fail_when_array_values_do_not_match_expect_op() {
717 let left = json!([1, 2, 3]);
718 let right = json!(expect::array().all(expect::string()));
719
720 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
721 assert_eq!(
722 output,
723 r#"Json expect::string() at root[0], received wrong type:
724 expected string
725 received integer 1
726 received full array [1, 2, 3]"#
727 );
728 }
729
730 #[test]
731 fn it_should_fail_when_array_values_do_not_match_values() {
732 let left = json!([1, 2, 3]);
733 let right = json!(expect::array().all("🦊"));
734
735 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
736 assert_eq!(
737 output,
738 r#"Json values at root[0] are different types:
739 expected string "🦊"
740 received integer 1
741 received full array [1, 2, 3]"#
742 );
743 }
744
745 #[test]
746 fn it_should_pass_when_array_values_do_match_expect_op() {
747 let left = json!(["alice@example.com", "bob@example.com"]);
748 let right = json!(expect::array().all(expect::email()));
749
750 let output = expect_json_eq(&left, &right);
751 assert!(output.is_ok(), "assertion error: {output:#?}");
752 }
753
754 #[test]
755 fn it_should_pass_when_array_values_do_match_values() {
756 let left = json!([1, 1, 1]);
757 let right = json!(expect::array().all(1));
758
759 let output = expect_json_eq(&left, &right);
760 assert!(output.is_ok(), "assertion error: {output:#?}");
761 }
762
763 #[test]
764 fn it_should_pass_when_array_values_do_match_complex_objects() {
765 let left = json!([
766 {
767 "name": "Alice Candles",
768 "email": "alice@example.com"
769 },
770 {
771 "name": "Bob Kettles",
772 "email": "bob@example.com"
773 },
774 ]);
775
776 let right = json!(expect::array().all(json!({
777 "name": expect::string().not_empty(),
778 "email": expect::email(),
779 })));
780
781 let output = expect_json_eq(&left, &right);
782 assert!(output.is_ok(), "assertion error: {output:#?}");
783 }
784
785 #[test]
786 fn it_should_not_pass_when_array_values_do_not_match_complex_objects() {
787 let left = json!([
788 {
789 "name": "Alice Candles",
790 "email": "alice@example.com"
791 },
792 {
793 "name": "",
794 "email": "bob@example.com"
795 },
796 ]);
797
798 let right = json!(expect::array().all(json!({
799 "name": expect::string().not_empty(),
800 "email": expect::email(),
801 })));
802
803 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
804 assert_eq!(
805 output,
806 r#"Json expect::string() error at root[1].name:
807 expected non-empty string
808 received ""
809 received full array [
810 {
811 "email": "alice@example.com",
812 "name": "Alice Candles"
813 },
814 {
815 "email": "bob@example.com",
816 "name": ""
817 }
818 ]"#
819 );
820 }
821
822 #[test]
823 fn it_should_pass_with_nested_contains() {
824 let left = json!([
825 {
826 "name": "Alice Candles",
827 "email": "alice@example.com"
828 },
829 {
830 "name": "Bob Kettles",
831 "email": "bob@example.com"
832 },
833 ]);
834
835 let right = json!(expect::array().all(expect::object().contains(json!({
836 "name": expect::string().not_empty(),
837 })),));
838
839 let output = expect_json_eq(&left, &right);
840 assert!(output.is_ok(), "assertion error: {output:#?}");
841 }
842}
843
844#[cfg(test)]
845mod test_unique {
846 use crate::expect;
847 use crate::expect_json_eq;
848 use pretty_assertions::assert_eq;
849 use serde_json::json;
850
851 #[test]
852 fn it_should_pass_when_array_is_empty() {
853 let left = json!([]);
854 let right = json!(expect::array().unique());
855
856 let output = expect_json_eq(&left, &right);
857 assert!(output.is_ok(), "assertion error: {output:#?}");
858 }
859
860 #[test]
861 fn it_should_fail_when_array_is_not_unique() {
862 let left = json!([1, 1, 2]);
863 let right = json!(expect::array().unique());
864
865 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
866 assert_eq!(
867 output,
868 r#"Json expect::array() error at root[1],
869 expected array to contain all unique values.
870 found duplicate 1
871 received full array [1, 1, 2]"#
872 );
873 }
874}