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

nordisk/holger-ui

crates/holger-ui-recipe/tests/toml_parity.rs

//! **`.nornir/build-variants.toml` IS the code's emission — and this fails for
//! any reason it is not.**
//!
//! 1. the committed bytes are `emit`'s bytes (a row added to the code and not
//!    re-emitted, a hand edit, a comment typed into the output: all red);
//! 2. the emission reads back, through the ONE loader, to the declaration;
//! 3. the file is inert — an edit is visible to a reader and invisible to the code;
//! 4. the comparison can go red at all (a set differing by one field is unequal).

use holger_ui_recipe::{declared, emitted_toml, repo_root, HolgerUiBuildThing};
use nornir_build_thing::emit::first_difference;
use nornir_build_thing::plugin::{BuildThing, Role};
use nornir_build_thing::variant::{ArtifactKind, BuildVariantSet, Profile, ServiceShape};

fn committed() -> String {
    let path = BuildVariantSet::conventional_path(&repo_root());
    std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()))
}

#[test]
fn the_committed_toml_is_the_codes_emission_byte_for_byte() {
    let emitted = emitted_toml().expect("the declaration emits");
    if let Some(diff) = first_difference(&committed(), &emitted) {
        panic!(
            ".nornir/build-variants.toml is not the code's emission — the code is the source. \
             Run `cargo run -p holger-ui-build-thing -- emit` and commit the result; never edit \
             the toml by hand. {diff}"
        );
    }
    let back = BuildVariantSet::from_toml_str(&emitted).expect("the emission parses back");
    assert_eq!(back, declared());
    back.validate_all().expect("and every variant validates");
    holger_ui_recipe::require_committed_is_emitted(&repo_root())
        .expect("the door's own check agrees");
}

#[test]
fn an_edited_toml_has_zero_effect_on_what_the_code_declares() {
    let before = declared();
    let edited = emitted_toml()
        .unwrap()
        .replace("name = \"mvp-ui-web\"", "name = \"mvp-ui-web-edited\"");
    let read = BuildVariantSet::from_toml_str(&edited).expect("still parses");
    assert_ne!(
        read, before,
        "the edit must be visible to a reader, else this proves nothing"
    );
    assert_eq!(
        HolgerUiBuildThing.variants(),
        before,
        "the code read the file — it must not"
    );
}

#[test]
fn the_comparison_reports_red_on_a_set_that_differs_by_one_field() {
    let set =
        BuildVariantSet::load_file(&BuildVariantSet::conventional_path(&repo_root())).unwrap();
    assert_eq!(set.variants.len(), 4, "4 [[build.variant]] rows: the open bundle, the metered bundle, the BFF and the OPEN `ui` (H5)");

    let mut p = set.clone();
    p.variants[0].target = None;
    assert_ne!(p, set, "a variant losing its target must compare unequal");
    let mut p = set.clone();
    p.variants[0].suites.clear();
    assert_ne!(
        p, set,
        "a variant losing its suite tag must compare unequal"
    );
}

/// **Every row is a build this repository already performs**, held to the values
/// the doors that perform it use: `Trunk.toml`, `README.md` §Release build
/// (`trunk build --release`) and `xtask publish` (`trunk build --release --dist
/// ~/.local/share/holger-console/dist`).
#[test]
fn the_rows_describe_the_builds_that_already_happen() {
    let set = declared();

    let v = set.get("mvp-ui-web").expect("mvp-ui-web is declared");
    assert_eq!(v.package.as_deref(), Some("holger-ui-web"));
    assert_eq!(v.bin.as_deref(), Some("holger-ui-web"));
    assert_eq!(v.target.as_deref(), Some("wasm32-unknown-unknown"));
    assert_eq!(v.profile, Profile::Release);
    assert_eq!(v.kind, ArtifactKind::Wasm);
    assert_eq!(
        v.role,
        Some(Role::Client),
        "a UI is a client, not a new role — `nornir_build_thing::plugin::Role` is \
         Server | Client | Solo and no `Ui` exists to spell"
    );
    assert!(
        v.member.is_none(),
        "a browser bundle is no system service: nothing installs a unit or a user for it"
    );
    assert_eq!(v.shape, ServiceShape::ThinStandalone);
    assert!(v.embeds.is_empty(), "nothing here compiles a sibling in");
    assert!(
        v.reaches.contains("holger"),
        "the console is a blank page without a running holger — the wire is gRPC-web \
         straight to the tonic-web door, with no BFF in between"
    );
    assert!(
        v.features.is_empty(),
        "the open bundle is what a bare `trunk build --release` makes: no feature"
    );

    // The suite tag, on the one row, although this repository has one delivery.
    // `workspace_nordisk/.nornir/SUITE-MODEL.md`: tagging is what lets one
    // command shape work house-wide. MVP because this console's surface is the
    // Secure Update Gateway's; ORIGINAL's `ui` atom is holger's egui app.
    assert_eq!(v.suites, ["MVP"]);

    // The feature universe is the paid half's one word (A28 M13).
    assert_eq!(set.offers.iter().map(String::as_str).collect::<Vec<_>>(), ["metered"]);

    // Exactly one normal case per role group, and there are two groups now.
    assert!(
        set.check_defaults().is_empty(),
        "{:?}",
        set.check_defaults()
    );
    assert!(
        set.get("mvp-ui-web").unwrap().is_default,
        "what a bare `trunk build --release` makes"
    );
    assert!(
        set.get("mvp-ui").unwrap().is_default,
        "what a bare `cargo build --release -p holger-ui` makes"
    );
}

