use super::*;
#[cfg(test)]
mod wildcard_tests {
use super::{field_to_dart_accessor, render_assertion_dart};
use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;
use std::collections::{HashMap, HashSet};
fn array_resolver(field: &str) -> FieldResolver {
let names: HashSet<String> = [field.to_string()].into_iter().collect();
FieldResolver::new(&HashMap::new(), &HashSet::new(), &names, &names, &HashSet::new())
}
fn render_contains(resolver: &FieldResolver, field: &str, value: &str) -> String {
let assertion = Assertion {
assertion_type: "contains".to_string(),
field: Some(field.to_string()),
value: Some(serde_json::Value::String(value.to_string())),
..Assertion::default()
};
let mut out = String::new();
render_assertion_dart(&mut out, &assertion, "result", false, resolver);
out
}
#[test]
fn single_wildcard_still_quantifies_over_every_element() {
let out = render_contains(&array_resolver("links"), "links[].url", "example.test");
assert!(out.contains("result.links.any((e) => e.url"), "got: {out}");
}
fn array_resolver_with_enum_field(field: &str) -> FieldResolver {
array_resolver(field.split("[].").next().unwrap_or(field)).with_enum_fields([field.to_string()].into())
}
#[test]
fn contains_on_an_enum_typed_array_element_field_compares_the_runtime_type_name() {
let out = render_contains(
&array_resolver_with_enum_field("structure[].kind"),
"structure[].kind",
"Function",
);
assert!(
out.contains("e.kind.runtimeType.toString().contains"),
"an enum-typed element field must compare against the runtime type name, not \
toString(), got:\n{out}"
);
assert!(!out.contains("e.kind.toString().contains"), "got: {out}");
}
#[test]
fn contains_on_a_non_enum_array_element_field_still_compares_the_stringified_value() {
let out = render_contains(&array_resolver("imports"), "imports[].source", "example.test");
assert!(
out.contains("e.source.toString().contains"),
"a non-enum element field must keep comparing its stringified content, got:\n{out}"
);
assert!(!out.contains("runtimeType"), "got: {out}");
}
#[test]
fn the_element_accessor_renders_a_surviving_wildcard_as_invalid_dart() {
assert_eq!(field_to_dart_accessor("links[].url"), "links![].url");
}
#[test]
fn nested_wildcard_should_emit_a_visible_skip_rather_than_an_index_zero_check() {
let out = render_contains(&array_resolver("pages"), "pages[].links[].url", "example.test");
assert_eq!(
out, " // skipped: nested array-wildcard field 'pages[].links[].url' not supported\n",
"got: {out}"
);
}
fn resolver_with_alias(alias_from: &str, alias_to: &str, result_field: &str) -> FieldResolver {
let aliases: HashMap<String, String> = [(alias_from.to_string(), alias_to.to_string())].into_iter().collect();
let result_fields: HashSet<String> = [result_field.to_string()].into_iter().collect();
FieldResolver::new(
&aliases,
&HashSet::new(),
&result_fields,
&HashSet::new(),
&HashSet::new(),
)
}
#[test]
fn alias_renaming_the_array_head_segment_still_resolves() {
let out = render_contains(
&resolver_with_alias("hreflang[].lang", "metadata.hreflangs[].lang", "metadata"),
"hreflang[].lang",
"en",
);
assert!(!out.contains("skipped"), "got: {out}");
assert!(
out.contains("result.metadata.hreflangs.any((e) => e.lang"),
"got: {out}"
);
}
#[test]
fn alias_renaming_only_the_sub_field_still_resolves() {
let out = render_contains(
&resolver_with_alias("assets[].category", "assets[].asset_category", "assets"),
"assets[].category",
"books",
);
assert!(!out.contains("skipped"), "got: {out}");
assert!(out.contains("result.assets.any((e) => e.assetCategory"), "got: {out}");
}
}
#[cfg(test)]
mod is_true_optional_field_tests {
use super::render_assertion_dart;
use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;
use std::collections::{HashMap, HashSet};
fn optional_resolver(field: &str) -> FieldResolver {
let optional: HashSet<String> = [field.to_string()].into_iter().collect();
FieldResolver::new(
&HashMap::new(),
&optional,
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
)
}
fn render(resolver: &FieldResolver, assertion: &Assertion) -> String {
let mut out = String::new();
render_assertion_dart(&mut out, assertion, "result", false, resolver);
out
}
fn is_true_assertion(field: &str) -> Assertion {
Assertion {
assertion_type: "is_true".to_string(),
field: Some(field.to_string()),
..Assertion::default()
}
}
#[test]
fn is_true_on_optional_struct_field_checks_presence() {
let out = render(&optional_resolver("data"), &is_true_assertion("data"));
assert_eq!(out, " expect(result.data, isNotNull);\n");
}
#[test]
fn is_false_on_optional_struct_field_checks_absence() {
let out = render(
&optional_resolver("data"),
&Assertion {
assertion_type: "is_false".to_string(),
field: Some("data".to_string()),
..Assertion::default()
},
);
assert_eq!(out, " expect(result.data, isNull);\n");
}
#[test]
fn is_true_on_non_optional_field_is_unchanged() {
let resolver = FieldResolver::new(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
);
let out = render(&resolver, &is_true_assertion("active"));
assert_eq!(out, " expect(result.active, isTrue);\n");
}
}
#[cfg(test)]
mod is_empty_branch_tests {
use super::render_assertion_dart;
use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;
use std::collections::{HashMap, HashSet};
fn render(resolver: &FieldResolver, field: &str) -> String {
let assertion = Assertion {
assertion_type: "is_empty".to_string(),
field: Some(field.to_string()),
..Assertion::default()
};
let mut out = String::new();
render_assertion_dart(&mut out, &assertion, "result", false, resolver);
out
}
fn no_arrays_resolver() -> FieldResolver {
FieldResolver::new(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
)
}
#[test]
fn is_empty_on_struct_field_does_not_call_isempty_directly() {
let out = render(&no_arrays_resolver(), "document");
assert_eq!(out, " expect((result.document?.toString() ?? ''), isEmpty);\n");
}
#[test]
fn is_empty_on_array_field_keeps_anyof_isnull_isempty() {
let array_fields: HashSet<String> = ["items".to_string()].into_iter().collect();
let resolver = FieldResolver::new(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&array_fields,
&HashSet::new(),
);
let out = render(&resolver, "items");
assert_eq!(out, " expect(result.items, anyOf(isNull, isEmpty));\n");
}
}
#[cfg(test)]
mod enum_wire_value_assertion_tests {
use super::render_assertion_dart;
use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;
use std::collections::{HashMap, HashSet};
fn enum_resolver(field: &str) -> FieldResolver {
let names: HashSet<String> = [field.to_string()].into_iter().collect();
FieldResolver::new(
&HashMap::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
)
.with_enum_fields(names)
}
fn optional_enum_resolver(field: &str) -> FieldResolver {
let names: HashSet<String> = [field.to_string()].into_iter().collect();
FieldResolver::new(
&HashMap::new(),
&names,
&HashSet::new(),
&HashSet::new(),
&HashSet::new(),
)
.with_enum_fields(names)
}
fn render(resolver: &FieldResolver, assertion: &Assertion) -> String {
let mut out = String::new();
render_assertion_dart(&mut out, assertion, "result", false, resolver);
out
}
fn equals_assertion(field: &str, value: &str) -> Assertion {
Assertion {
assertion_type: "equals".to_string(),
field: Some(field.to_string()),
value: Some(serde_json::Value::String(value.to_string())),
..Assertion::default()
}
}
#[test]
fn equals_on_enum_field_asserts_wire_value_verbatim() {
let out = render(&enum_resolver("kind"), &equals_assertion("kind", "KeyValue"));
assert_eq!(out, " expect(result.kind.wireValue, equals('KeyValue'));\n");
}
#[test]
fn equals_on_optional_enum_field_uses_safe_navigation() {
let out = render(&optional_enum_resolver("kind"), &equals_assertion("kind", "KeyValue"));
assert_eq!(out, " expect(result.kind?.wireValue, equals('KeyValue'));\n");
}
#[test]
fn not_equals_on_enum_field_asserts_wire_value_verbatim() {
let assertion = Assertion {
assertion_type: "not_equals".to_string(),
field: Some("kind".to_string()),
value: Some(serde_json::Value::String("Sequence".to_string())),
..Assertion::default()
};
let out = render(&enum_resolver("kind"), &assertion);
assert_eq!(out, " expect(result.kind.wireValue, isNot(equals('Sequence')));\n");
}
}