Skip to content

Commit 7234128

Browse files
authored
tests: Simple parts drawing tests (#84)
1 parent a372272 commit 7234128

11 files changed

Lines changed: 197 additions & 5 deletions

src/lib.rs

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,3 +909,195 @@ fn get_margin_h_lp(state: &WindowState, hider_border: bool) -> f32 {
909909
theme::visible_border_size(hider_border) as f32
910910
}
911911
}
912+
913+
#[cfg(test)]
914+
mod tests {
915+
#![allow(clippy::unwrap_used, clippy::indexing_slicing)]
916+
917+
use tiny_skia::{Paint, Shader};
918+
919+
use crate::parts::PartLayout;
920+
921+
use super::*;
922+
923+
fn expected_file_path(name: &str) -> String {
924+
format!("./tests/parts/{name}.expected.png")
925+
}
926+
fn got_file_path(name: &str) -> String {
927+
format!("./tests/parts/{name}.got.png")
928+
}
929+
930+
#[track_caller]
931+
fn png_check(name: &str, got: &[u8]) {
932+
let expected = std::fs::read(expected_file_path(name)).unwrap();
933+
std::fs::write(got_file_path(name), got).unwrap();
934+
assert_eq!(
935+
expected,
936+
got,
937+
"Mismatch in the file: {}",
938+
got_file_path(name)
939+
);
940+
}
941+
942+
#[allow(unused)]
943+
#[track_caller]
944+
fn png_update_expected(name: &str, got: &[u8]) {
945+
std::fs::write(expected_file_path(name), got).unwrap();
946+
}
947+
948+
fn test_layout_config() -> LayoutConfig {
949+
LayoutConfig {
950+
width: 200,
951+
height: 200,
952+
hide_titlebar: false,
953+
hide_border: false,
954+
hide_edges: false,
955+
}
956+
}
957+
958+
fn draw_test_part(layout_config: LayoutConfig, part_id: PartId) -> Pixmap {
959+
let layout = PartLayout::calc(layout_config);
960+
961+
let rect = layout[part_id as usize].surface_rect;
962+
963+
let mut pixmap = Pixmap::new(rect.width, rect.height).unwrap();
964+
965+
let theme = ColorTheme::dark();
966+
let colors = theme.for_state(true);
967+
968+
let buttons = Buttons::new(None);
969+
let mut shadow = Shadow::default();
970+
971+
draw_part(
972+
part_id,
973+
rect,
974+
&mut pixmap.as_mut(),
975+
None,
976+
1,
977+
true,
978+
&WindowState::ACTIVATED,
979+
colors,
980+
&buttons,
981+
Location::None,
982+
layout_config.hide_border,
983+
layout_config.hide_titlebar,
984+
&mut shadow,
985+
);
986+
987+
pixmap
988+
}
989+
990+
#[test]
991+
fn part_left() {
992+
let got = draw_test_part(test_layout_config(), PartId::Left)
993+
.encode_png()
994+
.unwrap();
995+
png_check("part-left", &got);
996+
}
997+
998+
#[test]
999+
fn part_right() {
1000+
let got = draw_test_part(test_layout_config(), PartId::Right)
1001+
.encode_png()
1002+
.unwrap();
1003+
png_check("part-right", &got);
1004+
}
1005+
1006+
#[test]
1007+
fn part_top() {
1008+
let got = draw_test_part(test_layout_config(), PartId::Top)
1009+
.encode_png()
1010+
.unwrap();
1011+
png_check("part-top", &got);
1012+
}
1013+
1014+
#[test]
1015+
fn part_bottom() {
1016+
let got = draw_test_part(test_layout_config(), PartId::Bottom)
1017+
.encode_png()
1018+
.unwrap();
1019+
png_check("part-bottom", &got);
1020+
}
1021+
1022+
#[test]
1023+
fn part_header() {
1024+
let got = draw_test_part(test_layout_config(), PartId::Header)
1025+
.encode_png()
1026+
.unwrap();
1027+
png_check("part-header", &got);
1028+
}
1029+
1030+
fn draw_combined(layout_config: LayoutConfig) -> Pixmap {
1031+
let layout = PartLayout::calc(layout_config);
1032+
1033+
let mut pixmap = Pixmap::new(400, 400).unwrap();
1034+
pixmap.fill(Color::WHITE);
1035+
1036+
let root_x = 100;
1037+
let root_y = 100;
1038+
1039+
pixmap.fill_rect(
1040+
tiny_skia::Rect::from_xywh(root_x as f32, root_y as f32, 200.0, 200.0).unwrap(),
1041+
&Paint {
1042+
shader: Shader::SolidColor(Color::TRANSPARENT),
1043+
..Default::default()
1044+
},
1045+
Transform::identity(),
1046+
None,
1047+
);
1048+
1049+
let mut draw_pixmap = |part_id: PartId| {
1050+
let part = draw_test_part(layout_config, part_id);
1051+
let rect = layout[part_id as usize].surface_rect;
1052+
pixmap.draw_pixmap(
1053+
root_x + rect.x,
1054+
root_y + rect.y,
1055+
part.as_ref(),
1056+
&PixmapPaint::default(),
1057+
Transform::identity(),
1058+
None,
1059+
);
1060+
};
1061+
1062+
for id in 0..PartId::COUNT {
1063+
if layout_config.hide_titlebar && id == PartId::Header as usize {
1064+
continue;
1065+
}
1066+
draw_pixmap(PartId::from_usize(id));
1067+
}
1068+
1069+
pixmap
1070+
}
1071+
1072+
#[test]
1073+
fn combined_parts() {
1074+
let layout_config = test_layout_config();
1075+
let got = draw_combined(layout_config).encode_png().unwrap();
1076+
png_check("combined-parts", &got);
1077+
}
1078+
1079+
#[test]
1080+
fn combined_parts_no_titlebar() {
1081+
let mut layout_config = test_layout_config();
1082+
layout_config.hide_titlebar = true;
1083+
let got = draw_combined(layout_config).encode_png().unwrap();
1084+
png_check("combined-parts-no-titlebar", &got);
1085+
}
1086+
1087+
#[test]
1088+
fn combined_parts_no_border() {
1089+
let mut layout_config = test_layout_config();
1090+
layout_config.hide_border = true;
1091+
let got = draw_combined(layout_config).encode_png().unwrap();
1092+
png_check("combined-parts-no-border", &got);
1093+
}
1094+
1095+
#[test]
1096+
fn combined_parts_no_titlebar_and_border() {
1097+
let mut layout_config = test_layout_config();
1098+
layout_config.hide_titlebar = true;
1099+
layout_config.hide_border = true;
1100+
let got = draw_combined(layout_config).encode_png().unwrap();
1101+
png_check("combined-parts-no-titlebar-and-border", &got);
1102+
}
1103+
}

