dwarves-gui/tests/robot_mimir_release.rs
//! **ROBOT-UI: the 🚀 Mímir release tab draws the plan the FORGE read from Mímir.**
//!
//! ```text
//! mock nornir (Mimir dependency verbs) ── forge (MimirRelease on its jera lane) ── the shell
//! ```
//!
//! The shipped shell is given only the forge. The tab asks `MimirRelease.Plan`; the forge
//! answers at once with the jera job, computes the plan from the mock's BuildOrder /
//! DepsOf / ChangedSinceLastRelease / AffectedByChange, and the tab — asking again — draws:
//!
//! 1. Mímir's release order and each repo's convergence (`moved` / `downstream` /
//! `converged`) and dependencies;
//! 2. what to release, in order;
//! 3. every Mímir read was made BY THE FORGE for the selected workspace (the shell holds
//! no nornir address, and reads no checkout);
//! 4. no publish affordance.
mod common;
use std::collections::BTreeMap;
use common::*;
use facett_core::Facet;
use nornir_warehouse_embed::testkit::{spawn_mock_mimir, MockMimir};
use serde_json::json;
fn mimir() -> MockMimir {
let dep = |repo: &str, deps: serde_json::Value| {
(
repo.to_string(),
json!({ "repo": repo, "transitive": false, "dependencies": deps }).to_string(),
)
};
MockMimir {
build_order: json!({ "build_order": ["shop-core", "shop", "web"] }).to_string(),
deps_of: BTreeMap::from([
dep("shop-core", json!([])),
dep(
"shop",
json!([{ "repo": "shop-core", "via": ["shop-core"] }]),
),
dep(
"web",
json!([{ "repo": "shop", "via": ["shop", "shop-api"] }]),
),
]),
changed_since_last_release: Ok(
json!({ "changed": ["shop"], "affected": ["shop", "web"], "build_order": [] })
.to_string(),
),
affected_by_change: json!({ "changed": ["shop"], "affected": ["shop", "web"] }).to_string(),
..MockMimir::default()
}
}
#[test]
fn the_mimir_release_tab_draws_the_forges_plan_from_mimir() {
let m = mimir();
let calls = m.calls.clone();
let nornir = spawn_mock_mimir(m);
let forge = dwarves::mimir_release::spawn_forge(nornir.endpoint.clone(), String::new());
let mut app = shell(&forge.endpoint);
Facet::update_json(&mut app, &json!({ "set_tab": "Mímir release" }).to_string());
Facet::update_json(&mut app, r#"{"wait":true}"#);
let s = Facet::state_json(&app);
let r = &s["mimir-release"];
// 1. the order, the convergence, the dependencies — Mímir's
assert_eq!(r["state"], "done", "{r}");
assert_eq!(r["plan"]["order"], json!(["shop-core", "shop", "web"]));
assert_eq!(
r["plan"]["status"],
json!({ "shop-core": "converged", "shop": "moved", "web": "downstream" })
);
assert_eq!(r["plan"]["deps"]["web"], json!(["shop"]));
assert_eq!(r["plan"]["since_last_release"], "measured");
// 2. what to release
assert_eq!(r["plan"]["to_release"], json!(["shop", "web"]));
// 3. asked of the forge, for the selected workspace; the forge read Mímir
assert!(
r["via"].as_str().unwrap().contains("MimirRelease.Plan"),
"{r}"
);
assert!(
!r["job_id"].as_str().unwrap_or("").is_empty(),
"the plan names the jera job that computed it: {r}"
);
let calls = calls.lock().unwrap().clone();
assert!(
!calls.is_empty() && calls.iter().all(|c| c.ends_with(&format!(" {WS}"))),
"{calls:?}"
);
assert_eq!(r["reads_local_checkouts"], false);
// 4. nothing to publish
assert_eq!(r["can_publish"], false);
matrix("mimir_release_tab_draws_the_forges_plan", true, "🚀 Mímir release: MimirRelease.Plan on the forge's jera lane, from Mímir's BuildOrder/DepsOf/ChangedSinceLastRelease/AffectedByChange, drawn as order + convergence + to-release");
}