Compare commits

...

3 commits

Author SHA1 Message Date
8d1e26c305
refactor: Improve form finder tests with rstest
All checks were successful
Rust CI / Rust CI (push) Successful in 2m8s
Signed-off-by: Awiteb <a@4rs.nl>
2024-08-11 09:29:15 +00:00
d4c3558b97
fix: Return None if the key not found and not Some(None)
Signed-off-by: Awiteb <a@4rs.nl>
2024-08-11 09:26:47 +00:00
d39f1e941a
refactor: Improve header finder tests with rstest
Signed-off-by: Awiteb <a@4rs.nl>
2024-08-11 11:50:15 +03:00
2 changed files with 147 additions and 150 deletions

View file

@ -62,112 +62,123 @@ impl CaptchaFinder for CaptchaFormFinder {
async fn find_token(&self, req: &mut Request) -> Option<Option<String>> {
req.form_data()
.await
.map(|form| form.fields.get(&self.token_name).cloned())
.ok()
.and_then(|form| form.fields.get(&self.token_name).cloned().map(Some))
}
async fn find_answer(&self, req: &mut Request) -> Option<Option<String>> {
req.form_data()
.await
.map(|form| form.fields.get(&self.answer_name).cloned())
.ok()
.and_then(|form| form.fields.get(&self.answer_name).cloned().map(Some))
}
}
#[cfg(test)]
mod tests {
use salvo_core::http::{header, headers::ContentType, HeaderValue, ReqBody};
use salvo_core::http::{header, HeaderValue, ReqBody};
use super::*;
#[tokio::test]
async fn test_captcha_form_finder() {
let finder = CaptchaFormFinder::new();
#[rstest::rstest]
#[case::not_found(
None,
None,
None,
None,
"application/x-www-form-urlencoded",
None,
None
)]
#[case::not_found(None, None, None, None, "text/plain", None, None)]
#[case::normal(
None,
None,
Some(("captcha_token", "token")),
Some(("captcha_answer", "answer")),
"application/x-www-form-urlencoded",
Some(Some("token")),
Some(Some("answer"))
)]
#[case::custom_keys(
Some("custom_token"),
Some("custom_answer"),
Some(("custom_token", "token")),
Some(("custom_answer", "answer")),
"application/x-www-form-urlencoded",
Some(Some("token")),
Some(Some("answer"))
)]
#[case::custom_not_found(
Some("custom_token"),
Some("custom_answer"),
None,
None,
"application/x-www-form-urlencoded",
None,
None
)]
#[case::custom_not_found_with_body(
Some("custom_token"),
Some("custom_answer"),
Some(("captcha_token", "token")),
Some(("captcha_answer", "answer")),
"application/x-www-form-urlencoded",
None,
None
)]
#[case::invalid_type(
None,
None,
Some(("captcha_token", "token")),
Some(("captcha_answer", "answer")),
"application/json",
None,
None
)]
async fn test_form_finder(
#[case] custom_token_key: Option<&'static str>,
#[case] custom_answer_key: Option<&'static str>,
#[case] token_key_val: Option<(&'static str, &'static str)>,
#[case] answer_key_val: Option<(&'static str, &'static str)>,
#[case] content_type: &'static str,
#[case] excepted_token: Option<Option<&'static str>>,
#[case] excepted_answer: Option<Option<&'static str>>,
) {
let mut req = Request::default();
*req.body_mut() = ReqBody::Once("captcha_token=token&captcha_answer=answer".into());
let mut finder = CaptchaFormFinder::new();
if let Some(token_key) = custom_token_key {
finder = finder.token_name(token_key.to_string())
}
if let Some(answer_key) = custom_answer_key {
finder = finder.answer_name(answer_key.to_string())
}
let body = token_key_val
.zip(answer_key_val)
.map(|((t_k, t_v), (a_k, a_v))| format!("{t_k}={t_v}&{a_k}={a_v}"))
.unwrap_or_else(|| {
token_key_val
.or(answer_key_val)
.map(|(k, v)| format!("{k}={v}"))
.unwrap_or_default()
});
*req.body_mut() = ReqBody::Once(body.into());
let headers = req.headers_mut();
headers.insert(
header::CONTENT_TYPE,
HeaderValue::from_str(&ContentType::form_url_encoded().to_string()).unwrap(),
HeaderValue::from_str(content_type).unwrap(),
);
assert_eq!(
finder.find_token(&mut req).await,
Some(Some("token".to_owned()))
excepted_token.map(|o| o.map(ToOwned::to_owned))
);
assert_eq!(
finder.find_answer(&mut req).await,
Some(Some("answer".to_owned()))
excepted_answer.map(|o| o.map(ToOwned::to_owned))
);
}
#[tokio::test]
async fn test_captcha_form_finder_customized() {
let finder = CaptchaFormFinder::new()
.token_name("token".to_string())
.answer_name("answer".to_string());
let mut req = Request::default();
*req.body_mut() = ReqBody::Once("token=token&answer=answer".into());
let headers = req.headers_mut();
headers.insert(
header::CONTENT_TYPE,
HeaderValue::from_str(&ContentType::form_url_encoded().to_string()).unwrap(),
);
assert_eq!(
finder.find_token(&mut req).await,
Some(Some("token".to_owned()))
);
assert_eq!(
finder.find_answer(&mut req).await,
Some(Some("answer".to_owned()))
);
}
#[tokio::test]
async fn test_captcha_form_finder_none() {
let finder = CaptchaFormFinder::new();
let mut req = Request::default();
*req.body_mut() = ReqBody::Once("".into());
let headers = req.headers_mut();
headers.insert(
header::CONTENT_TYPE,
HeaderValue::from_str(&ContentType::form_url_encoded().to_string()).unwrap(),
);
assert_eq!(finder.find_token(&mut req).await, Some(None));
assert_eq!(finder.find_answer(&mut req).await, Some(None));
}
#[tokio::test]
async fn test_captcha_form_finder_customized_none() {
let finder = CaptchaFormFinder::new()
.token_name("token".to_string())
.answer_name("answer".to_string());
let mut req = Request::default();
*req.body_mut() = ReqBody::Once("".into());
let headers = req.headers_mut();
headers.insert(
header::CONTENT_TYPE,
HeaderValue::from_str(&ContentType::form_url_encoded().to_string()).unwrap(),
);
assert_eq!(finder.find_token(&mut req).await, Some(None));
assert_eq!(finder.find_answer(&mut req).await, Some(None));
}
#[tokio::test]
async fn test_captcha_form_finder_invalid() {
let finder = CaptchaFormFinder::new();
let mut req = Request::default();
*req.body_mut() = ReqBody::Once("captcha_token=token&captcha_answer=answer".into());
let headers = req.headers_mut();
headers.insert(
header::CONTENT_TYPE,
HeaderValue::from_str(&ContentType::json().to_string()).unwrap(),
);
assert_eq!(finder.find_token(&mut req).await, None);
assert_eq!(finder.find_answer(&mut req).await, None);
}
}

