expect_json/expect_core/
expect_op_error.rs

1use crate::ExpectJsonError;
2use crate::JsonType;
3use crate::expect_core::Context;
4use crate::expect_core::ExpectOp;
5use crate::internals::ExpectOpMeta;
6use crate::internals::objects::ArrayObject;
7use crate::internals::objects::FloatObject;
8use crate::internals::objects::IntegerObject;
9use crate::internals::objects::ValueObject;
10use crate::internals::objects::ValueTypeObject;
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 {json_type} error at {context}, regex did not match:
81    expected {json_type} to match regex pattern '{pattern}',
82    received {received}"
83    )]
84    RegexNoMatch {
85        context: Context<'static>,
86        json_type: JsonType,
87        pattern: String,
88        received: ValueObject,
89    },
90
91    #[error(
92        "Json expect::array() error at {context},
93    expected array to contain all unique values.
94    found duplicate {duplicate}
95    received full array {received_array}"
96    )]
97    ArrayContainsDuplicate {
98        context: Context<'static>,
99        duplicate: ValueObject,
100        received_array: ArrayObject,
101    },
102
103    #[error(
104        "{error}
105    received full array {received_full_array}"
106    )]
107    ArrayAllEqual {
108        #[source]
109        error: Box<ExpectJsonError>,
110        received_full_array: ArrayObject,
111    },
112
113    #[error(
114        "Json expect::integer() error at {context}, is zero:
115    expected non-zero integer
116    received {received}"
117    )]
118    IntegerIsZero {
119        context: Context<'static>,
120        received: IntegerObject,
121    },
122
123    #[error(
124        "Json expect::integer() error at {context}, is not zero:
125    expected 0
126    received {received}"
127    )]
128    IntegerIsNotZero {
129        context: Context<'static>,
130        received: IntegerObject,
131    },
132
133    #[error(
134        "Json expect::float() error at {context}, is zero:
135    expected non-zero float
136    received {received}"
137    )]
138    FloatIsZero {
139        context: Context<'static>,
140        received: FloatObject,
141    },
142
143    #[error(
144        "Json expect::float() error at {context}, is not zero:
145    expected 0.0
146    received {received}"
147    )]
148    FloatIsNotZero {
149        context: Context<'static>,
150        received: FloatObject,
151    },
152
153    #[error(
154        "Json expect::{}() error at {context}:
155    {message},
156    {error}",
157    expected_operation.name,
158    )]
159    UnknownError {
160        #[source]
161        error: Box<dyn StdError>,
162        context: Context<'static>,
163        message: String,
164        expected_operation: ExpectOpMeta,
165    },
166
167    #[error(
168        "Json expect::{}() error at {context}:
169    {message}",
170    expected_operation.name,
171    )]
172    UnknownErrorMessage {
173        context: Context<'static>,
174        message: String,
175        expected_operation: ExpectOpMeta,
176    },
177
178    #[error("{error}")]
179    ExpectJsonError {
180        #[source]
181        error: Box<ExpectJsonError>,
182    },
183}
184
185impl ExpectOpError {
186    pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
187    where
188        O: ExpectOp + ?Sized,
189        S: Into<String>,
190    {
191        Self::UnknownErrorMessage {
192            context: context.to_static(),
193            message: message.into(),
194            expected_operation: ExpectOpMeta::new(expect_op),
195        }
196    }
197
198    pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
199    where
200        O: ExpectOp + ?Sized,
201        S: Into<String>,
202        E: StdError + 'static,
203    {
204        Self::UnknownError {
205            context: context.to_static(),
206            error: Box::new(error),
207            message: message.into(),
208            expected_operation: ExpectOpMeta::new(expect_op),
209        }
210    }
211
212    pub fn unsupported_operation_type<O, V>(
213        context: &Context<'_>,
214        expect_op: &O,
215        received: V,
216    ) -> Self
217    where
218        O: ExpectOp + ?Sized,
219        V: Into<ValueTypeObject>,
220    {
221        Self::UnsupportedOperation {
222            context: context.to_static(),
223            received: received.into(),
224            expected_operation: ExpectOpMeta::new(expect_op),
225        }
226    }
227}
228
229impl From<ExpectJsonError> for ExpectOpError {
230    fn from(error: ExpectJsonError) -> Self {
231        Self::ExpectJsonError {
232            error: Box::new(error),
233        }
234    }
235}
236
237fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
238    let types = expected_operation.types;
239    if types.is_empty() {
240        return "no supported types listed (need to implement ExpectOp::supported_types)"
241            .to_string();
242    }
243
244    types.join(", ")
245}