use std::collections::HashMap;
use serde::Deserialize;
use super::impl_condition_deserialize;
#[derive(Debug, Clone)]
pub enum ResponseCondition {
When(ResponseConditionMatch),
Unless(ResponseConditionMatch),
}
impl_condition_deserialize!(ResponseCondition, ResponseConditionMatch, "response condition");
#[derive(Debug, Clone, Deserialize)]
pub struct ResponseConditionMatch {
#[serde(default)]
pub status: Option<Vec<u16>>,
#[serde(default)]
pub headers: Option<HashMap<String, String>>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_response_condition_when_status() {
let yaml = r#"
- when:
status: [200, 201]
"#;
let conds: Vec<ResponseCondition> = serde_yaml::from_str(yaml).unwrap();
assert_eq!(conds.len(), 1, "should parse 1 condition");
assert!(
matches!(
&conds[0],
ResponseCondition::When(m) if m.status.as_ref().unwrap() == &[200, 201]
),
"should be When condition with status [200, 201]"
);
}
#[test]
fn parse_response_condition_unless_headers() {
let yaml = r#"
- unless:
headers:
x-skip: "true"
"#;
let conds: Vec<ResponseCondition> = serde_yaml::from_str(yaml).unwrap();
assert_eq!(conds.len(), 1, "should parse 1 condition");
assert!(
matches!(&conds[0], ResponseCondition::Unless(m) if m.headers.is_some()),
"should be Unless condition with headers"
);
}
#[test]
fn parse_response_condition_all_fields() {
let yaml = r#"
status: [500, 502, 503]
headers:
content-type: "text/html"
"#;
let m: ResponseConditionMatch = serde_yaml::from_str(yaml).unwrap();
assert_eq!(m.status.as_ref().unwrap(), &[500, 502, 503], "status codes mismatch");
assert_eq!(
m.headers.as_ref().unwrap().get("content-type").unwrap(),
"text/html",
"content-type header mismatch"
);
}
#[test]
fn parse_empty_response_conditions() {
let conds: Vec<ResponseCondition> = serde_yaml::from_str("[]").unwrap();
assert!(conds.is_empty(), "empty array should parse to empty vec");
}
#[test]
fn reject_response_condition_neither() {
let yaml = "- {}";
let err = serde_yaml::from_str::<Vec<ResponseCondition>>(yaml).unwrap_err();
assert!(err.to_string().contains("either"));
}
#[test]
fn reject_response_condition_both() {
let yaml = r#"
- when:
status: [200]
unless:
status: [500]
"#;
let err = serde_yaml::from_str::<Vec<ResponseCondition>>(yaml).unwrap_err();
assert!(err.to_string().contains("exactly one"));
}
}