Files
k-frame/crates/protocol/tests/round_trip_tests.rs
Gabriel Kaszewski 26ebfad3a2 add SPA config UI, wire media/rss adapters, event-driven layout push
- React SPA: dashboard, data sources CRUD, widgets CRUD, layout builder,
  presets. TanStack Router + Query, shadcn/ui, Vite proxy to :3000
- wire media + rss adapters into polling loop, remove xtb source type
- media adapter: read username/password from headers, proper subsonic auth
- event handler: subscribe to LayoutChanged, push screen update to clients
- fix clippy warnings across workspace (Default impls, collapsible ifs,
  redundant closures, is_none_or, unused imports)
2026-06-19 00:12:42 +02:00

97 lines
3.0 KiB
Rust

use protocol::{
ClientMessage, ServerMessage, WidgetDescriptor, WireContainerNode, WireDirection,
WireDisplayHint, WireKeyValue, WireLayoutChild, WireLayoutNode, WireSizing, WireValue,
WireWidgetState, decode_client_message, decode_server_message, encode, encode_client,
};
#[test]
fn screen_update_round_trips() {
let msg = ServerMessage::ScreenUpdate {
layout: WireLayoutNode::Container(WireContainerNode {
direction: WireDirection::Row,
gap: 4,
padding: 2,
children: vec![
WireLayoutChild {
sizing: WireSizing::Flex(1),
node: WireLayoutNode::Leaf(1),
},
WireLayoutChild {
sizing: WireSizing::Fixed(80),
node: WireLayoutNode::Leaf(2),
},
],
}),
widgets: vec![WidgetDescriptor {
id: 1,
display_hint: WireDisplayHint::IconValue,
state: WireWidgetState {
data: vec![
WireKeyValue {
key: "temperature".into(),
value: WireValue::String("5.4°C".into()),
},
WireKeyValue {
key: "icon".into(),
value: WireValue::String("cloud_rain".into()),
},
],
error: None,
},
}],
};
let frame = encode(&msg).unwrap();
let payload = &frame[4..];
let decoded = decode_server_message(payload).unwrap();
assert_eq!(msg, decoded);
}
#[test]
fn data_update_round_trips() {
let msg = ServerMessage::DataUpdate {
widgets: vec![WidgetDescriptor {
id: 3,
display_hint: WireDisplayHint::TextBlock,
state: WireWidgetState {
data: vec![WireKeyValue {
key: "body".into(),
value: WireValue::String("Breaking news...".into()),
}],
error: None,
},
}],
};
let frame = encode(&msg).unwrap();
let payload = &frame[4..];
let decoded = decode_server_message(payload).unwrap();
assert_eq!(msg, decoded);
}
#[test]
fn server_heartbeat_round_trips() {
let msg = ServerMessage::Heartbeat;
let frame = encode(&msg).unwrap();
let payload = &frame[4..];
let decoded = decode_server_message(payload).unwrap();
assert_eq!(msg, decoded);
}
#[test]
fn client_heartbeat_round_trips() {
let msg = ClientMessage::Heartbeat;
let frame = encode_client(&msg).unwrap();
let payload = &frame[4..];
let decoded = decode_client_message(payload).unwrap();
assert_eq!(msg, decoded);
}
#[test]
fn frame_has_correct_length_prefix() {
let msg = ServerMessage::Heartbeat;
let frame = encode(&msg).unwrap();
let len = u32::from_be_bytes([frame[0], frame[1], frame[2], frame[3]]) as usize;
assert_eq!(len, frame.len() - 4);
}