Tighten web surfaces and clean handoff
This commit is contained in:
@@ -277,6 +277,7 @@ fn handle_websocket(
|
||||
let mut sequence = 1u64;
|
||||
let mut last_event_millis = None::<u64>;
|
||||
let mut last_event_signatures = Vec::<(Option<String>, String)>::new();
|
||||
let mut last_streamed_preview = None::<crate::dto::ApiPreviewSnapshot>;
|
||||
loop {
|
||||
let snapshot = service.snapshot();
|
||||
send_stream_message(
|
||||
@@ -286,13 +287,22 @@ fn handle_websocket(
|
||||
ApiStreamMessage::Snapshot(ApiStateSnapshot::from_snapshot(&snapshot)),
|
||||
)?;
|
||||
sequence += 1;
|
||||
send_stream_message(
|
||||
&mut stream,
|
||||
sequence,
|
||||
snapshot.generated_at_millis,
|
||||
ApiStreamMessage::Preview(crate::dto::ApiPreviewSnapshot::from_snapshot(&snapshot)),
|
||||
)?;
|
||||
sequence += 1;
|
||||
|
||||
let preview_payload = crate::dto::ApiPreviewSnapshot::from_snapshot(&snapshot);
|
||||
if last_streamed_preview
|
||||
.as_ref()
|
||||
.map(|previous| previous != &preview_payload)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
send_stream_message(
|
||||
&mut stream,
|
||||
sequence,
|
||||
snapshot.generated_at_millis,
|
||||
ApiStreamMessage::Preview(preview_payload.clone()),
|
||||
)?;
|
||||
sequence += 1;
|
||||
last_streamed_preview = Some(preview_payload);
|
||||
}
|
||||
|
||||
let mut new_events = snapshot
|
||||
.recent_events
|
||||
|
||||
@@ -147,6 +147,28 @@ fn web_ui_browser_smoke_serves_shell_assets_and_stream_bootstrap() {
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn technical_surface_script_guards_missing_recent_events_in_state_snapshot() {
|
||||
let server = start_server();
|
||||
let technical_js = send_http_request(server.local_addr(), "GET", "/technical.js", None);
|
||||
let state = send_http_request(server.local_addr(), "GET", "/api/v1/state", None);
|
||||
let state_body: Value = serde_json::from_str(&state.body).expect("state json");
|
||||
|
||||
assert_eq!(technical_js.status_code, 200);
|
||||
assert!(technical_js
|
||||
.body
|
||||
.contains("function snapshotRecentEvents(snapshot)"));
|
||||
assert!(technical_js
|
||||
.body
|
||||
.contains("Array.isArray(snapshot?.recent_events) ? snapshot.recent_events : []"));
|
||||
assert!(technical_js
|
||||
.body
|
||||
.contains("const recentEvents = snapshotRecentEvents(appState.snapshot);"));
|
||||
assert!(state_body["state"].get("recent_events").is_none());
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn state_preview_and_snapshot_endpoints_are_versioned_and_separated() {
|
||||
let server = start_server();
|
||||
@@ -268,6 +290,40 @@ fn technical_surface_commands_update_backend_node_targets_and_panel_mapping() {
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn technical_surface_can_disable_output_again_after_enabling_it() {
|
||||
let server = start_server();
|
||||
|
||||
let enable_mode = send_command_json(
|
||||
server.local_addr(),
|
||||
r#"{"command":{"type":"set_output_backend_mode","payload":{"mode":"ddp_wled"}}}"#,
|
||||
);
|
||||
let enable_output = send_command_json(
|
||||
server.local_addr(),
|
||||
r#"{"command":{"type":"set_live_output_enabled","payload":{"enabled":true}}}"#,
|
||||
);
|
||||
let disable_output = send_command_json(
|
||||
server.local_addr(),
|
||||
r#"{"command":{"type":"set_live_output_enabled","payload":{"enabled":false}}}"#,
|
||||
);
|
||||
|
||||
assert_eq!(enable_mode.status_code, 200);
|
||||
assert_eq!(enable_output.status_code, 200);
|
||||
assert_eq!(disable_output.status_code, 200);
|
||||
|
||||
let state = send_http_request(server.local_addr(), "GET", "/api/v1/state", None);
|
||||
let state_body: Value = serde_json::from_str(&state.body).expect("state json");
|
||||
|
||||
assert_eq!(state_body["state"]["technical"]["backend_mode"], "ddp_wled");
|
||||
assert_eq!(state_body["state"]["technical"]["output_enabled"], false);
|
||||
assert_eq!(
|
||||
state_body["state"]["technical"]["live_status"],
|
||||
"DDP (WLED) selected - output disabled"
|
||||
);
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discovery_scan_endpoint_returns_structured_results_and_rejects_invalid_subnets() {
|
||||
let server = start_server();
|
||||
|
||||
Reference in New Issue
Block a user