Files
k-frame/crates/client-application/tests/client_app_tests.rs

172 lines
4.8 KiB
Rust

use client_application::{ClientApp, RepaintCommand};
use client_domain::BoundingBox;
use protocol::{
ServerMessage, WidgetDescriptor, WireAlignItems, WireContainerNode, WireDirection,
WireDisplayHint, WireDisplayHintKind, WireJustifyContent, WireKeyValue, WireLayoutChild,
WireLayoutNode, WireSizing, WireValue, WireWidgetState,
};
fn screen() -> BoundingBox {
BoundingBox::screen(240, 320)
}
fn weather_descriptor(id: u16, temp: &str) -> WidgetDescriptor {
WidgetDescriptor {
id,
display_hint: WireDisplayHint::new(WireDisplayHintKind::IconValue),
state: WireWidgetState {
data: vec![WireKeyValue {
key: "temperature".into(),
value: WireValue::String(temp.into()),
}],
error: None,
},
}
}
fn two_widget_layout() -> WireLayoutNode {
WireLayoutNode::Container(WireContainerNode {
direction: WireDirection::Row,
gap: 0,
padding: 0,
justify_content: WireJustifyContent::Start,
align_items: WireAlignItems::Stretch,
children: vec![
WireLayoutChild {
sizing: WireSizing::Flex(1),
node: WireLayoutNode::Leaf(1),
},
WireLayoutChild {
sizing: WireSizing::Flex(1),
node: WireLayoutNode::Leaf(2),
},
],
})
}
#[test]
fn screen_update_repaints_all_widgets() {
let mut app = ClientApp::new(screen());
let msg = ServerMessage::ScreenUpdate {
layout: two_widget_layout(),
widgets: vec![
weather_descriptor(1, "5.4°C"),
weather_descriptor(2, "20°C"),
],
};
let repaints = app.handle_message(msg);
assert_eq!(repaints.len(), 2);
assert_eq!(repaints[0].widget_id, 1);
assert_eq!(repaints[0].bounds, BoundingBox::new(0, 0, 120, 320));
assert_eq!(repaints[1].widget_id, 2);
assert_eq!(repaints[1].bounds, BoundingBox::new(120, 0, 120, 320));
}
#[test]
fn data_update_only_repaints_changed_widgets() {
let mut app = ClientApp::new(screen());
app.handle_message(ServerMessage::ScreenUpdate {
layout: two_widget_layout(),
widgets: vec![
weather_descriptor(1, "5.4°C"),
weather_descriptor(2, "20°C"),
],
});
let repaints = app.handle_message(ServerMessage::DataUpdate {
widgets: vec![weather_descriptor(1, "6.1°C")],
});
assert_eq!(repaints.len(), 1);
assert_eq!(repaints[0].widget_id, 1);
assert_eq!(
repaints[0].state.data[0].value,
WireValue::String("6.1°C".into())
);
}
#[test]
fn data_update_with_unchanged_data_produces_no_repaints() {
let mut app = ClientApp::new(screen());
app.handle_message(ServerMessage::ScreenUpdate {
layout: two_widget_layout(),
widgets: vec![
weather_descriptor(1, "5.4°C"),
weather_descriptor(2, "20°C"),
],
});
let repaints = app.handle_message(ServerMessage::DataUpdate {
widgets: vec![weather_descriptor(1, "5.4°C")],
});
assert!(repaints.is_empty());
}
#[test]
fn second_screen_update_repaints_all_widgets_with_new_layout() {
let mut app = ClientApp::new(screen());
app.handle_message(ServerMessage::ScreenUpdate {
layout: two_widget_layout(),
widgets: vec![
weather_descriptor(1, "5.4°C"),
weather_descriptor(2, "20°C"),
],
});
let column_layout = WireLayoutNode::Container(WireContainerNode {
direction: WireDirection::Column,
gap: 0,
padding: 0,
justify_content: WireJustifyContent::Start,
align_items: WireAlignItems::Stretch,
children: vec![
WireLayoutChild {
sizing: WireSizing::Flex(1),
node: WireLayoutNode::Leaf(1),
},
WireLayoutChild {
sizing: WireSizing::Flex(1),
node: WireLayoutNode::Leaf(2),
},
],
});
let repaints = app.handle_message(ServerMessage::ScreenUpdate {
layout: column_layout,
widgets: vec![
weather_descriptor(1, "5.4°C"),
weather_descriptor(2, "20°C"),
],
});
assert_eq!(repaints.len(), 2);
assert_eq!(repaints[0].bounds, BoundingBox::new(0, 0, 240, 160));
assert_eq!(repaints[1].bounds, BoundingBox::new(0, 160, 240, 160));
}
#[test]
fn data_update_before_screen_update_produces_no_repaints() {
let mut app = ClientApp::new(screen());
let repaints = app.handle_message(ServerMessage::DataUpdate {
widgets: vec![weather_descriptor(1, "5.4°C")],
});
assert!(repaints.is_empty());
}
#[test]
fn heartbeat_produces_no_repaints() {
let mut app = ClientApp::new(screen());
let repaints = app.handle_message(ServerMessage::Heartbeat);
assert!(repaints.is_empty());
}