1use crate::__private::ExpectOpExt;
2use crate::expect_core::Context;
3use crate::expect_core::ExpectOpError;
4use crate::expect_core::ExpectOpResult;
5use crate::internals::objects::IntegerObject;
6use crate::internals::objects::NullObject;
7use crate::internals::objects::ValueObject;
8use crate::JsonType;
9use serde_json::Map;
10use serde_json::Value;
11use std::fmt::Debug;
12
13pub trait ExpectOp: ExpectOpExt + Debug + Send + 'static {
76 fn on_any(&self, context: &mut Context<'_>, received: &Value) -> ExpectOpResult<()> {
77 match received {
78 Value::Null => self.on_null(context),
79 Value::Number(received_number) => {
80 let value_num = ValueObject::from(received_number.clone());
81 match value_num {
82 ValueObject::Float(received_float) => self.on_f64(context, received_float.into()),
83 ValueObject::Integer(IntegerObject::Positive(received_integer)) => self.on_u64(context, received_integer),
84 ValueObject::Integer(IntegerObject::Negative(received_integer)) => self.on_i64(context, received_integer),
85 _ => panic!("Unexpected non-number value, expected a float or an integer, found {value_num:?}. (This is a bug, please report at: https://github.com/JosephLenton/expect-json/issues)"),
86 }
87 }
88 Value::String(received_string) => self.on_string(context, received_string),
89 Value::Bool(received_boolean) => self.on_boolean(context, *received_boolean),
90 Value::Array(received_array) => self.on_array(context, received_array),
91 Value::Object(received_object) => self.on_object(context, received_object),
92 }
93 }
94
95 #[allow(unused_variables)]
96 fn on_null(&self, context: &mut Context<'_>) -> ExpectOpResult<()> {
97 Err(ExpectOpError::unsupported_operation_type(
98 context, self, NullObject,
99 ))
100 }
101
102 #[allow(unused_variables)]
103 fn on_f64(&self, context: &mut Context<'_>, received: f64) -> ExpectOpResult<()> {
104 Err(ExpectOpError::unsupported_operation_type(
105 context, self, received,
106 ))
107 }
108
109 #[allow(unused_variables)]
110 fn on_u64(&self, context: &mut Context<'_>, received: u64) -> ExpectOpResult<()> {
111 Err(ExpectOpError::unsupported_operation_type(
112 context, self, received,
113 ))
114 }
115
116 #[allow(unused_variables)]
117 fn on_i64(&self, context: &mut Context<'_>, received: i64) -> ExpectOpResult<()> {
118 Err(ExpectOpError::unsupported_operation_type(
119 context, self, received,
120 ))
121 }
122
123 #[allow(unused_variables)]
124 fn on_boolean(&self, context: &mut Context<'_>, received: bool) -> ExpectOpResult<()> {
125 Err(ExpectOpError::unsupported_operation_type(
126 context, self, received,
127 ))
128 }
129
130 #[allow(unused_variables)]
131 fn on_string(&self, context: &mut Context<'_>, received: &str) -> ExpectOpResult<()> {
132 Err(ExpectOpError::unsupported_operation_type(
133 context,
134 self,
135 received.to_owned(),
136 ))
137 }
138
139 #[allow(unused_variables)]
140 fn on_array(&self, context: &mut Context<'_>, received: &[Value]) -> ExpectOpResult<()> {
141 Err(ExpectOpError::unsupported_operation_type(
142 context,
143 self,
144 received.to_owned(),
145 ))
146 }
147
148 #[allow(unused_variables)]
149 fn on_object(
150 &self,
151 context: &mut Context<'_>,
152 received: &Map<String, Value>,
153 ) -> ExpectOpResult<()> {
154 Err(ExpectOpError::unsupported_operation_type(
155 context,
156 self,
157 received.to_owned(),
158 ))
159 }
160
161 fn debug_supported_types(&self) -> &'static [JsonType] {
165 &[]
166 }
167}
168
169#[cfg(test)]
170mod test_on_any {
171 use super::*;
172 use crate::internals::objects::ArrayObject;
173 use crate::internals::objects::BooleanObject;
174 use crate::internals::objects::FloatObject;
175 use crate::internals::objects::ObjectObject;
176 use crate::internals::objects::StringObject;
177 use crate::internals::objects::ValueTypeObject;
178 use crate::internals::ExpectOpMeta;
179 use serde_json::json;
180
181 #[crate::expect_core::expect_op(internal)]
183 #[derive(Debug, Clone)]
184 struct TestJsonExpectOp;
185
186 impl ExpectOp for TestJsonExpectOp {}
187
188 #[test]
189 fn it_should_error_by_default_against_json_null() {
190 let mut outer_context = Context::new();
191 let received = json!(null);
192 let output = TestJsonExpectOp
193 .on_any(&mut outer_context, &received)
194 .unwrap_err();
195 assert!(matches!(
196 output,
197 ExpectOpError::UnsupportedOperation {
198 context,
199 received: ValueTypeObject(ValueObject::Null(NullObject)),
200 expected_operation: ExpectOpMeta {
201 name: "TestJsonExpectOp",
202 types: &[],
203 },
204 } if context == outer_context.to_static()
205 ));
206 }
207
208 #[test]
209 fn it_should_error_by_default_against_json_boolean() {
210 let mut outer_context = Context::new();
211 let received = json!(true);
212 let output = TestJsonExpectOp
213 .on_any(&mut outer_context, &received)
214 .unwrap_err();
215 assert!(matches!(
216 output,
217 ExpectOpError::UnsupportedOperation {
218 context,
219 received: ValueTypeObject(ValueObject::Boolean(BooleanObject(true))),
220 expected_operation: ExpectOpMeta {
221 name: "TestJsonExpectOp",
222 types: &[],
223 },
224 } if context == outer_context.to_static()
225 ));
226 }
227
228 #[test]
229 fn it_should_error_by_default_against_json_positive_integer() {
230 let mut outer_context = Context::new();
231 let received = json!(123);
232 let output = TestJsonExpectOp
233 .on_any(&mut outer_context, &received)
234 .unwrap_err();
235 assert!(matches!(
236 output,
237 ExpectOpError::UnsupportedOperation {
238 context,
239 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Positive(123))),
240 expected_operation: ExpectOpMeta {
241 name: "TestJsonExpectOp",
242 types: &[],
243 },
244 } if context == outer_context.to_static()
245 ));
246 }
247
248 #[test]
249 fn it_should_error_by_default_against_json_negative_integer() {
250 let mut outer_context = Context::new();
251 let received = json!(-123);
252 let output = TestJsonExpectOp
253 .on_any(&mut outer_context, &received)
254 .unwrap_err();
255 assert!(matches!(
256 output,
257 ExpectOpError::UnsupportedOperation {
258 context,
259 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Negative(-123))),
260 expected_operation: ExpectOpMeta {
261 name: "TestJsonExpectOp",
262 types: &[],
263 },
264 } if context == outer_context.to_static()
265 ));
266 }
267
268 #[test]
269 fn it_should_error_by_default_against_json_float() {
270 let mut outer_context = Context::new();
271 let received = json!(123.456);
272 let output = TestJsonExpectOp
273 .on_any(&mut outer_context, &received)
274 .unwrap_err();
275 assert!(matches!(
276 output,
277 ExpectOpError::UnsupportedOperation {
278 context,
279 received: ValueTypeObject(ValueObject::Float(FloatObject(123.456))),
280 expected_operation: ExpectOpMeta {
281 name: "TestJsonExpectOp",
282 types: &[],
283 },
284 } if context == outer_context.to_static()
285 ));
286 }
287
288 #[test]
289 fn it_should_error_by_default_against_json_string() {
290 let mut outer_context = Context::new();
291 let received = json!("🦊");
292 let output = TestJsonExpectOp
293 .on_any(&mut outer_context, &received)
294 .unwrap_err();
295 assert!(matches!(
296 output,
297 ExpectOpError::UnsupportedOperation {
298 context,
299 received,
300 expected_operation: ExpectOpMeta {
301 name: "TestJsonExpectOp",
302 types: &[],
303 },
304 } if context == outer_context.to_static()
305 && received == ValueTypeObject(ValueObject::String(StringObject("🦊".to_string())))
306 ));
307 }
308
309 #[test]
310 fn it_should_error_by_default_against_json_array() {
311 let mut outer_context = Context::new();
312 let received = json!([]);
313 let output = TestJsonExpectOp
314 .on_any(&mut outer_context, &received)
315 .unwrap_err();
316 assert!(matches!(
317 output,
318 ExpectOpError::UnsupportedOperation {
319 context,
320 received,
321 expected_operation: ExpectOpMeta {
322 name: "TestJsonExpectOp",
323 types: &[],
324 },
325 } if context == outer_context.to_static()
326 && received == ValueTypeObject(ValueObject::Array(ArrayObject(vec![])))
327 ));
328 }
329
330 #[test]
331 fn it_should_error_by_default_against_json_object() {
332 let mut outer_context = Context::new();
333 let received = json!({});
334 let output = TestJsonExpectOp
335 .on_any(&mut outer_context, &received)
336 .unwrap_err();
337 assert!(matches!(
338 output,
339 ExpectOpError::UnsupportedOperation {
340 context,
341 received,
342 expected_operation: ExpectOpMeta {
343 name: "TestJsonExpectOp",
344 types: &[],
345 },
346 } if context == outer_context.to_static()
347 && received == ValueTypeObject(ValueObject::Object(ObjectObject(Map::new())))
348 ));
349 }
350}