facett-ops/tests/pages_from_the_row.rs
//! `cargo ops demo-wasm` / `deploy-pages` build the `facett-demo-wasm` ROW in the pinned image
//! and publish the as-built dist, through edda's `nornir_pages::demo_wasm` — the container
//! road since 2026-09-30 (it was host cargo + host wasm-bindgen). These hold the half
//! that needs no engine.
use std::path::PathBuf;
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).parent().unwrap().to_path_buf()
}
fn code(f: &str) -> String {
std::fs::read_to_string(root().join("facett-ops/src").join(f))
.unwrap()
.lines()
.filter(|l| !l.trim_start().starts_with("//"))
.collect::<Vec<_>>()
.join("\n")
}
/// The page imports exactly what the row's cell produces, into the cell's out dir.
#[test]
fn the_page_imports_what_the_row_produces() {
let set = facett_build_thing::declared();
let (row, dist) = facett_ops::pages::demo_row(&set, &root()).expect("the demo row serves the page");
assert_eq!(row.name, facett_build_thing::DEMO_WASM_VARIANT);
let cell = set.wasm(&row.name).unwrap();
assert_eq!(dist, root().join(&cell.out_dir));
let b = cell.bindgen.as_ref().expect("the demo cell declares bindgen");
assert_eq!(b.target.as_str(), "web", "the loader is a plain <script type=module>");
assert!(!b.typescript);
let cfg = facett_ops::pages::pages_cfg(&root());
for f in nornir_pages::bundle_files(&cfg) {
assert!(cell.outputs(row).iter().any(|o| o.ends_with(&f)), "cell does not produce {f}");
}
}
/// RED-when-broken: a recipe whose demo row loses its cell is refused BY NAME.
#[test]
fn a_demo_row_without_its_cell_is_refused() {
let mut set = facett_build_thing::declared();
set.wasms.retain(|c| c.name != facett_build_thing::DEMO_WASM_VARIANT);
let e = facett_ops::pages::demo_row(&set, &root()).expect_err("refused");
assert!(e.contains("facett-demo-wasm") && e.contains("[[build.wasm]]"), "{e}");
}
/// No host road: the verbs hand the recipe and the row to edda's
/// `nornir_pages::demo_wasm`/`deploy_pages`, which since 2026-09-30 ARE the container
/// road (`nornir_build_thing::container_road`: the row's argv in the pinned image,
/// then its bindgen stage in the same image). Nothing here spells a build.
#[test]
fn demo_wasm_and_deploy_pages_have_no_host_build() {
let pages = code("pages.rs");
assert!(
pages.contains("nornir_pages::demo_wasm(&pages_cfg(root), &set, facett_build_thing::DEMO_WASM_VARIANT)"),
"pages.rs does not build the recipe's demo row through edda's container road"
);
assert!(pages.contains("nornir_pages::deploy_pages(&pages_cfg(root), &set, facett_build_thing::DEMO_WASM_VARIANT)"));
for banned in ["Command::new", "std::process", "\"wasm32", "\"--features", "wasm-bindgen\""] {
assert!(!pages.contains(banned), "pages.rs spells `{banned}`");
}
let main = code("main.rs");
assert!(main.contains("\"demo-wasm\" => demo_wasm()") && main.contains("\"deploy-pages\" => deploy_pages()"));
// And edda's side: the host `cargo build` + host wasm-bindgen are gone from the
// flow facett calls (read off the sibling checkout this workspace builds against).
let edda = std::fs::read_to_string(root().join("../edda/crates/nornir-pages/src/lib.rs"))
.expect("edda is a sibling of this checkout");
let edda = edda.split("#[cfg(test)]").next().unwrap();
assert!(edda.contains("container_road::build_row("), "nornir_pages::demo_wasm does not build in the container");
for banned in ["Command::new(\"cargo\")", "ensure_wasm_bindgen", "\"wasm-opt\""] {
assert!(!edda.contains(banned), "nornir-pages spells `{banned}` — the host road is back");
}
}
/// NO GPU IS SAID PLAINLY on the pages demo (owner, 2026-10-01: "loading, then black";
/// the console said only "No available adapters."). `wasm_start` asks
/// `navigator.gpu` / `isSecureContext` / `requestAdapter()` through facett-core's
/// shared `adapter_retry` BEFORE eframe starts, and every refusal reaches the page via
/// `show_no_gpu` — the same words a facet-wrapped mount uses.
#[test]
fn the_pages_demo_says_no_gpu_on_the_page_before_eframe_starts() {
let src = std::fs::read_to_string(root().join("facett-demo/src/main.rs")).unwrap();
let start = src.find("pub fn wasm_start(").expect("wasm_start exists");
let body = &src[start..];
let runner = body.find("eframe::WebRunner::new()").expect("wasm_start starts eframe");
for (step, needle) in [
("navigator.gpu + isSecureContext", "browser_preflight()"),
("requestAdapter()", "request_adapter().await"),
("the bounded retry", "adapter_retry::after_failure("),
] {
let at = body.find(needle).unwrap_or_else(|| panic!("wasm_start never checks {step} (`{needle}`)"));
assert!(at < runner, "{step} is checked AFTER eframe starts — the black canvas comes first");
}
assert!(body.contains("show_no_gpu(adapter_retry::preflight_message(p))"), "preflight refusal is not shown");
assert!(body.contains("Next::Fail(msg) => {\n show_no_gpu(&msg);"), "null adapter is not shown");
assert!(src.contains("div.set_text_content(Some(msg))"), "show_no_gpu writes nothing into the page");
assert!(!src.contains("mod adapter_retry"), "a second copy of the policy");
// The wording is facett-core's; facet-wrapped re-exports the same module.
use facet_wrapped::adapter_retry::{preflight_message, Preflight};
assert!(preflight_message(Preflight::NoWebGpu).contains("chrome://flags/#enable-unsafe-webgpu and #enable-vulkan"));
assert!(src.contains("facett::core::adapter_retry"), "the demo does not use the shared policy");
}