use crate::v1_1::selector::ValueOrSelector;
use crate::validation::{Context, ValidateWithContext};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, Default)]
#[serde(rename_all = "lowercase")]
pub enum ParameterLocation {
#[default]
Path,
Query,
Querystring,
Header,
Cookie,
Channel,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)]
pub struct Parameter {
pub name: String,
#[serde(rename = "in", skip_serializing_if = "Option::is_none")]
pub in_: Option<ParameterLocation>,
pub value: ValueOrSelector,
#[serde(flatten)]
#[serde(with = "crate::common::extensions")]
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<BTreeMap<String, serde_json::Value>>,
}
impl ValidateWithContext for Parameter {
fn validate_with_context(&self, ctx: &mut Context) {
ctx.require_non_empty("name", &self.name);
ctx.in_field("value", |ctx| self.value.validate_with_context(ctx));
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::v1_1::selector::Selector;
use enumset::EnumSet;
use serde_json::json;
#[test]
fn channel_and_querystring_locations_round_trip() {
for s in ["querystring", "channel"] {
let p: Parameter =
serde_json::from_value(json!({ "name": "n", "in": s, "value": "v" })).unwrap();
assert!(p.in_.is_some());
}
}
#[test]
fn value_can_be_a_selector() {
let p: Parameter = serde_json::from_value(json!({
"name": "petId",
"value": { "context": "$response.body", "selector": "$.id", "type": "jsonpath" }
}))
.unwrap();
assert!(matches!(p.value, ValueOrSelector::Selector(_)));
let mut ctx = Context::with_path(EnumSet::empty(), "#.p");
p.validate_with_context(&mut ctx);
assert!(ctx.errors.is_empty());
}
#[test]
fn validate_rejects_empty_name_and_bad_selector() {
let p = Parameter {
name: String::new(),
value: ValueOrSelector::Selector(Selector::default()),
..Default::default()
};
let mut ctx = Context::with_path(EnumSet::empty(), "#.p");
p.validate_with_context(&mut ctx);
let msgs: Vec<_> = ctx.errors.iter().map(ToString::to_string).collect();
assert!(msgs.iter().any(|e| e == "#.p.name: must not be empty"));
assert!(
msgs.iter()
.any(|e| e == "#.p.value.context: must not be empty")
);
}
}