/// ★ **The `mvp-ui` BFF row, and it names a build that runs.**
///
/// This test used to assert the OPPOSITE — `no_bff_row_is_declared_because_no_bff_package_exists`,
/// whose whole job was to make adding the row a deliberate act that came WITH
/// the crate rather than a copy of gunnar-ui's declaration describing nothing.
/// It carried its own retirement instruction:
///
/// > holger-ui-server now EXISTS — declare its row (see this test's doc comment)
/// > and delete this assertion
///
/// The crate landed 2026-09-17 and this is what replaced it: the same guard,
/// pointing the other way. A row whose package is not in the workspace is still
/// a row naming a build that cannot run, and that is now checked for the row
/// that exists rather than asserted about the one that did not.
#[test]
fn the_bff_row_names_a_package_that_is_in_this_workspace() {
    let set = declared();
    let v = set.get("mvp-ui").expect(
        "`mvp-ui` is the backend-for-frontend row; it was added the day \
         crates/holger-ui-server did",
    );

    // The program is the product crate `holger-ui` (HOL-PRODUCTS), over the library.
    assert_eq!(v.package.as_deref(), Some("holger-ui"));
    assert_eq!(v.bin.as_deref(), Some("holger-ui"));
    assert!(
        repo_root()
            .join("crates/holger-ui/Cargo.toml")
            .is_file(),
        "the row names a package this workspace does not contain, so \
         `cargo build -p holger-ui-server` fails with `package not found`"
    );
    assert_eq!(v.profile, Profile::Release);
    // ★ `service` since 2026-09-19, and the three facts that made it true are
    // checked here rather than assumed. This assertion said `Exe` until that
    // day, with the reason "this binary installs no unit — it has
    // --env-template and --check-env, which write nothing, and no --install".
    // All three clauses are now false, so the assertion moved with them.
    assert_eq!(
        v.kind,
        ArtifactKind::Service,
        "`holger-ui-server --install` mints a unit through skidbladnir \
         (holger_ui_server::lifecycle), so `service` is what is built"
    );
    assert_eq!(
        v.member.as_deref(),
        Some("holger-ui"),
        "a `service` REQUIRES a member: it is the account the unit runs as and the \
         one an uninstall knows to leave alone. It must equal \
         holger_ui_server::lifecycle::{{UNIT, USER}}"
    );
    assert_eq!(
        v.target.as_deref(),
        Some("x86_64-unknown-linux-musl"),
        "the triple `cargo xtask front plan` step 15 in private-holger-ops builds this \
         binary for. The row said `None` while the only plan that builds it said musl, \
         and a row that disagrees with its own door is the row that is wrong"
    );
    assert_eq!(v.role, Some(Role::Server), "it opens a port and holds state");
    assert_eq!(v.shape, ServiceShape::ThinStandalone);
    assert!(v.embeds.is_empty(), "nothing here compiles a sibling in");
    assert!(
        v.reaches.contains("holger"),
        "without a reachable holger every /api/ answer is a gateway refusal"
    );
    assert!(
        v.features.is_empty(),
        "the BFF row builds the open server: its `metered` half is turned on by \
         holger-estate-front, which links it as a library, and no door here builds it"
    );
    assert_eq!(v.suites, ["MVP"]);
    assert!(v.is_default, "the only row in the server group");
}

/// **NO `[[build.wasm]]` cell, and the absence is the declaration.**
///
/// The bundle is built by trunk, which runs the row's cargo build and then
/// wasm-bindgen, `wasm-opt` and the `index.html` asset pipeline — writing
/// CONTENT-HASHED names (`holger-ui-web-<hash>_bg.wasm`, which `xtask publish`
/// globs for by that `_bg.wasm` suffix). `BindgenStage` DERIVES its outputs from
/// the package name, so a cell here would name `holger_ui_web_bg.wasm` and
/// `holger_ui_web.js`, two files trunk never writes, and anything chaining the
/// cell would be checked against a claim that is false.
#[test]
fn the_console_declares_no_wasm_cell_because_trunk_is_not_wasm_bindgen() {
    let set = declared();
    assert!(
        set.wasms.is_empty(),
        "a [[build.wasm]] cell would have to describe trunk, and BindgenStage cannot: \
         trunk's outputs are content-hashed and it also runs wasm-opt and the index.html \
         pipeline. See this test's doc comment."
    );
    let bundle = repo_root().join("Trunk.toml");
    assert!(
        bundle.is_file(),
        "the bundler this repository actually uses: {}",
        bundle.display()
    );
}

/// ★ A28 M13: **the paid console is its own bundle.** `mvp-ui-web-metered` is the open row
/// with `metered`, into `dist-metered/` from `index-metered.html`; the open row stays the
/// client group's default, into `dist/` from `index.html`.
#[test]
fn the_metered_bundle_is_its_own_row_and_its_own_dist() {
    let set = declared();
    let open = set.get("mvp-ui-web").expect("the open bundle");
    let paid = set.get("mvp-ui-web-metered").expect("the metered bundle");
    assert_eq!(paid.features, ["metered"]);
    assert!(!paid.is_default, "a bare `trunk build --release` makes the open bundle");
    assert!(open.is_default);
    assert_eq!((paid.package.as_deref(), paid.bin.as_deref(), paid.target.as_deref(), paid.kind, paid.role), (open.package.as_deref(), open.bin.as_deref(), open.target.as_deref(), open.kind, open.role));
    let apps: Vec<(&str, &str, &str)> = set.web_apps.iter().map(|a| (a.name.as_str(), a.out_dir.as_str(), a.index.as_str())).collect();
    assert_eq!(apps, [("mvp-ui-web", "dist", "index.html"), ("mvp-ui-web-metered", "dist-metered", "index-metered.html")]);
    for (_, _, page) in &apps {
        assert!(repo_root().join(page).is_file(), "{page} is committed");
    }
}