use super::*;
use crate::core::config::e2e::{CallConfig, CallOverride};
use crate::core::ir::{FieldDef, TypeDef};
fn docs_fixture(assertions: serde_json::Value) -> Fixture {
serde_json::from_value(serde_json::json!({
"id": "sample_fixture",
"description": "Sample fixture",
"input": {"html": "<p>Hello World</p>"},
"assertions": assertions,
"docs": {"topic": "smoke", "stem": "sample_fixture"}
}))
.expect("fixture must parse")
}
fn call_config() -> E2eConfig {
E2eConfig {
call: CallConfig {
function: "convert".into(),
result_var: "result".into(),
..CallConfig::default()
},
..E2eConfig::default()
}
}
fn type_defs_declaring_error() -> Vec<TypeDef> {
vec![
TypeDef {
name: "ConversionResult".to_string(),
fields: vec![FieldDef {
name: "content".to_string(),
..FieldDef::default()
}],
..TypeDef::default()
},
TypeDef {
name: "ResponseObject".to_string(),
fields: vec![FieldDef {
name: "error".to_string(),
..FieldDef::default()
}],
..TypeDef::default()
},
]
}
#[test]
fn an_error_path_assertion_field_derives_no_accessor() {
let fixture = docs_fixture(serde_json::json!([
{"type": "error", "value": "Authentication"},
{"type": "equals", "field": "error.status_code", "value": 401}
]));
let operations = resolve(&fixture, &call_config(), "java", &type_defs_declaring_error(), &[]);
assert_eq!(
operations,
Vec::new(),
"an error fixture documents a failure mode; no backend renders a success-path accessor for it"
);
}
#[test]
fn a_field_the_availability_oracle_rejects_derives_no_accessor() {
let fixture = docs_fixture(serde_json::json!([{"type": "is_true", "field": "cost_tracked"}]));
let mut config = call_config();
config.result_fields = ["content".to_string()].into_iter().collect();
let operations = resolve(&fixture, &config, "csharp", &[], &[]);
assert_eq!(
operations,
Vec::new(),
"`cost_tracked` is not a member of the result; the assertion renderer skips it and so must the snippet"
);
}
#[test]
fn a_pseudo_field_on_a_byte_buffer_result_derives_no_accessor() {
let fixture = docs_fixture(serde_json::json!([
{"type": "not_error"},
{"type": "not_empty", "field": "audio"}
]));
let mut config = call_config();
config.call.overrides.insert(
"csharp".to_string(),
CallOverride {
result_is_bytes: true,
..CallOverride::default()
},
);
let operations = resolve(&fixture, &config, "csharp", &[], &[]);
assert_eq!(
operations,
Vec::new(),
"a `byte[]` result has no `audio` member -- the field names the buffer itself"
);
}
#[test]
fn a_pseudo_field_still_resolves_for_a_backend_whose_result_is_a_struct() {
let fixture = docs_fixture(serde_json::json!([
{"type": "not_error"},
{"type": "not_empty", "field": "audio"}
]));
let mut config = call_config();
config.call.overrides.insert(
"csharp".to_string(),
CallOverride {
result_is_bytes: true,
..CallOverride::default()
},
);
let operations = resolve(&fixture, &config, "python", &[], &[]);
assert_eq!(operations.len(), 1);
assert_eq!(operations[0].expression, "result.audio");
}
#[test]
fn a_field_that_resolves_on_the_return_type_still_derives_an_accessor() {
let fixture = docs_fixture(serde_json::json!([
{"type": "equals", "field": "content", "value": "Hello World\n"},
{"type": "not_empty", "field": "content"}
]));
let operations = resolve(&fixture, &call_config(), "python", &type_defs_declaring_error(), &[]);
assert_eq!(
operations.len(),
1,
"the duplicate `content` field must not be shown twice"
);
assert_eq!(operations[0].kind, "show");
assert_eq!(operations[0].expression, "result.content");
}
#[test]
fn a_streaming_virtual_field_derives_no_accessor() {
let fixture = docs_fixture(serde_json::json!([
{"type": "is_true", "field": "stream.has_page_event"},
{"type": "greater_than_or_equal", "field": "stream.event_count_min", "value": 1}
]));
let operations = resolve(&fixture, &call_config(), "dart", &[], &[]);
assert_eq!(
operations,
Vec::new(),
"stream-level predicates resolve against the drained chunk list, not against the result"
);
}
#[test]
fn an_assertion_grouping_prefix_derives_no_accessor() {
let fixture = docs_fixture(serde_json::json!([
{"type": "greater_than", "field": "rate_limit.min_duration_ms", "value": 100}
]));
let type_defs = vec![TypeDef {
name: "CrawlResult".to_string(),
fields: vec![
FieldDef {
name: "content".to_string(),
..FieldDef::default()
},
FieldDef {
name: "rate_limit_ms".to_string(),
..FieldDef::default()
},
],
..TypeDef::default()
}];
let operations = resolve(&fixture, &call_config(), "csharp", &type_defs, &[]);
assert_eq!(
operations,
Vec::new(),
"`rate_limit` is an assertion grouping the IR has never heard of; the IR declares only `rate_limit_ms`"
);
}
#[test]
fn a_hand_authored_shows_entry_is_never_filtered() {
let mut fixture = docs_fixture(serde_json::json!([{"type": "not_error"}]));
fixture.docs.as_mut().expect("docs").shows = vec!["cost_tracked".to_string()];
let mut config = call_config();
config.result_fields = ["content".to_string()].into_iter().collect();
let operations = resolve(&fixture, &config, "python", &[], &[]);
assert_eq!(operations.len(), 1);
assert_eq!(operations[0].expression, "result.cost_tracked");
}