use crate::e2e::field_access::{FieldResolver, JsonNavStep, SwiftFirstClassMap};
use std::collections::{HashMap, HashSet};
fn resolver_with_json_bridged_field(field_name: &str) -> FieldResolver {
let swift_first_class_map = SwiftFirstClassMap {
json_bridged_field_names: HashSet::from([field_name.to_string()]),
..SwiftFirstClassMap::default()
};
FieldResolver::new_with_swift_first_class(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashMap::new(),
swift_first_class_map,
)
}
#[test]
fn indexed_element_directly_after_the_bridged_leaf_yields_one_index_step() {
let resolver = resolver_with_json_bridged_field("detected_languages");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].detected_languages[0]")
.expect("an indexed element after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].detected_languages");
assert_eq!(steps, vec![JsonNavStep::Index(0)]);
}
#[test]
fn dotted_key_after_the_bridged_leaf_yields_one_key_step() {
let resolver = resolver_with_json_bridged_field("metadata");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.output_format")
.expect("a dotted key after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(steps, vec![JsonNavStep::Key("output_format".to_string())]);
}
#[test]
fn multiple_dotted_keys_chain_into_multiple_key_steps() {
let resolver = resolver_with_json_bridged_field("metadata");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.html.title")
.expect("a multi-segment dotted path after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(
steps,
vec![
JsonNavStep::Key("format".to_string()),
JsonNavStep::Key("title".to_string()),
]
);
}
#[test]
fn a_non_variant_key_after_format_is_still_kept() {
let resolver = resolver_with_json_bridged_field("metadata");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.revision")
.expect("a dotted key after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(
steps,
vec![
JsonNavStep::Key("format".to_string()),
JsonNavStep::Key("revision".to_string()),
]
);
}
#[test]
fn excel_variant_segment_is_skipped_not_turned_into_a_key_step() {
let resolver = resolver_with_json_bridged_field("metadata");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.excel.sheet_count")
.expect("a variant-crossing dotted path after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(
steps,
vec![
JsonNavStep::Key("format".to_string()),
JsonNavStep::Key("sheet_count".to_string()),
]
);
assert!(
!steps.contains(&JsonNavStep::Key("excel".to_string())),
"must not emit a Key step for the variant name, got: {steps:?}"
);
}
#[test]
fn html_variant_segment_is_skipped_not_turned_into_a_key_step() {
let resolver = resolver_with_json_bridged_field("metadata");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.html.title")
.expect("a variant-crossing dotted path after a JSON-bridged leaf must be navigable");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(
steps,
vec![
JsonNavStep::Key("format".to_string()),
JsonNavStep::Key("title".to_string()),
]
);
assert!(
!steps.contains(&JsonNavStep::Key("html".to_string())),
"must not emit a Key step for the variant name, got: {steps:?}"
);
}
#[test]
fn index_then_keys_mixes_step_kinds_in_order() {
let resolver = resolver_with_json_bridged_field("chunks");
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].chunks[0].metadata.total_chunks")
.expect("an index followed by dotted keys must be navigable");
assert_eq!(leaf_field, "results[0].chunks");
assert_eq!(
steps,
vec![
JsonNavStep::Index(0),
JsonNavStep::Key("metadata".to_string()),
JsonNavStep::Key("total_chunks".to_string()),
]
);
}
#[test]
fn wildcard_bracket_is_not_navigable() {
let resolver = resolver_with_json_bridged_field("headings");
assert_eq!(resolver.swift_json_bridged_navigation("metadata.headings[].text"), None);
}
#[test]
fn string_key_bracket_is_not_navigable() {
let resolver = resolver_with_json_bridged_field("labels");
assert_eq!(resolver.swift_json_bridged_navigation("labels[key].items"), None);
}
#[test]
fn trailing_count_suffix_is_left_to_the_existing_count_suffix_mechanism() {
let resolver = resolver_with_json_bridged_field("og_locale_alternates");
assert_eq!(
resolver.swift_json_bridged_navigation("metadata.og_locale_alternates.length"),
None
);
}
#[test]
fn a_path_with_no_bridged_leaf_yields_no_navigation() {
let empty = HashSet::new();
let resolver = FieldResolver::new(&HashMap::new(), &empty, &empty, &empty, &empty);
assert_eq!(resolver.swift_json_bridged_navigation("results[0].mime_type"), None);
}
fn resolver_anchored_on_extraction_result(root_type: Option<&str>) -> FieldResolver {
let field_types = HashMap::from([
(
"ExtractionResult".to_string(),
HashMap::from([("results".to_string(), "ExtractedDocument".to_string())]),
),
(
"ExtractedDocument".to_string(),
HashMap::from([("metadata".to_string(), "Metadata".to_string())]),
),
(
"Metadata".to_string(),
HashMap::from([("format".to_string(), "FormatMetadata".to_string())]),
),
]);
let json_bridged_by_type = HashMap::from([
("Metadata".to_string(), HashMap::from([("format".to_string(), true)])),
(
"ExtractedDocument".to_string(),
HashMap::from([("metadata".to_string(), false)]),
),
]);
let swift_first_class_map = SwiftFirstClassMap {
field_types,
json_bridged_field_names: HashSet::from(["metadata".to_string()]),
json_bridged_by_type,
root_type: root_type.map(str::to_string),
..SwiftFirstClassMap::default()
};
FieldResolver::new_with_swift_first_class(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashMap::new(),
swift_first_class_map,
)
}
#[test]
fn should_anchor_json_bridge_on_owner_type_not_bare_field_name() {
let resolver = resolver_anchored_on_extraction_result(Some("ExtractionResult"));
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.excel.sheet_count")
.expect("format is bridged on Metadata and must be found");
assert_eq!(leaf_field, "results[0].metadata.format");
assert_eq!(steps, vec![JsonNavStep::Key("sheet_count".to_string())]);
}
#[test]
fn should_fall_back_to_the_flat_set_when_the_cursor_cannot_be_anchored() {
let resolver = resolver_anchored_on_extraction_result(None);
let (leaf_field, steps) = resolver
.swift_json_bridged_navigation("results[0].metadata.format.excel.sheet_count")
.expect("the flat set still marks metadata bridged when unanchored");
assert_eq!(leaf_field, "results[0].metadata");
assert_eq!(
steps,
vec![
JsonNavStep::Key("format".to_string()),
JsonNavStep::Key("sheet_count".to_string()),
]
);
}