|
@@ -197,6 +197,7 @@ fn stale_from_snapshot_picks_unreachable_nodes() {
|
|
|
ha: None,
|
|
ha: None,
|
|
|
};
|
|
};
|
|
|
let snap = crate::web::events::Snapshot {
|
|
let snap = crate::web::events::Snapshot {
|
|
|
|
|
+ version: String::new(),
|
|
|
ts: 1,
|
|
ts: 1,
|
|
|
clusters: vec![crate::web::events::ClusterSnap {
|
|
clusters: vec![crate::web::events::ClusterSnap {
|
|
|
name: "c".into(),
|
|
name: "c".into(),
|
|
@@ -219,6 +220,7 @@ fn stale_from_snapshot_picks_unreachable_nodes() {
|
|
|
async fn token_gate_covers_recipes_panel() {
|
|
async fn token_gate_covers_recipes_panel() {
|
|
|
let app = app_state(Some("s3cret"));
|
|
let app = app_state(Some("s3cret"));
|
|
|
*app.last.lock().unwrap() = Some(crate::web::events::Snapshot {
|
|
*app.last.lock().unwrap() = Some(crate::web::events::Snapshot {
|
|
|
|
|
+ version: String::new(),
|
|
|
ts: 1,
|
|
ts: 1,
|
|
|
clusters: Vec::new(),
|
|
clusters: Vec::new(),
|
|
|
jobs: Vec::new(),
|
|
jobs: Vec::new(),
|
|
@@ -280,6 +282,7 @@ async fn sse_replays_cached_snapshot_on_connect() {
|
|
|
// cached snapshot, otherwise a fresh client waits a whole poll tick.
|
|
// cached snapshot, otherwise a fresh client waits a whole poll tick.
|
|
|
let app = app_state(None);
|
|
let app = app_state(None);
|
|
|
*app.last.lock().unwrap() = Some(crate::web::events::Snapshot {
|
|
*app.last.lock().unwrap() = Some(crate::web::events::Snapshot {
|
|
|
|
|
+ version: String::new(),
|
|
|
ts: 1,
|
|
ts: 1,
|
|
|
clusters: Vec::new(),
|
|
clusters: Vec::new(),
|
|
|
jobs: Vec::new(),
|
|
jobs: Vec::new(),
|
|
@@ -305,6 +308,7 @@ async fn sse_replays_cached_snapshot_on_connect() {
|
|
|
async fn bus_delivers_state_events() {
|
|
async fn bus_delivers_state_events() {
|
|
|
let (tx, mut rx) = tokio::sync::broadcast::channel::<Event>(8);
|
|
let (tx, mut rx) = tokio::sync::broadcast::channel::<Event>(8);
|
|
|
let snap = crate::web::events::Snapshot {
|
|
let snap = crate::web::events::Snapshot {
|
|
|
|
|
+ version: String::new(),
|
|
|
ts: 1,
|
|
ts: 1,
|
|
|
clusters: Vec::new(),
|
|
clusters: Vec::new(),
|
|
|
jobs: Vec::new(),
|
|
jobs: Vec::new(),
|
|
@@ -327,6 +331,36 @@ async fn bus_delivers_state_events() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// The dashboard header carries a small version badge under the title; the
|
|
|
|
|
+/// version itself is baked in at image build (`SM121_VERSION`) and reaches the
|
|
|
|
|
+/// page through the state snapshot, so a plain `cargo build` shows `dev`.
|
|
|
|
|
+#[test]
|
|
|
|
|
+fn header_shows_the_build_version() {
|
|
|
|
|
+ use crate::web::events::build_snapshot;
|
|
|
|
|
+ let snap = build_snapshot(
|
|
|
|
|
+ &fake_config(),
|
|
|
|
|
+ &crate::web::probe::Fleet {
|
|
|
|
|
+ nodes: std::collections::HashMap::new(),
|
|
|
|
|
+ switch_off: std::collections::HashMap::new(),
|
|
|
|
|
+ soft_off: std::collections::HashMap::new(),
|
|
|
|
|
+ ha: std::collections::HashMap::new(),
|
|
|
|
|
+ },
|
|
|
|
|
+ &[],
|
|
|
|
|
+ &[],
|
|
|
|
|
+ &std::collections::HashMap::new(),
|
|
|
|
|
+ );
|
|
|
|
|
+ assert_eq!(snap.version, crate::build_info::version());
|
|
|
|
|
+ let json = serde_json::to_string(&snap).unwrap();
|
|
|
|
|
+ assert!(
|
|
|
|
|
+ json.contains("\"version\""),
|
|
|
|
|
+ "state JSON has no version: {json}"
|
|
|
|
|
+ );
|
|
|
|
|
+ let page = super::UI_HTML;
|
|
|
|
|
+ for needle in ["id=\"ver\"", "header .ver", "v\" + snap.version"] {
|
|
|
|
|
+ assert!(page.contains(needle), "dashboard page missing {needle}");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[tokio::test]
|
|
#[tokio::test]
|
|
|
async fn snapshot_serializes_with_type_tag() {
|
|
async fn snapshot_serializes_with_type_tag() {
|
|
|
let ev = Event::State {
|
|
let ev = Event::State {
|