74 lines
2.6 KiB
Rust
74 lines
2.6 KiB
Rust
//! Every widget the registry knows must be listed in the node catalog.
|
|
//!
|
|
//! The editor's palette is built from `init_node_types()`. A widget that exists in
|
|
//! `WidgetRegistry` but has no catalog entry is real, executes, generates code — and
|
|
//! cannot be found by a person using the tool. It is the same gap that had the instrument
|
|
//! catalogue, the forge, energy metering and dialect import reachable by an agent and by
|
|
//! nobody else, one level further in.
|
|
use flowrs_core::graph::nodes::init_node_types;
|
|
use flowrs_core::graph::widget::WidgetRegistry;
|
|
use std::collections::HashSet;
|
|
|
|
#[test]
|
|
fn every_registry_widget_is_in_the_palette() {
|
|
let catalog: HashSet<String> = init_node_types().iter().map(|n| n.name.clone()).collect();
|
|
let reg = WidgetRegistry::with_builtins();
|
|
|
|
// A comparison between two empty sets passes and proves nothing; several guards in
|
|
// this repo have done exactly that. Pin that both sides are populated.
|
|
assert!(
|
|
catalog.len() > 200,
|
|
"catalog looks empty: {}",
|
|
catalog.len()
|
|
);
|
|
assert!(
|
|
reg.all().len() > 100,
|
|
"registry looks empty: {}",
|
|
reg.all().len()
|
|
);
|
|
|
|
let missing: Vec<String> = reg
|
|
.all()
|
|
.iter()
|
|
.map(|w| w.id())
|
|
.filter(|id| !catalog.contains(id))
|
|
.collect();
|
|
|
|
assert!(
|
|
missing.is_empty(),
|
|
"{} widget(s) exist and cannot be found in the palette:\n {}",
|
|
missing.len(),
|
|
missing.join("\n ")
|
|
);
|
|
}
|
|
|
|
/// And the other direction: a catalog entry with no widget and no primitive behind it
|
|
/// would be a palette tile that produces a node nothing can run or emit.
|
|
#[test]
|
|
fn every_palette_entry_has_something_behind_it() {
|
|
let reg = WidgetRegistry::with_builtins();
|
|
let orphans: Vec<String> = init_node_types()
|
|
.iter()
|
|
.filter(|n| reg.get(&n.name).is_none())
|
|
// Primitives are implemented in codegen rather than the registry; `node_coverage`
|
|
// is what proves those emit, so an entry is only an orphan if neither knows it.
|
|
.filter(|n| {
|
|
let mut g = flowrs_core::graph::Graph::new();
|
|
g.add_node(&n.name, 0.0, 0.0);
|
|
match g.to_rust() {
|
|
Ok(src) => src.contains(&format!("// TODO: unsupported node type `{}`", n.name)),
|
|
Err(e) => {
|
|
!e.contains("is not connected") && !e.contains("only valid inside a loop")
|
|
}
|
|
}
|
|
})
|
|
.map(|n| n.name.clone())
|
|
.collect();
|
|
|
|
assert!(
|
|
orphans.is_empty(),
|
|
"{} palette entries have no widget and emit nothing:\n {}",
|
|
orphans.len(),
|
|
orphans.join("\n ")
|
|
);
|
|
}
|