Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-widgets/tests/control_snapshots.rs
StratoSDK / crates / strato-widgets / tests / control_snapshots.rs
1use glam::Vec2;
2use std::collections::BTreeMap;
3use strato_core::layout::{Constraints, Layout};
4use strato_renderer::{batch::DrawCommand, batch::RenderBatch};
5use strato_widgets::button::ButtonState;
6use strato_widgets::{Button, Slider, Theme, Widget};
7 
8fn summarize_batch(batch: &RenderBatch) -> Vec<String> {
9 batch
10 .commands
11 .iter()
12 .map(|cmd| match cmd {
13 DrawCommand::Rect { rect, color, .. } => format!(
14 "rect {:.1},{:.1} {:.1}x{:.1} rgba({:.2},{:.2},{:.2},{:.2})",
15 rect.x, rect.y, rect.width, rect.height, color.r, color.g, color.b, color.a
16 ),
17 DrawCommand::Text {
18 text,
19 position,
20 color,
21 font_size,
22 ..
23 } => format!(
24 "text '{}' @({:.1},{:.1}) size {:.1} rgba({:.2},{:.2},{:.2},{:.2})",
25 text, position.0, position.1, font_size, color.r, color.g, color.b, color.a
26 ),
27 DrawCommand::Circle {
28 center,
29 radius,
30 color,
31 ..
32 } => format!(
33 "circle ({:.1},{:.1}) r{:.1} rgba({:.2},{:.2},{:.2},{:.2})",
34 center.0, center.1, radius, color.r, color.g, color.b, color.a
35 ),
36 other => format!("{:?}", other),
37 })
38 .collect()
39}
40 
41fn render_button_with_state(state: ButtonState) -> Vec<String> {
42 let theme = Theme::default();
43 let mut button = Button::new(format!("{:?}", state)).size(140.0, 44.0);
44 button.set_state(state);
45 
46 let mut batch = RenderBatch::new();
47 let size = <Button as Widget>::layout(&mut button, Constraints::tight(140.0, 44.0));
48 let layout = Layout::new(Vec2::ZERO, size);
49 let ctx = strato_widgets::widget::WidgetContext {
50 theme: &theme,
51 state,
52 is_focused: matches!(state, ButtonState::Focused),
53 is_hovered: matches!(state, ButtonState::Hovered),
54 delta_time: 1.0,
55 };
56 button.update(&ctx);
57 button.render(&mut batch, layout);
58 
59 summarize_batch(&batch)
60}
61 
62fn render_slider_variant(disabled: bool) -> Vec<String> {
63 let mut slider = Slider::new(0.0, 100.0).size(200.0, 32.0).enabled(!disabled);
64 slider.set_value(50.0);
65 
66 let mut batch = RenderBatch::new();
67 let size = <Slider as Widget>::layout(&mut slider, Constraints::tight(220.0, 48.0));
68 let layout = Layout::new(Vec2::ZERO, size);
69 let theme = Theme::default();
70 let ctx = strato_widgets::widget::WidgetContext {
71 theme: &theme,
72 state: if disabled {
73 ButtonState::Disabled
74 } else {
75 ButtonState::Normal
76 },
77 is_focused: false,
78 is_hovered: false,
79 delta_time: 1.0,
80 };
81 slider.update(&ctx);
82 slider.render(&mut batch, layout);
83 
84 summarize_batch(&batch)
85}
86 
87fn format_snapshot(map: &BTreeMap<String, Vec<String>>) -> String {
88 let mut lines = Vec::new();
89 for (key, entries) in map {
90 lines.push(format!("{}:", key));
91 for entry in entries {
92 lines.push(format!(" - {}", entry));
93 }
94 }
95 lines.join("\n")
96}
97 
98const EXPECTED_BUTTON_SNAPSHOT: &str = include_str!("snapshots/button_state_commands.snap");
99const EXPECTED_SLIDER_SNAPSHOT: &str = include_str!("snapshots/slider_commands.snap");
100 
101#[test]
102fn button_state_snapshots() {
103 let mut snapshots = BTreeMap::new();
104 for state in [
105 ButtonState::Normal,
106 ButtonState::Hovered,
107 ButtonState::Pressed,
108 ButtonState::Focused,
109 ButtonState::Disabled,
110 ] {
111 snapshots.insert(format!("{:?}", state), render_button_with_state(state));
112 }
113 let rendered = format_snapshot(&snapshots);
114 assert_eq!(
115 rendered.trim(),
116 EXPECTED_BUTTON_SNAPSHOT.replace("\r\n", "\n").trim()
117 );
118}
119 
120#[test]
121fn slider_snapshots() {
122 let mut snapshots = BTreeMap::new();
123 snapshots.insert("enabled".to_string(), render_slider_variant(false));
124 snapshots.insert("disabled".to_string(), render_slider_variant(true));
125 let rendered = format_snapshot(&snapshots);
126 assert_eq!(
127 rendered.trim(),
128 EXPECTED_SLIDER_SNAPSHOT.replace("\r\n", "\n").trim()
129 );
130}
131