use crate::core::config::e2e::CallConfig;
use crate::e2e::fixture::Fixture;
const DEFAULT_DOCS_MOCK_URL: &str = "https://example.com";
pub(super) fn with_default_mock_url_literals(mut fixture: Fixture, call: &CallConfig) -> Fixture {
let candidates: Vec<(String, bool)> = fixture
.resolved_args(call)
.iter()
.filter_map(|arg| match arg.arg_type.as_str() {
"mock_url" => Some((arg.field.clone(), false)),
"mock_url_list" => Some((arg.field.clone(), true)),
_ => None,
})
.collect();
let mut injected_any = false;
for (field, is_list) in candidates {
let already_declared = if is_list {
crate::e2e::codegen::resolve_urls_field(&fixture.input, &field)
.as_array()
.is_some()
} else {
crate::e2e::codegen::resolve_field(&fixture.input, &field)
.as_str()
.is_some()
};
if already_declared {
continue;
}
let default = if is_list {
serde_json::json!([DEFAULT_DOCS_MOCK_URL])
} else {
serde_json::Value::String(DEFAULT_DOCS_MOCK_URL.to_string())
};
if set_input_field(&mut fixture.input, &field, default) {
injected_any = true;
}
}
if injected_any {
fixture.preserve_input_urls = true;
}
fixture
}
fn set_input_field(input: &mut serde_json::Value, field_path: &str, value: serde_json::Value) -> bool {
let path = field_path.strip_prefix("input.").unwrap_or(field_path);
if path.is_empty() || path == "input" {
return false;
}
let mut segments = path.split('.').peekable();
let mut current = input;
while let Some(segment) = segments.next() {
if !current.is_object() {
*current = serde_json::Value::Object(serde_json::Map::new());
}
let Some(map) = current.as_object_mut() else {
return false;
};
if segments.peek().is_none() {
map.insert(segment.to_string(), value);
return true;
}
current = map
.entry(segment.to_string())
.or_insert_with(|| serde_json::Value::Object(serde_json::Map::new()));
}
false
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::config::e2e::ArgMapping;
fn mock_url_arg(field: &str) -> ArgMapping {
ArgMapping {
name: "url".into(),
field: field.into(),
arg_type: "mock_url".into(),
optional: false,
owned: false,
element_type: None,
go_type: None,
vec_inner_is_ref: false,
trait_name: None,
}
}
fn mock_url_list_arg(field: &str) -> ArgMapping {
ArgMapping {
arg_type: "mock_url_list".into(),
..mock_url_arg(field)
}
}
fn call_with_args(args: Vec<ArgMapping>) -> CallConfig {
CallConfig {
args,
..CallConfig::default()
}
}
#[test]
fn injects_the_default_url_when_the_fixture_declares_none() {
let fixture = Fixture {
input: serde_json::json!({}),
..Fixture::default()
};
let call = call_with_args(vec![mock_url_arg("url")]);
let result = with_default_mock_url_literals(fixture, &call);
assert_eq!(
result.input.get("url").and_then(|v| v.as_str()),
Some(DEFAULT_DOCS_MOCK_URL)
);
assert!(
result.preserve_input_urls,
"injecting a literal must opt the fixture in"
);
}
#[test]
fn leaves_an_already_declared_url_untouched() {
let fixture = Fixture {
input: serde_json::json!({"url": "http://127.0.0.1:9/"}),
..Fixture::default()
};
let call = call_with_args(vec![mock_url_arg("url")]);
let result = with_default_mock_url_literals(fixture, &call);
assert_eq!(
result.input.get("url").and_then(|v| v.as_str()),
Some("http://127.0.0.1:9/")
);
}
#[test]
fn injects_a_single_element_default_list_for_mock_url_list() {
let fixture = Fixture {
input: serde_json::json!({}),
..Fixture::default()
};
let call = call_with_args(vec![mock_url_list_arg("urls")]);
let result = with_default_mock_url_literals(fixture, &call);
assert_eq!(
result.input.get("urls").and_then(|v| v.as_array()),
Some(&vec![serde_json::Value::String(DEFAULT_DOCS_MOCK_URL.to_string())])
);
assert!(result.preserve_input_urls);
}
#[test]
fn a_fixture_with_no_mock_url_arg_is_left_unmarked() {
let fixture = Fixture {
input: serde_json::json!({"text": "sample"}),
..Fixture::default()
};
let call = call_with_args(vec![ArgMapping {
name: "text".into(),
field: "text".into(),
arg_type: "string".into(),
optional: false,
owned: false,
element_type: None,
go_type: None,
vec_inner_is_ref: false,
trait_name: None,
}]);
let result = with_default_mock_url_literals(fixture, &call);
assert!(!result.preserve_input_urls);
assert!(result.input.get("url").is_none());
}
}