1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::{
accessor::StatusAccessor,
error::{AsserhttpError, AsserhttpResult},
status::infallible::AnyStatus,
};
/// For assertions on http response status returning an error instead of panicking
pub trait FallibleAsserhttpStatus<T> {
/// Expects response status to be equal
/// * `status` - expected status or asserhttp::Status or closure
///
/// # Example
/// ```no_run
/// # use ureq::OrAnyStatus;
/// use asserhttp::*;
///
/// #[tokio::main]
/// async fn main() {
/// reqwest::blocking::get("http://localhost").try_expect_status(200).unwrap();
/// reqwest::blocking::get("http://localhost").try_expect_status(Status::Ok).unwrap();
/// reqwest::blocking::get("http://localhost").try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
/// reqwest::get("http://localhost").await.try_expect_status(200).unwrap();
/// reqwest::get("http://localhost").await.try_expect_status(Status::Ok).unwrap();
/// reqwest::get("http://localhost").await.try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
///
/// isahc::get("http://localhost").try_expect_status(200).unwrap();
/// isahc::get("http://localhost").try_expect_status(Status::Ok).unwrap();
/// isahc::get("http://localhost").try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
/// isahc::get_async("http://localhost").await.try_expect_status(200).unwrap();
/// isahc::get_async("http://localhost").await.try_expect_status(Status::Ok).unwrap();
/// isahc::get_async("http://localhost").await.try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
///
/// surf::get("http://localhost").await.try_expect_status(200).unwrap();
/// surf::get("http://localhost").await.try_expect_status(Status::Ok).unwrap();
/// surf::get("http://localhost").await.try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
///
/// ureq::get("http://localhost").call().or_any_status().try_expect_status(200).unwrap();
/// ureq::get("http://localhost").call().or_any_status().try_expect_status(Status::Ok).unwrap();
/// ureq::get("http://localhost").call().or_any_status().try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
///
/// hyper::Client::new().get("http://localhost".parse().unwrap()).await.try_expect_status(200).unwrap();
/// hyper::Client::new().get("http://localhost".parse().unwrap()).await.try_expect_status(Status::Ok).unwrap();
/// hyper::Client::new().get("http://localhost".parse().unwrap()).await.try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
///
/// awc::Client::default().get("http://localhost").send().await.try_expect_status(200).unwrap();
/// awc::Client::default().get("http://localhost").send().await.try_expect_status(Status::Ok).unwrap();
/// awc::Client::default().get("http://localhost").send().await.try_expect_status(|s| { assert_eq!(s, 200); Ok(()) }).unwrap();
/// }
/// ```
///
/// # Error
/// * [AsserhttpError::StatusMismatch] when actual status is different from expected one
fn try_expect_status(&mut self, status: impl Into<FallibleAnyStatus>) -> AsserhttpResult<&mut T>;
}
impl<T> FallibleAsserhttpStatus<T> for T
where
T: StatusAccessor,
{
fn try_expect_status(&mut self, status: impl Into<FallibleAnyStatus>) -> AsserhttpResult<&mut T> {
status.into()(self.get_status())?;
Ok(self)
}
}
impl<T, E> FallibleAsserhttpStatus<T> for Result<T, E>
where
T: StatusAccessor,
E: std::fmt::Debug,
{
fn try_expect_status(&mut self, status: impl Into<FallibleAnyStatus>) -> AsserhttpResult<&mut T> {
self.as_mut()
.map_err(|e| AsserhttpError::HttpError(format!("{e:?}")))?
.try_expect_status(status)
}
}
pub struct FallibleAnyStatus(Box<dyn Fn(u16) -> AsserhttpResult<()>>);
impl From<u16> for FallibleAnyStatus {
fn from(expected: u16) -> Self {
Self(Box::new(move |actual| {
if actual != expected {
return Err(AsserhttpError::StatusMismatch { expected, actual });
}
Ok(())
}))
}
}
impl From<crate::Status> for FallibleAnyStatus {
fn from(value: crate::Status) -> Self {
value.to_string().parse::<u16>().map(Self::from).unwrap()
}
}
impl<F: 'static> From<F> for FallibleAnyStatus
where
F: Fn(u16) -> AsserhttpResult<()>,
{
fn from(fun: F) -> Self {
Self(Box::new(fun))
}
}
#[cfg(feature = "rocket")]
impl From<rocket::http::Status> for FallibleAnyStatus {
fn from(value: rocket::http::Status) -> Self {
Self::from(value.code)
}
}
impl std::ops::Deref for FallibleAnyStatus {
type Target = dyn Fn(u16) -> AsserhttpResult<()>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<AnyStatus> for FallibleAnyStatus {
fn from(asserter: AnyStatus) -> Self {
Self(Box::new(move |status| {
asserter(status);
Ok(())
}))
}
}