View file

@ -78,85 +78,71 @@ mod tests {
use salvo_core::http::HeaderValue;
#[tokio::test]
async fn test_captcha_header_finder() {
let finder = CaptchaHeaderFinder::new();
#[rstest::rstest]
#[case::not_found(None, None, None, None, None, None)]
#[case::normal(
None,
None,
Some(("x-captcha-token", "token")),
Some(("x-captcha-answer", "answer")),
Some(Some("token")),
Some(Some("answer"))
)]
#[case::custom_headers(
Some("custom-token"),
Some("custom-answer"),
Some(("custom-token", "token")),
Some(("custom-answer", "answer")),
Some(Some("token")),
Some(Some("answer"))
)]
#[case::custom_not_found(Some("custom-token"), Some("custom-answer"), None, None, None, None)]
#[case::custom_not_found_with_headers(
Some("custom-token"),
Some("custom-answer"),
Some(("x-captcha-token", "token")),
Some(("x-captcha-answer", "answer")),
None,
None
)]
async fn test_header_finder(
#[case] custom_token_header: Option<&'static str>,
#[case] custom_answer_header: Option<&'static str>,
#[case] token_header_name_value: Option<(&'static str, &'static str)>,
#[case] answer_header_name_value: Option<(&'static str, &'static str)>,
#[case] excepted_token: Option<Option<&'static str>>,
#[case] excepted_answer: Option<Option<&'static str>>,
) {
let mut finder = CaptchaHeaderFinder::new();
if let Some(custom_token) = custom_token_header {
finder = finder.token_header(HeaderName::from_static(custom_token));
}
if let Some(custom_answer) = custom_answer_header {
finder = finder.answer_header(HeaderName::from_static(custom_answer));
}
let mut req = Request::default();
let headers = req.headers_mut();
headers.insert(
HeaderName::from_static("x-captcha-token"),
HeaderValue::from_str("token").unwrap(),
);
headers.insert(
HeaderName::from_static("x-captcha-answer"),
HeaderValue::from_static("answer"),
);
if let Some((token_header_name, token_header_value)) = token_header_name_value {
headers.insert(
HeaderName::from_static(token_header_name),
HeaderValue::from_static(token_header_value),
);
}
if let Some((answer_header_name, answer_header_value)) = answer_header_name_value {
headers.insert(
HeaderName::from_static(answer_header_name),
HeaderValue::from_static(answer_header_value),
);
}
assert_eq!(
finder.find_token(&mut req).await,
Some(Some("token".to_owned()))
excepted_token.map(|o| o.map(ToOwned::to_owned))
);
assert_eq!(
finder.find_answer(&mut req).await,
Some(Some("answer".to_owned()))
excepted_answer.map(|o| o.map(ToOwned::to_owned))
);
}
#[tokio::test]
async fn test_captcha_header_finder_customized() {
let finder = CaptchaHeaderFinder::new()
.token_header(HeaderName::from_static("token"))
.answer_header(HeaderName::from_static("answer"));
let mut req = Request::default();
let headers = req.headers_mut();
headers.insert(
HeaderName::from_static("token"),
HeaderValue::from_str("token").unwrap(),
);
headers.insert(
HeaderName::from_static("answer"),
HeaderValue::from_static("answer"),
);
assert_eq!(
finder.find_token(&mut req).await,
Some(Some("token".to_owned()))
);
assert_eq!(
finder.find_answer(&mut req).await,
Some(Some("answer".to_owned()))
);
}
#[tokio::test]
async fn test_captcha_header_finder_none() {
let finder = CaptchaHeaderFinder::new();
let mut req = Request::default();
assert_eq!(finder.find_token(&mut req).await, None);
assert_eq!(finder.find_answer(&mut req).await, None);
}
#[tokio::test]
async fn test_captcha_header_finder_customized_none() {
let finder = CaptchaHeaderFinder::new()
.token_header(HeaderName::from_static("token"))
.answer_header(HeaderName::from_static("answer"));
let mut req = Request::default();
let headers = req.headers_mut();
headers.insert(
HeaderName::from_static("x-captcha-token"),
HeaderValue::from_str("token").unwrap(),
);
headers.insert(
HeaderName::from_static("x-captcha-answer"),
HeaderValue::from_static("answer"),
);
assert_eq!(finder.find_token(&mut req).await, None);
assert_eq!(finder.find_answer(&mut req).await, None);
}
}