expect_json/expects/ops/expect_array/
expect_array.rs

1use crate::expect_op;
2use crate::ops::expect_array::ExpectArraySubOp;
3use crate::Context;
4use crate::ExpectOp;
5use crate::ExpectOpResult;
6use crate::JsonType;
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 is_empty(mut self) -> Self {
22        self.sub_ops.push(ExpectArraySubOp::IsEmpty);
23        self
24    }
25
26    pub fn min_len(mut self, min_len: usize) -> Self {
27        self.sub_ops.push(ExpectArraySubOp::MinLen(min_len));
28        self
29    }
30
31    pub fn max_len(mut self, max_len: usize) -> Self {
32        self.sub_ops.push(ExpectArraySubOp::MaxLen(max_len));
33        self
34    }
35
36    pub fn contains<I, V>(mut self, expected_values: I) -> Self
37    where
38        I: IntoIterator<Item = V>,
39        V: Into<Value>,
40    {
41        let inner_expected_values = expected_values
42            .into_iter()
43            .map(Into::into)
44            .collect::<Vec<_>>();
45        self.sub_ops
46            .push(ExpectArraySubOp::Contains(inner_expected_values));
47        self
48    }
49}
50
51impl ExpectOp for ExpectArray {
52    fn on_array(&self, context: &mut Context, received: &[Value]) -> ExpectOpResult<()> {
53        for sub_op in &self.sub_ops {
54            sub_op.on_array(self, context, received)?;
55        }
56
57        Ok(())
58    }
59
60    fn supported_types(&self) -> &'static [JsonType] {
61        &[JsonType::Array]
62    }
63}
64
65#[cfg(test)]
66mod test_contains {
67    use crate::expect;
68    use crate::expect_json_eq;
69    use pretty_assertions::assert_eq;
70    use serde_json::json;
71
72    #[test]
73    fn it_should_be_equal_for_identical_numeric_arrays() {
74        let left = json!([1, 2, 3]);
75        let right = json!(expect::array().contains([1, 2, 3]));
76
77        let output = expect_json_eq(&left, &right);
78        assert!(output.is_ok());
79    }
80
81    #[test]
82    fn it_should_be_equal_for_reversed_identical_numeric_arrays() {
83        let left = json!([1, 2, 3]);
84        let right = json!(expect::array().contains([3, 2, 1]));
85
86        let output = expect_json_eq(&left, &right);
87        assert!(output.is_ok());
88    }
89
90    #[test]
91    fn it_should_be_equal_for_partial_contains() {
92        let left = json!([0, 1, 2, 3, 4, 5]);
93        let right = json!(expect::array().contains([1, 2, 3]));
94
95        let output = expect_json_eq(&left, &right);
96        assert!(output.is_ok());
97    }
98
99    #[test]
100    fn it_should_error_for_totall_different_values() {
101        let left = json!([0, 1, 2, 3]);
102        let right = json!(expect::array().contains([4, 5, 6]));
103
104        let output = expect_json_eq(&left, &right).unwrap_err().to_string();
105        assert_eq!(
106            output,
107            r#"Json array at root does not contain expected value:
108    expected array to contain 4, but it was not found.
109    received [0, 1, 2, 3]"#
110        );
111    }
112
113    #[test]
114    fn it_should_be_ok_for_empty_contains() {
115        let left = json!([0, 1, 2, 3]);
116        let right = json!(expect::array().contains([] as [u32; 0]));
117
118        let output = expect_json_eq(&left, &right);
119        assert!(output.is_ok());
120    }
121
122    #[test]
123    fn it_should_error_if_used_against_the_wrong_type() {
124        let left = json!("🦊");
125        let right = json!(expect::array().contains([4, 5, 6]));
126
127        let output = expect_json_eq(&left, &right).unwrap_err().to_string();
128        assert_eq!(
129            output,
130            r#"Json expect::array() at root, received wrong type:
131    expected array
132    received string "🦊""#
133        );
134    }
135
136    #[test]
137    fn it_should_handle_nested_contains() {
138        let left = json!([
139            {
140                "text": "Hello",
141                "author": "Jane Candle"
142            },
143            {
144                "text": "Goodbye",
145                "author": "John Lighthouse"
146            }
147        ]);
148
149        let right = json!(expect::array().contains([json!({
150            "text": "Hello",
151            "author": expect::string().contains("Jane"),
152        }),]));
153
154        let output = expect_json_eq(&left, &right);
155        assert!(output.is_ok(), "{}", output.unwrap_err().to_string());
156    }
157}
158
159#[cfg(test)]
160mod test_is_empty {
161    use crate::expect;
162    use crate::expect_json_eq;
163    use pretty_assertions::assert_eq;
164    use serde_json::json;
165
166    #[test]
167    fn it_should_pass_when_array_is_empty() {
168        let left = json!([]);
169        let right = json!(expect::array().is_empty());
170
171        let output = expect_json_eq(&left, &right);
172        assert!(output.is_ok(), "assertion error: {output:#?}");
173    }
174
175    #[test]
176    fn it_should_fail_when_array_is_not_empty() {
177        let left = json!([1, 2, 3]);
178        let right = json!(expect::array().is_empty());
179
180        let output = expect_json_eq(&left, &right).unwrap_err().to_string();
181        assert_eq!(
182            output,
183            format!(
184                r#"Json expect::array() error at root:
185    expected empty array
186    received [1, 2, 3]"#
187            )
188        );
189    }
190}
191
192#[cfg(test)]
193mod test_min_len {
194    use crate::expect;
195    use crate::expect_json_eq;
196    use pretty_assertions::assert_eq;
197    use serde_json::json;
198
199    #[test]
200    fn it_should_pass_when_array_has_exactly_enough_elements() {
201        let left = json!([1, 2, 3]);
202        let right = json!(expect::array().min_len(3));
203
204        let output = expect_json_eq(&left, &right);
205        assert!(output.is_ok(), "assertion error: {output:#?}");
206    }
207
208    #[test]
209    fn it_should_pass_when_array_has_more_than_enough_elements() {
210        let left = json!([1, 2, 3, 4, 5]);
211        let right = json!(expect::array().min_len(3));
212
213        let output = expect_json_eq(&left, &right);
214        assert!(output.is_ok(), "assertion error: {output:#?}");
215    }
216
217    #[test]
218    fn it_should_fail_when_array_has_too_few_elements() {
219        let left = json!([1, 2, 3]);
220        let right = json!(expect::array().min_len(4));
221
222        let output = expect_json_eq(&left, &right).unwrap_err().to_string();
223        assert_eq!(
224            output,
225            format!(
226                r#"Json expect::array() error at root:
227    expected array to have at least 4 elements, but it has 3,
228    received [1, 2, 3]"#
229            )
230        );
231    }
232}
233
234#[cfg(test)]
235mod test_max_len {
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_pass_when_array_has_exactly_enough_elements() {
243        let left = json!([1, 2, 3]);
244        let right = json!(expect::array().max_len(3));
245
246        let output = expect_json_eq(&left, &right);
247        assert!(output.is_ok(), "assertion error: {output:#?}");
248    }
249
250    #[test]
251    fn it_should_pass_when_array_has_less_than_enough_elements() {
252        let left = json!([1, 2]);
253        let right = json!(expect::array().max_len(6));
254
255        let output = expect_json_eq(&left, &right);
256        assert!(output.is_ok(), "assertion error: {output:#?}");
257    }
258
259    #[test]
260    fn it_should_fail_when_array_has_too_few_elements() {
261        let left = json!([1, 2, 3, 4]);
262        let right = json!(expect::array().max_len(3));
263
264        let output = expect_json_eq(&left, &right).unwrap_err().to_string();
265        assert_eq!(
266            output,
267            format!(
268                r#"Json expect::array() error at root:
269    expected array to have at most 3 elements, but it has 4,
270    received [1, 2, 3, 4]"#
271            )
272        );
273    }
274}