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 all<V>(mut self, expected: V) -> Self
92 where
93 V: Into<Value>,
94 {
95 self.sub_ops
96 .push(ExpectArraySubOp::AllEqual(expected.into()));
97 self
98 }
99
100 pub fn unique(mut self) -> Self {
129 self.sub_ops.push(ExpectArraySubOp::AllUnique);
130 self
131 }
132}
133
134impl ExpectOp for ExpectArray {
135 fn on_array(&self, context: &mut Context, received: &[Value]) -> ExpectOpResult<()> {
136 for sub_op in &self.sub_ops {
137 sub_op.on_array(self, context, received)?;
138 }
139
140 Ok(())
141 }
142
143 fn debug_supported_types(&self) -> &'static [JsonType] {
144 &[JsonType::Array]
145 }
146}
147
148#[cfg(test)]
149mod test_contains {
150 use crate::expect;
151 use crate::expect_json_eq;
152 use pretty_assertions::assert_eq;
153 use serde_json::json;
154
155 #[test]
156 fn it_should_be_equal_for_identical_numeric_arrays() {
157 let left = json!([1, 2, 3]);
158 let right = json!(expect::array().contains([1, 2, 3]));
159
160 let output = expect_json_eq(&left, &right);
161 assert!(output.is_ok());
162 }
163
164 #[test]
165 fn it_should_be_equal_for_reversed_identical_numeric_arrays() {
166 let left = json!([1, 2, 3]);
167 let right = json!(expect::array().contains([3, 2, 1]));
168
169 let output = expect_json_eq(&left, &right);
170 assert!(output.is_ok());
171 }
172
173 #[test]
174 fn it_should_be_equal_for_partial_contains() {
175 let left = json!([0, 1, 2, 3, 4, 5]);
176 let right = json!(expect::array().contains([1, 2, 3]));
177
178 let output = expect_json_eq(&left, &right);
179 assert!(output.is_ok());
180 }
181
182 #[test]
183 fn it_should_error_for_totall_different_values() {
184 let left = json!([0, 1, 2, 3]);
185 let right = json!(expect::array().contains([4, 5, 6]));
186
187 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
188 assert_eq!(
189 output,
190 r#"Json array at root does not contain expected value:
191 expected array to contain 4, but it was not found.
192 received [0, 1, 2, 3]"#
193 );
194 }
195
196 #[test]
197 fn it_should_be_ok_for_empty_contains() {
198 let left = json!([0, 1, 2, 3]);
199 let right = json!(expect::array().contains([] as [u32; 0]));
200
201 let output = expect_json_eq(&left, &right);
202 assert!(output.is_ok());
203 }
204
205 #[test]
206 fn it_should_error_if_used_against_the_wrong_type() {
207 let left = json!("🦊");
208 let right = json!(expect::array().contains([4, 5, 6]));
209
210 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
211 assert_eq!(
212 output,
213 r#"Json expect::array() at root, received wrong type:
214 expected array
215 received string "🦊""#
216 );
217 }
218
219 #[test]
220 fn it_should_handle_nested_contains() {
221 let left = json!([
222 {
223 "text": "Hello",
224 "author": "Jane Candle"
225 },
226 {
227 "text": "Goodbye",
228 "author": "John Lighthouse"
229 }
230 ]);
231
232 let right = json!(expect::array().contains([json!({
233 "text": "Hello",
234 "author": expect::string().contains("Jane"),
235 }),]));
236
237 let output = expect_json_eq(&left, &right);
238 assert!(output.is_ok(), "{}", output.unwrap_err().to_string());
239 }
240
241 #[test]
242 fn it_should_fail_nested_contains_that_do_not_match() {
243 let left = json!([
244 {
245 "text": "Hello",
246 "author": "Jane Candle"
247 },
248 {
249 "text": "Goodbye",
250 "author": "John Lighthouse"
251 }
252 ]);
253
254 let right = json!(expect::array().contains([json!({
255 "text": "Hello",
256 "author": expect::string().contains("🦊"),
257 }),]));
258
259 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
260 assert_eq!(
261 output,
262 r#"Json array at root does not contain expected value:
263 expected array to contain {
264 "author": expect::string(),
265 "text": "Hello"
266 }, but it was not found.
267 received [
268 {
269 "author": "Jane Candle",
270 "text": "Hello"
271 },
272 {
273 "author": "John Lighthouse",
274 "text": "Goodbye"
275 }
276 ]"#
277 );
278 }
279}
280
281#[cfg(test)]
282mod test_empty {
283 use crate::expect;
284 use crate::expect_json_eq;
285 use pretty_assertions::assert_eq;
286 use serde_json::json;
287
288 #[test]
289 fn it_should_pass_when_array_is_empty() {
290 let left = json!([]);
291 let right = json!(expect::array().empty());
292
293 let output = expect_json_eq(&left, &right);
294 assert!(output.is_ok(), "assertion error: {output:#?}");
295 }
296
297 #[test]
298 fn it_should_fail_when_array_is_not_empty() {
299 let left = json!([1, 2, 3]);
300 let right = json!(expect::array().empty());
301
302 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
303 assert_eq!(
304 output,
305 r#"Json expect::array() error at root:
306 expected empty array
307 received [1, 2, 3]"#
308 );
309 }
310}
311
312#[cfg(test)]
313mod test_not_empty {
314 use crate::expect;
315 use crate::expect_json_eq;
316 use pretty_assertions::assert_eq;
317 use serde_json::json;
318
319 #[test]
320 fn it_should_pass_when_array_is_not_empty() {
321 let left = json!([1]);
322 let right = json!(expect::array().not_empty());
323
324 let output = expect_json_eq(&left, &right);
325 assert!(output.is_ok(), "assertion error: {output:#?}");
326 }
327
328 #[test]
329 fn it_should_fail_when_array_is_empty() {
330 let left = json!([]);
331 let right = json!(expect::array().not_empty());
332
333 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
334 assert_eq!(
335 output,
336 r#"Json expect::array() error at root:
337 expected non-empty array
338 received []"#
339 );
340 }
341}
342
343#[cfg(test)]
344mod test_min_len {
345 use crate::expect;
346 use crate::expect_json_eq;
347 use pretty_assertions::assert_eq;
348 use serde_json::json;
349
350 #[test]
351 fn it_should_pass_when_array_has_exactly_enough_elements() {
352 let left = json!([1, 2, 3]);
353 let right = json!(expect::array().min_len(3));
354
355 let output = expect_json_eq(&left, &right);
356 assert!(output.is_ok(), "assertion error: {output:#?}");
357 }
358
359 #[test]
360 fn it_should_pass_when_array_has_more_than_enough_elements() {
361 let left = json!([1, 2, 3, 4, 5]);
362 let right = json!(expect::array().min_len(3));
363
364 let output = expect_json_eq(&left, &right);
365 assert!(output.is_ok(), "assertion error: {output:#?}");
366 }
367
368 #[test]
369 fn it_should_fail_when_array_has_too_few_elements() {
370 let left = json!([1, 2, 3]);
371 let right = json!(expect::array().min_len(4));
372
373 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
374 assert_eq!(
375 output,
376 r#"Json expect::array() error at root:
377 expected array to have at least 4 elements, but it has 3.
378 received [1, 2, 3]"#
379 );
380 }
381}
382
383#[cfg(test)]
384mod test_len {
385 use crate::expect;
386 use crate::expect_json_eq;
387 use pretty_assertions::assert_eq;
388 use serde_json::json;
389
390 #[test]
391 fn it_should_pass_when_array_has_exactly_enough_elements() {
392 let left = json!([1, 2, 3]);
393 let right = json!(expect::array().len(3));
394
395 let output = expect_json_eq(&left, &right);
396 assert!(output.is_ok(), "assertion error: {output:#?}");
397 }
398
399 #[test]
400 fn it_should_fail_when_array_has_more_than_enough_elements() {
401 let left = json!([1, 2, 3, 4, 5]);
402 let right = json!(expect::array().len(3));
403
404 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
405 assert_eq!(
406 output,
407 r#"Json expect::array() error at root:
408 expected array to have 3 elements, but it has 5.
409 received [1, 2, 3, 4, 5]"#
410 );
411 }
412
413 #[test]
414 fn it_should_fail_when_array_has_too_few_elements() {
415 let left = json!([1, 2, 3]);
416 let right = json!(expect::array().len(4));
417
418 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
419 assert_eq!(
420 output,
421 r#"Json expect::array() error at root:
422 expected array to have 4 elements, but it has 3.
423 received [1, 2, 3]"#
424 );
425 }
426}
427
428#[cfg(test)]
429mod test_max_len {
430 use crate::expect;
431 use crate::expect_json_eq;
432 use pretty_assertions::assert_eq;
433 use serde_json::json;
434
435 #[test]
436 fn it_should_pass_when_array_has_exactly_enough_elements() {
437 let left = json!([1, 2, 3]);
438 let right = json!(expect::array().max_len(3));
439
440 let output = expect_json_eq(&left, &right);
441 assert!(output.is_ok(), "assertion error: {output:#?}");
442 }
443
444 #[test]
445 fn it_should_pass_when_array_has_less_than_enough_elements() {
446 let left = json!([1, 2]);
447 let right = json!(expect::array().max_len(6));
448
449 let output = expect_json_eq(&left, &right);
450 assert!(output.is_ok(), "assertion error: {output:#?}");
451 }
452
453 #[test]
454 fn it_should_fail_when_array_has_too_few_elements() {
455 let left = json!([1, 2, 3, 4]);
456 let right = json!(expect::array().max_len(3));
457
458 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
459 assert_eq!(
460 output,
461 r#"Json expect::array() error at root:
462 expected array to have at most 3 elements, but it has 4.
463 received [1, 2, 3, 4]"#
464 );
465 }
466}
467
468#[cfg(test)]
469mod test_all {
470 use crate::expect;
471 use crate::expect_json_eq;
472 use pretty_assertions::assert_eq;
473 use serde_json::json;
474
475 #[test]
476 fn it_should_pass_when_array_is_empty() {
477 let left = json!([]);
478 let right = json!(expect::array().all(expect::string()));
479
480 let output = expect_json_eq(&left, &right);
481 assert!(output.is_ok(), "assertion error: {output:#?}");
482 }
483
484 #[test]
485 fn it_should_pass_with_mix_of_operations() {
486 let left = json!([
487 "123e4567-e89b-12d3-a456-426614174000",
488 "123e4567-e89b-12d3-a456-426614174001",
489 "123e4567-e89b-12d3-a456-426614174002",
490 ]);
491 let right = json!(expect::array().all(expect::uuid()).len(3).unique());
492
493 let output = expect_json_eq(&left, &right);
494 assert!(output.is_ok(), "assertion error: {output:#?}");
495 }
496
497 #[test]
498 fn it_should_fail_with_mix_of_operations() {
499 let left = json!([
500 "123e4567-e89b-12d3-a456-426614174000",
501 "123e4567-e89b-12d3-a456-426614174001",
502 "123e4567-e89b-12d3-a456-426614174002",
503 "123e4567-e89b-12d3-a456-426614174003",
504 ]);
505 let right = json!(expect::array().all(expect::uuid()).len(3).unique());
506
507 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
508 assert_eq!(
509 output,
510 r#"Json expect::array() error at root:
511 expected array to have 3 elements, but it has 4.
512 received ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001", "123e4567-e89b-12d3-a456-426614174002", "123e4567-e89b-12d3-a456-426614174003"]"#
513 );
514 }
515
516 #[test]
517 fn it_should_fail_when_array_values_do_not_match_expect_op() {
518 let left = json!([1, 2, 3]);
519 let right = json!(expect::array().all(expect::string()));
520
521 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
522 assert_eq!(
523 output,
524 r#"Json expect::string() at root[0], received wrong type:
525 expected string
526 received integer 1
527 received full array [1, 2, 3]"#
528 );
529 }
530
531 #[test]
532 fn it_should_fail_when_array_values_do_not_match_values() {
533 let left = json!([1, 2, 3]);
534 let right = json!(expect::array().all("🦊"));
535
536 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
537 assert_eq!(
538 output,
539 r#"Json values at root[0] are different types:
540 expected string "🦊"
541 received integer 1
542 received full array [1, 2, 3]"#
543 );
544 }
545
546 #[test]
547 fn it_should_pass_when_array_values_do_match_expect_op() {
548 let left = json!(["alice@example.com", "bob@example.com"]);
549 let right = json!(expect::array().all(expect::email()));
550
551 let output = expect_json_eq(&left, &right);
552 assert!(output.is_ok(), "assertion error: {output:#?}");
553 }
554
555 #[test]
556 fn it_should_pass_when_array_values_do_match_values() {
557 let left = json!([1, 1, 1]);
558 let right = json!(expect::array().all(1));
559
560 let output = expect_json_eq(&left, &right);
561 assert!(output.is_ok(), "assertion error: {output:#?}");
562 }
563
564 #[test]
565 fn it_should_pass_when_array_values_do_match_complex_objects() {
566 let left = json!([
567 {
568 "name": "Alice Candles",
569 "email": "alice@example.com"
570 },
571 {
572 "name": "Bob Kettles",
573 "email": "bob@example.com"
574 },
575 ]);
576
577 let right = json!(expect::array().all(json!({
578 "name": expect::string().not_empty(),
579 "email": expect::email(),
580 })));
581
582 let output = expect_json_eq(&left, &right);
583 assert!(output.is_ok(), "assertion error: {output:#?}");
584 }
585
586 #[test]
587 fn it_should_not_pass_when_array_values_do_not_match_complex_objects() {
588 let left = json!([
589 {
590 "name": "Alice Candles",
591 "email": "alice@example.com"
592 },
593 {
594 "name": "",
595 "email": "bob@example.com"
596 },
597 ]);
598
599 let right = json!(expect::array().all(json!({
600 "name": expect::string().not_empty(),
601 "email": expect::email(),
602 })));
603
604 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
605 assert_eq!(
606 output,
607 r#"Json expect::string() error at root[1].name:
608 expected non-empty string
609 received ""
610 received full array [
611 {
612 "email": "alice@example.com",
613 "name": "Alice Candles"
614 },
615 {
616 "email": "bob@example.com",
617 "name": ""
618 }
619 ]"#
620 );
621 }
622}
623
624#[cfg(test)]
625mod test_unique {
626 use crate::expect;
627 use crate::expect_json_eq;
628 use pretty_assertions::assert_eq;
629 use serde_json::json;
630
631 #[test]
632 fn it_should_pass_when_array_is_empty() {
633 let left = json!([]);
634 let right = json!(expect::array().unique());
635
636 let output = expect_json_eq(&left, &right);
637 assert!(output.is_ok(), "assertion error: {output:#?}");
638 }
639
640 #[test]
641 fn it_should_fail_when_array_is_not_unique() {
642 let left = json!([1, 1, 2]);
643 let right = json!(expect::array().unique());
644
645 let output = expect_json_eq(&left, &right).unwrap_err().to_string();
646 assert_eq!(
647 output,
648 r#"Json expect::array() error at root[1],
649 expected array to contain all unique values.
650 found duplicate 1
651 received full array [1, 1, 2]"#
652 );
653 }
654}