diff --git a/crates/ui-egui/src/dialogs/tests.rs b/crates/ui-egui/src/dialogs/tests.rs index 51959c320..5794ae7e4 100644 --- a/crates/ui-egui/src/dialogs/tests.rs +++ b/crates/ui-egui/src/dialogs/tests.rs @@ -466,12 +466,13 @@ fn dialogs_do_not_stretch_to_the_screen() { #[test] fn workspace_and_toolbar_dialogs_end_at_their_buttons() { // New Workspace, Manage Workspaces, New Toolbar and Manage Toolbars draw their own windows: each - // ends just below its OK button, with no empty band above or below the buttons. - for (kind, fields, window) in [ - ("newWorkspace", json!({"name": "Mine"}), "dialog-workspace"), - ("manageWorkspaces", json!({"selected": "", "name": ""}), "dialog-workspace"), - (crate::custom_toolbars::KIND, json!({"name": "Toolbar 1"}), "dialog-new-toolbar"), - (crate::custom_toolbars::MANAGE, json!({"selected": "", "name": ""}), "dialog-manage-toolbars"), + // ends just below its OK button, with no empty band above or below the buttons, and Cancel (where + // the dialog has one) sits on OK's row, to its left. + for (kind, fields, window, has_cancel) in [ + ("newWorkspace", json!({"name": "Mine"}), "dialog-workspace", true), + ("manageWorkspaces", json!({"selected": "", "name": ""}), "dialog-workspace", false), + (crate::custom_toolbars::KIND, json!({"name": "Toolbar 1"}), "dialog-new-toolbar", true), + (crate::custom_toolbars::MANAGE, json!({"selected": "", "name": ""}), "dialog-manage-toolbars", false), ] { let mut app = app(); open(&mut app, kind, fields); @@ -479,20 +480,46 @@ fn workspace_and_toolbar_dialogs_end_at_their_buttons() { theme::install_fonts(&ctx); theme::apply(&ctx, Default::default()); let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1600.0, 1000.0)); - let mut ok = None; + let mut shapes = Vec::new(); for _ in 0..4 { let input = egui::RawInput { screen_rect: Some(screen), ..Default::default() }; let mut out = ctx.run_ui(input, |ui| show(&mut app, ui.ctx())); out.textures_delta.clear(); - ok = out.shapes.iter().find_map(|c| match &c.shape { - egui::Shape::Text(t) if t.galley.text() == "OK" => Some(t.visual_bounding_rect()), - _ => None, - }); + shapes = out.shapes; } - let ok = ok.unwrap_or_else(|| panic!("{kind} draws no OK button")); let outer = ctx.memory(|m| m.area_rect(egui::Id::unique(window))).unwrap(); + let texts = |label: &str| -> Vec { + shapes + .iter() + .filter_map(|c| match &c.shape { + egui::Shape::Text(t) if t.galley.text() == label && outer.intersects(t.visual_bounding_rect()) => Some(t.visual_bounding_rect()), + _ => None, + }) + .collect() + }; + let oks = texts("OK"); + assert_eq!(oks.len(), 1, "{kind} draws {} OK buttons in its window", oks.len()); + let ok = oks[0]; let below = outer.bottom() - ok.bottom(); - assert!(below < 40.0, "{kind}: {below} pt between OK and the bottom of its {} pt window", outer.height()); + assert!((0.0..40.0).contains(&below), "{kind}: {below} pt between OK and the bottom of its {} pt window", outer.height()); + // The nearest thing drawn above the button row: the last field, its label or its list. + let above = shapes + .iter() + .map(|c| c.shape.visual_bounding_rect()) + .filter(|r| r.is_finite() && outer.intersects(*r) && r.bottom() <= ok.top()) + .map(|r| r.bottom()) + .fold(outer.top(), f32::max); + let gap = ok.top() - above; + assert!(gap < 40.0, "{kind}: {gap} pt between OK and what is drawn above it in its {} pt window", outer.height()); + let cancels = texts("Cancel"); + if has_cancel { + assert_eq!(cancels.len(), 1, "{kind} draws {} Cancel buttons in its window", cancels.len()); + let cancel = cancels[0]; + assert!((cancel.center().y - ok.center().y).abs() < 1.0, "{kind}: Cancel at y {} and OK at y {}", cancel.center().y, ok.center().y); + assert!(cancel.right() < ok.left(), "{kind}: Cancel ends at x {} but OK starts at x {}", cancel.right(), ok.left()); + } else { + assert!(cancels.is_empty(), "{kind} draws a Cancel button"); + } } }