src/parts.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl PartId {
3232
const HEADER: usize = Self::Header as usize;
3333
pub const COUNT: usize = 5;
3434

35-
fn from_usize(v: usize) -> Self {
35+
pub fn from_usize(v: usize) -> Self {
3636
match v {
3737
Self::TOP => PartId::Top,
3838
Self::LEFT => PartId::Left,
@@ -180,17 +180,17 @@ pub struct LayoutConfig {
180180
}
181181

182182
#[derive(Default, Debug, Clone, Copy)]
183-
struct PartLayout {
183+
pub struct PartLayout {
184184
/// Positioned relative to the main surface.
185-
surface_rect: Rect,
185+
pub surface_rect: Rect,
186186
/// Positioned relative to the local surface, aka. `surface_rect`.
187187
///
188188
/// `None` if it fully covers `surface_rect`.
189-
input_rect: Option<Rect>,
189+
pub input_rect: Option<Rect>,
190190
}
191191

192192
impl PartLayout {
193-
fn calc(config: LayoutConfig) -> [Self; 5] {
193+
pub fn calc(config: LayoutConfig) -> [Self; 5] {
194194
let LayoutConfig {
195195
width,
196196
height,
34.1 KB
Loading
30.2 KB
Loading
32.1 KB
Loading
36.1 KB
Loading
1.98 KB
Loading
675 Bytes
Loading

tests/parts/part-left.expected.png

10 KB
Loading
10.9 KB
Loading

0 commit comments

Comments
 (0)