expect_json/expect_core/
expect_op_error.rs

1use crate::expect_core::Context;
2use crate::expect_core::ExpectOp;
3use crate::internals::objects::ArrayObject;
4use crate::internals::objects::FloatObject;
5use crate::internals::objects::IntegerObject;
6use crate::internals::objects::ValueObject;
7use crate::internals::objects::ValueTypeObject;
8use crate::internals::ExpectOpMeta;
9use crate::ExpectJsonError;
10use crate::JsonType;
11use std::error::Error as StdError;
12use thiserror::Error;
13
14pub type ExpectOpResult<V> = Result<V, ExpectOpError>;
15
16#[derive(Debug, Error)]
17pub enum ExpectOpError {
18    // TODO, this error message should include which operations it _can_ be performed on.
19    // The underlying problem might be the server returned different data to what we expected.
20    #[error(
21        "Json expect::{}() at {context}, received wrong type:
22    expected {}
23    received {received}",
24        expected_operation.name,
25        format_expected_operation_types(expected_operation),
26    )]
27    UnsupportedOperation {
28        context: Context<'static>,
29        received: ValueTypeObject,
30        expected_operation: ExpectOpMeta,
31    },
32
33    #[error(
34        "Json object at {context} is missing key for {}:
35    expected field '{expected_key}',
36    but it was not found",
37        expected_operation.name
38    )]
39    ObjectKeyMissingForExpectOp {
40        context: Context<'static>,
41        expected_key: String,
42        expected_operation: ExpectOpMeta,
43    },
44
45    #[error(
46        "Json at {context} has key with value, expecting either key not present or different value.
47    received {received}"
48    )]
49    ObjectKeyValueIsEqual {
50        context: Context<'static>,
51        received: ValueObject,
52        expected_operation: ExpectOpMeta,
53    },
54
55    #[error(
56        "Json {json_type} at {context} contains value was expecting to not be there:
57    expected {json_type} to not contain {expected}, but it was found.
58    received {received}"
59    )]
60    ContainsFound {
61        context: Context<'static>,
62        json_type: JsonType,
63        expected: ValueObject,
64        received: ValueObject,
65    },
66
67    #[error(
68        "Json {json_type} at {context} does not contain expected value:
69    expected {json_type} to contain {expected}, but it was not found.
70    received {received}"
71    )]
72    ContainsNotFound {
73        context: Context<'static>,
74        json_type: JsonType,
75        expected: ValueObject,
76        received: ValueObject,
77    },
78
79    #[error(
80        "Json expect::array() error at {context},
81    expected array to contain all unique values.
82    found duplicate {duplicate}
83    received full array {received_array}"
84    )]
85    ArrayContainsDuplicate {
86        context: Context<'static>,
87        duplicate: ValueObject,
88        received_array: ArrayObject,
89    },
90
91    #[error(
92        "{error}
93    received full array {received_full_array}"
94    )]
95    ArrayAllEqual {
96        #[source]
97        error: Box<ExpectJsonError>,
98        received_full_array: ArrayObject,
99    },
100
101    #[error(
102        "Json expect::integer() error at {context}, is zero:
103    expected non-zero integer
104    received {received}"
105    )]
106    IntegerIsZero {
107        context: Context<'static>,
108        received: IntegerObject,
109    },
110
111    #[error(
112        "Json expect::integer() error at {context}, is not zero:
113    expected 0
114    received {received}"
115    )]
116    IntegerIsNotZero {
117        context: Context<'static>,
118        received: IntegerObject,
119    },
120
121    #[error(
122        "Json expect::float() error at {context}, is zero:
123    expected non-zero float
124    received {received}"
125    )]
126    FloatIsZero {
127        context: Context<'static>,
128        received: FloatObject,
129    },
130
131    #[error(
132        "Json expect::float() error at {context}, is not zero:
133    expected 0.0
134    received {received}"
135    )]
136    FloatIsNotZero {
137        context: Context<'static>,
138        received: FloatObject,
139    },
140
141    #[error(
142        "Json expect::{}() error at {context}:
143    {message},
144    {error}",
145    expected_operation.name,
146    )]
147    UnknownError {
148        #[source]
149        error: Box<dyn StdError>,
150        context: Context<'static>,
151        message: String,
152        expected_operation: ExpectOpMeta,
153    },
154
155    #[error(
156        "Json expect::{}() error at {context}:
157    {message}",
158    expected_operation.name,
159    )]
160    UnknownErrorMessage {
161        context: Context<'static>,
162        message: String,
163        expected_operation: ExpectOpMeta,
164    },
165
166    #[error("{error}")]
167    ExpectJsonError {
168        #[source]
169        error: Box<ExpectJsonError>,
170    },
171}
172
173impl ExpectOpError {
174    pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
175    where
176        O: ExpectOp + ?Sized,
177        S: Into<String>,
178    {
179        Self::UnknownErrorMessage {
180            context: context.to_static(),
181            message: message.into(),
182            expected_operation: ExpectOpMeta::new(expect_op),
183        }
184    }
185
186    pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
187    where
188        O: ExpectOp + ?Sized,
189        S: Into<String>,
190        E: StdError + 'static,
191    {
192        Self::UnknownError {
193            context: context.to_static(),
194            error: Box::new(error),
195            message: message.into(),
196            expected_operation: ExpectOpMeta::new(expect_op),
197        }
198    }
199
200    pub fn unsupported_operation_type<O, V>(
201        context: &Context<'_>,
202        expect_op: &O,
203        received: V,
204    ) -> Self
205    where
206        O: ExpectOp + ?Sized,
207        V: Into<ValueTypeObject>,
208    {
209        Self::UnsupportedOperation {
210            context: context.to_static(),
211            received: received.into(),
212            expected_operation: ExpectOpMeta::new(expect_op),
213        }
214    }
215}
216
217impl From<ExpectJsonError> for ExpectOpError {
218    fn from(error: ExpectJsonError) -> Self {
219        Self::ExpectJsonError {
220            error: Box::new(error),
221        }
222    }
223}
224
225fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
226    let types = expected_operation.types;
227    if types.is_empty() {
228        return "no supported types listed (need to implement ExpectOp::supported_types)"
229            .to_string();
230    }
231
232    types.join(", ")
233}