use super::accessors::materialise_vec_temporaries;
use crate::e2e::field_access::{FieldResolver, SwiftFirstClassMap};
use crate::e2e::fixture::Assertion;
use std::collections::{HashMap, HashSet};
#[test]
fn single_optional_subscript_preserves_the_question_mark() {
let (setup, rewritten, is_map_subscript) =
materialise_vec_temporaries("result.items()?[0].value()", "is_true_1").unwrap();
assert_eq!(setup, vec!["let _vec_items_is_true_1_1 = result.items()".to_string()]);
assert_eq!(rewritten, "_vec_items_is_true_1_1?[0].value()");
assert!(!is_map_subscript);
}
#[test]
fn nested_chain_carries_optionality_across_a_later_plain_marker() {
let (setup, rewritten, is_map_subscript) =
materialise_vec_temporaries("result.items()?[0].nested()[1].value()", "is_true_2").unwrap();
assert_eq!(
setup,
vec![
"let _vec_items_is_true_2_1 = result.items()".to_string(),
"let _vec_nested_is_true_2_2 = _vec_items_is_true_2_1?[0].nested()".to_string(),
]
);
assert_eq!(rewritten, "_vec_nested_is_true_2_2?[1].value()");
assert!(!is_map_subscript);
}
#[test]
fn terminal_map_key_containing_parens_and_bracket_does_not_trigger_a_bogus_second_hoist() {
let (setup, rewritten, is_map_subscript) =
materialise_vec_temporaries("result.labels()[\"a()[b\"]", "equals_zz").unwrap();
assert_eq!(
setup,
vec![
"let _vec_labels_equals_zz_1 = (try? JSONSerialization.jsonObject(with: \
(result.labels().toString() ?? \"{}\").data(using: .utf8)!) as? [String: String]) ?? [:]"
.to_string(),
]
);
assert_eq!(rewritten, "_vec_labels_equals_zz_1[\"a()[b\"]");
assert!(is_map_subscript);
}
#[test]
fn key_with_an_escaped_quote_finds_the_true_closing_quote() {
let (setup, rewritten, is_map_subscript) =
materialise_vec_temporaries("result.labels()[\"a\\\"b\"]", "equals_eq").unwrap();
assert_eq!(
setup,
vec![
"let _vec_labels_equals_eq_1 = (try? JSONSerialization.jsonObject(with: \
(result.labels().toString() ?? \"{}\").data(using: .utf8)!) as? [String: String]) ?? [:]"
.to_string(),
]
);
assert_eq!(rewritten, "_vec_labels_equals_eq_1[\"a\\\"b\"]");
assert!(is_map_subscript);
}
#[test]
fn key_ending_in_a_backslash_finds_the_true_closing_quote() {
let (setup, rewritten, is_map_subscript) =
materialise_vec_temporaries("result.labels()[\"a\\\\\"]", "equals_bs").unwrap();
assert_eq!(
setup,
vec![
"let _vec_labels_equals_bs_1 = (try? JSONSerialization.jsonObject(with: \
(result.labels().toString() ?? \"{}\").data(using: .utf8)!) as? [String: String]) ?? [:]"
.to_string(),
]
);
assert_eq!(rewritten, "_vec_labels_equals_bs_1[\"a\\\\\"]");
assert!(is_map_subscript);
}
#[test]
fn mixed_map_then_optional_vec_subscript_is_refused() {
let result = materialise_vec_temporaries("result.labels()[\"key\"].items()?[0]", "not_empty_9");
assert!(result.is_none(), "got: {result:?}");
}
#[test]
fn map_key_containing_bracket_followed_by_a_real_further_subscript_is_refused_cleanly() {
let result = materialise_vec_temporaries("result.labels()[\"a()[b\"].nested()[0]", "equals_ex");
assert!(result.is_none(), "got: {result:?}");
}
#[test]
fn a_subscript_with_no_closing_bracket_refuses_instead_of_returning_a_partial_rewrite() {
let result = materialise_vec_temporaries("result.items()[0", "malformed_1");
assert!(result.is_none(), "got: {result:?}");
}
#[test]
fn mixed_optional_map_then_vec_reaches_the_registered_skip_via_render_assertion() {
let resolver = FieldResolver::new_with_swift_first_class(
&HashMap::new(),
&HashSet::from(["labels.items".to_string()]),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashMap::new(),
SwiftFirstClassMap::default(),
);
let assertion = Assertion {
assertion_type: "equals".to_string(),
field: Some("labels[key].items[0]".to_string()),
value: Some(serde_json::json!("x")),
..Default::default()
};
let mut out = String::new();
super::assertions::render_assertion(
&mut out,
&assertion,
"result",
&resolver,
false,
false,
false,
false,
&HashMap::new(),
false,
false,
);
assert!(
out.contains("mixes a JSON-bridged map subscript with a further RustVec subscript in Swift"),
"must emit the registered mixed map-then-vec skip; got:\n{out}"
);
assert!(
!out.contains("_vec_"),
"must not emit a hoisted-but-refused accessor local; got:\n{out}"
);
}