diff --git a/crates/aura-cli/tests/cli_run.rs b/crates/aura-cli/tests/cli_run.rs index 4cc769a..8ee4c68 100644 --- a/crates/aura-cli/tests/cli_run.rs +++ b/crates/aura-cli/tests/cli_run.rs @@ -655,6 +655,60 @@ fn graph_emits_self_contained_html_viewer() { assert!(!stdout.contains("Sub(#Sf,#Ss)"), "retired ascii-dag notation must be gone: {stdout}"); } +/// Property (#28): `aura graph ` renders the CONSUMER's own +/// graph — the structure of the file it is handed — not the embedded r_sma +/// sample. Mirrors the `dispatch_run` dual-grammar: a first-positional naming +/// an existing `.json` selects the loaded-blueprint branch, which reads the +/// file, reloads it via `blueprint_from_json`, and `render_html`s it — so the +/// emitted page's inlined `window.AURA_MODEL` reflects THAT file's nodes. +/// Handed the retired r-breakout example (std-vocabulary only, so no project is +/// needed), the page must carry a marker unique to that graph — `channel_hi`, a +/// RollingMax node name absent from the sample and from every static viewer +/// asset — and must NOT carry the sample-only `"type":"Bias"` node, i.e. it did +/// not silently fall back to the embedded r_sma sample. Driven through the built +/// binary so it pins the observable CLI contract. +#[test] +fn graph_renders_a_consumer_blueprint_file_not_the_embedded_sample() { + let cwd = temp_cwd("graph-consumer-blueprint"); + // A committed consumer blueprint that is NOT the embedded sample and resolves + // against the base std vocabulary alone (RollingMax/RollingMin/Delay/Gt/Latch/ + // Sub) — no project fixture required. Absolute path, so the temp cwd is free of + // any Aura.toml (guarantees std-env resolution). + let blueprint = format!("{}/examples/r_breakout.json", env!("CARGO_MANIFEST_DIR")); + let out = Command::new(BIN) + .arg("graph") + .arg(&blueprint) + .current_dir(&cwd) + .output() + .expect("spawn aura graph "); + assert_eq!( + out.status.code(), + Some(0), + "`aura graph ` exit: {:?}\nstderr: {}", + out.status, + String::from_utf8_lossy(&out.stderr) + ); + let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout"); + // the page inlines a model as the viewer's data source... + assert!( + stdout.contains("window.AURA_MODEL = {\"root\":"), + "model not inlined into the page" + ); + // ...and that model is the CONSUMER graph's — its own node `channel_hi` + // (unique to r-breakout, absent from the r_sma sample and from every static + // asset) is present. + assert!( + stdout.contains("channel_hi"), + "the consumer blueprint's own node (channel_hi) is missing — its graph was not rendered" + ); + // ...NOT the embedded r_sma sample: the sample's Bias node type must be absent + // (proof the file was rendered, not silently ignored in favour of the sample). + assert!( + !stdout.contains("\"type\":\"Bias\""), + "rendered the embedded r_sma sample (its Bias node is present) instead of the consumer blueprint" + ); +} + #[test] fn sweep_with_trailing_token_is_strict_and_exits_two() { // strict-arg reading (#16): an unexpected trailing token is a usage error.