Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

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");
}