#![cfg(all(feature = "desktop", not(alloc_frugal)))]
use rust_widgets::core::Rect;
use rust_widgets::widget::capability::WidgetFactory;
#[test]
fn every_registered_name_resolves_to_a_capability_in_both_directions() {
let factory = WidgetFactory::new_with_defaults();
let mut unconstructible: Vec<&str> = Vec::new();
let mut unresolvable: Vec<(&str, &str)> = Vec::new();
let mut kind_disagreement: Vec<(&str, &str, String)> = Vec::new();
for capability in factory.capabilities() {
let canonical = capability.canonical_name;
let declared_kind = format!("{:?}", capability.kind);
let names = core::iter::once(canonical).chain(capability.aliases.iter().copied());
for name in names {
let Some(widget) = factory.create(name, Rect::new(0, 0, 64, 48), "") else {
unconstructible.push(name);
continue;
};
let reported_kind = format!("{:?}", widget.kind());
let resolved = factory.capability_for_kind_instance(widget.as_ref());
let Some(resolved) = resolved else {
unresolvable.push((name, canonical));
continue;
};
let Some(by_name) = factory.capability(name) else {
unconstructible.push(name);
continue;
};
if format!("{:?}", by_name.kind) != declared_kind
|| format!("{:?}", resolved.kind) != declared_kind
|| reported_kind != declared_kind
{
kind_disagreement.push((
name,
canonical,
format!(
"widget.kind={reported_kind} by_name={:?} resolved={:?}",
by_name.kind, resolved.kind
),
));
}
}
}
assert!(
unconstructible.is_empty(),
"these registered names cannot be constructed, so the alias addresses nothing: \
{unconstructible:?}"
);
assert!(
unresolvable.is_empty(),
"these registered names construct a control the capability layer cannot address, so \
its own properties report UnknownWidget (name, canonical): {unresolvable:?}"
);
assert!(
kind_disagreement.is_empty(),
"a name's creation path, its mounted control and its property path disagree about the \
kind, so the declarative layer, the CSS selector and the accessibility role answer \
differently for one control (name, canonical, all three answers): {kind_disagreement:?}"
);
}
#[test]
fn every_resolved_capability_matches_the_contract_the_control_publishes() {
let factory = WidgetFactory::new_with_defaults();
let mut missing: Vec<(&str, &str)> = Vec::new();
let mut undeclared: Vec<(&str, &str)> = Vec::new();
for capability in factory.capabilities() {
let Some(widget) = factory.create(capability.canonical_name, Rect::new(0, 0, 64, 48), "")
else {
continue;
};
let Some(resolved) = factory.capability_for_kind_instance(widget.as_ref()) else {
continue;
};
let Some(published) = widget.properties_dyn().map(|props| props.property_names()) else {
continue;
};
for &name in published {
let declared = resolved.properties.iter().any(|schema| schema.name == name);
let is_base = matches!(name, "enabled" | "visible" | "tooltip" | "geometry");
if !declared && !is_base {
missing.push((resolved.canonical_name, name));
}
}
for schema in resolved.properties.iter() {
if !schema.readable && !schema.writable {
continue;
}
if !published.contains(&schema.name) {
undeclared.push((resolved.canonical_name, schema.name));
}
}
}
assert!(
missing.is_empty(),
"the resolved capability does not declare properties the control publishes, so the \
registry would reject a name the control answers (control, property): {missing:?}"
);
assert!(
undeclared.is_empty(),
"the resolved capability declares properties the control does not answer, so the \
registry advertises names that resolve to UnknownProperty (control, property): \
{undeclared:?}"
);
}