joule-ui-catalogue now holds the node form both ways: the reading of a node and the catalogue writer. joule-ui-a2ui keeps its names on that reading, so wai-app depends on the neutral crate and neither format's name is left under wai/, in a manifest or a lock file. A test holds the two lock files and the manifest to that. check_catalogue compares the document with what the registry writes, every keyword of it, and reads it as a schema: on each node it builds, the catalogue and the reading must agree. That includes a node with no props for a widget that requires some, a key folding onto a slot of an open widget, and every child a widget does not admit. Co-Authored-By: Claude Opus 5.5 <[email protected]>
71 lines
3.3 KiB
Rust
71 lines
3.3 KiB
Rust
//! The registry's two exports, committed under `widgets/`, are what the registry gives
|
|
//! today, byte for byte, and the catalogue is one the registry's ingest takes back. A
|
|
//! widget added to the registry fails here until the files are written again:
|
|
//!
|
|
//! WAI_APP_BLESS=1 cargo test --test exports the_committed_files
|
|
|
|
use joule_ui_core::{PropSchema, PropType, WidgetSchema};
|
|
use joule_ui_lang::Library;
|
|
use std::path::PathBuf;
|
|
use wai_app::registry::{self, ROOT};
|
|
|
|
fn dir() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("widgets")
|
|
}
|
|
|
|
fn committed(name: &str) -> Vec<u8> {
|
|
std::fs::read(dir().join(name)).unwrap_or_else(|e| panic!("{name}: {e} (write it with WAI_APP_BLESS=1 cargo test --test exports the_committed_files)"))
|
|
}
|
|
|
|
#[test]
|
|
fn the_committed_files_are_what_the_registry_gives() {
|
|
let bless = std::env::var_os("WAI_APP_BLESS").is_some();
|
|
for (name, bytes) in registry::exports() {
|
|
if bless {
|
|
std::fs::write(dir().join(name), &bytes).unwrap();
|
|
}
|
|
assert!(committed(name) == bytes, "{name} is not what the registry gives: write it with WAI_APP_BLESS=1 cargo test --test exports the_committed_files");
|
|
}
|
|
let mut listed: Vec<String> = std::fs::read_dir(dir()).unwrap().map(|e| e.unwrap().file_name().to_string_lossy().into_owned()).filter(|n| !n.starts_with('.')).collect();
|
|
listed.sort();
|
|
assert_eq!(listed, ["catalogue.json", "library.json"], "the directory holds the exports alone");
|
|
}
|
|
|
|
/// The drift test's own negative control: the same comparison on a registry with one
|
|
/// widget more, or one prop more, fails for both files.
|
|
#[test]
|
|
fn a_registry_changed_without_writing_the_files_again_differs_from_them() {
|
|
let added = registry::registry().with(WidgetSchema::new("Clock", "The room's clock."));
|
|
let widened = registry::registry().with(WidgetSchema::new("Chat", "The room's chat.").prop("limit", PropSchema::optional(PropType::Number)));
|
|
for r in [added, widened] {
|
|
let lib = Library::new(r, Some(ROOT.into())).unwrap();
|
|
for (name, bytes) in registry::exports_of(&lib) {
|
|
assert!(committed(name) != bytes, "{name} did not change with the registry");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_committed_catalogue_comes_back_through_the_ingest() {
|
|
let v: serde_json::Value = serde_json::from_slice(&committed("catalogue.json")).unwrap();
|
|
joule_ui_catalogue::check_catalogue(&v, ®istry::registry()).unwrap();
|
|
assert_eq!(v["$ref"], format!("#/$defs/{ROOT}"));
|
|
assert_eq!(v["$id"], registry::CATALOGUE_ID);
|
|
for n in registry::library().names() {
|
|
assert_eq!(v["$defs"][&n]["description"].as_str(), registry::registry().get(&n).map(|s| s.description.as_str()), "{n}");
|
|
}
|
|
}
|
|
|
|
/// The published files are WAI's widgets and nothing else, and the manifests that
|
|
/// build them say the same: none of them names a format.
|
|
#[test]
|
|
fn the_files_name_no_format() {
|
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
let manifests = ["Cargo.toml", "Cargo.lock", "../wai-rs/Cargo.lock"].map(|f| (f, std::fs::read(root.join(f)).unwrap()));
|
|
for (name, bytes) in registry::exports().into_iter().chain(manifests) {
|
|
let text = String::from_utf8(bytes).unwrap().to_lowercase();
|
|
for word in [concat!("a", "2ui"), concat!("open", "ui")] {
|
|
assert!(!text.contains(word), "{name} names a format");
|
|
}
|
|
}
|
|
}
|