use std::{cell::RefCell, rc::Rc}; use gpui::{ Context, IntoElement, MouseButton, ParentElement as _, Render, Styled as _, TestAppContext, VisualTestContext, Window, div, point, px, }; use gpui_native_core::select::Select; use gpui_native_theme::Theme; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Level { Low, Mid, High, } const LEVELS: [(Level, &str); 3] = [ (Level::Low, "Low"), (Level::Mid, "Mid"), (Level::High, "High"), ]; type Changes = Rc>>>; struct Harness { value: Option, changes: Changes, } impl Render for Harness { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { let changes = self.changes.clone(); let view = cx.entity(); div().size_full().p_4().child( Select::new("level") .options(LEVELS) .selected(self.value) .on_change(move |next, _window, cx| { changes.borrow_mut().push(next); view.update(cx, |harness, cx| { harness.value = next; cx.notify(); }); }), ) } } fn level_window() -> (TestAppContext, VisualTestContext, Changes) { let mut cx = TestAppContext::single(); cx.update(Theme::init); let changes = Rc::new(RefCell::new(Vec::new())); let harness_changes = changes.clone(); let window = cx.add_window(move |_, _| Harness { value: None, changes: harness_changes, }); let mut visual = VisualTestContext::from_window(window.into(), &cx); visual.update(|window, cx| { window.draw(cx).clear(cx); }); (cx, visual, changes) } fn click(visual: &mut VisualTestContext, position: gpui::Point) { visual.simulate_mouse_down(position, MouseButton::Left, gpui::Modifiers::default()); visual.simulate_mouse_up(position, MouseButton::Left, gpui::Modifiers::default()); } /// The trigger band is `16..46`; the panel hangs 4 px below it with a 4 px /// inner padding, so the three rows ride `~58..90`, `~90..122`, `~122..154`. /// Every option must answer a pointer press — a popup that clips its last /// item never does. #[test] fn every_option_row_answers_the_pointer() { let (_cx, mut visual, changes) = level_window(); let expected = [ (px(74.), Level::Low), (px(106.), Level::Mid), (px(138.), Level::High), ]; for (y, value) in expected { click(&mut visual, point(px(100.), px(31.))); visual.update(|window, cx| { window.draw(cx).clear(cx); }); click(&mut visual, point(px(100.), y)); visual.update(|window, cx| { window.draw(cx).clear(cx); }); assert_eq!( changes.borrow().last(), Some(&Some(value)), "pressing {value:?}'s row must choose it" ); } }