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