use crate::e2e::codegen::field_skip::nested_wildcard_skip_line;
use crate::e2e::escape::escape_java;
use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;
fn wildcard_lambda_param(assertion: &Assertion) -> String {
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
assertion.assertion_type.hash(&mut hasher);
assertion.field.hash(&mut hasher);
assertion
.value
.as_ref()
.map(std::string::ToString::to_string)
.unwrap_or_default()
.hash(&mut hasher);
format!("e{:x}", hasher.finish() & 0xffff_ffff)
}
pub(super) fn render_wildcard_assertion(
out: &mut String,
assertion: &Assertion,
result_var: &str,
field_resolver: &FieldResolver,
field: &str,
array_part: &str,
elem_part: &str,
) {
if let Some(line) = nested_wildcard_skip_line(" ", "//", field, elem_part) {
out.push_str(&line);
out.push('\n');
return;
}
let array_accessor = if array_part.is_empty() {
result_var.to_string()
} else {
let accessor = field_resolver.accessor(array_part, "java", result_var);
if field_resolver.is_optional(field_resolver.resolve(array_part)) {
format!("java.util.Optional.ofNullable({accessor}).orElse(java.util.List.of())")
} else {
accessor
}
};
let param = wildcard_lambda_param(assertion);
let elem_accessor = field_resolver.accessor(elem_part, "java", ¶m);
let any_match = |value: &serde_json::Value| -> Option<(String, String)> {
let serde_json::Value::String(s) = value else {
return None;
};
let escaped = escape_java(s);
Some((
format!(
"{array_accessor}.stream().anyMatch({param} -> String.valueOf({elem_accessor}).contains(\"{escaped}\"))"
),
escaped,
))
};
match assertion.assertion_type.as_str() {
"contains" | "not_contains" if assertion.value.is_some() => {
let value = assertion.value.as_ref().expect("guarded by the match arm");
let Some((expr, escaped)) = any_match(value) else {
out.push_str(&format!(
" // skipped: non-string value for '{field}' traversal assertion\n"
));
return;
};
if assertion.assertion_type == "contains" {
out.push_str(&format!(
" assertTrue({expr}, \"expected some element of '{field}' to contain: {escaped}\");\n"
));
} else {
out.push_str(&format!(
" assertFalse({expr}, \"expected no element of '{field}' to contain: {escaped}\");\n"
));
}
}
"contains" | "contains_all" | "not_contains" => {
let Some(values) = &assertion.values else {
out.push_str(&format!(
" // skipped: '{field}' traversal assertion has no values\n"
));
return;
};
let negated = assertion.assertion_type == "not_contains";
for value in values {
let Some((expr, escaped)) = any_match(value) else {
continue;
};
if negated {
out.push_str(&format!(
" assertFalse({expr}, \"expected no element of '{field}' to contain: {escaped}\");\n"
));
} else {
out.push_str(&format!(
" assertTrue({expr}, \"expected some element of '{field}' to contain: {escaped}\");\n"
));
}
}
}
"not_empty" => {
out.push_str(&format!(
" assertTrue({array_accessor}.stream().anyMatch({param} -> \
!String.valueOf({elem_accessor}).isEmpty()), \"expected some element of '{field}' to be \
non-empty\");\n"
));
}
other => {
out.push_str(&format!(
" // skipped: unsupported traversal assertion '{other}' on '{field}'\n"
));
}
}
}