@@ -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+ }
0 commit comments