use gpui::{ AppContext as _, IntoElement, ParentElement as _, Render, Styled as _, TestAppContext, VisualTestContext, Window, div, }; use gpui_native_core::button::{Button, ButtonVariant}; use gpui_native_core::field::{Field, FieldVariant}; use gpui_native_theme::Theme; struct FieldHost { variant: FieldVariant, with_error: bool, } impl Render for FieldHost { fn render(&mut self, _window: &mut Window, _cx: &mut gpui::Context) -> impl IntoElement { let mut field = Field::new("test-field", "Server URL") .description("Where patches are sent.") .variant(self.variant) .child( Button::new("test-field-button") .label("Edit") .variant(ButtonVariant::Ghost), ); if self.with_error { field = field.error(Some("Required")); } div().size_full().p_4().child(field) } } fn field_window( variant: FieldVariant, with_error: bool, ) -> (TestAppContext, gpui::AnyWindowHandle) { let mut cx = TestAppContext::single(); cx.update(Theme::init); let window = cx.add_window(move |_, _| FieldHost { variant, with_error, }); let window: gpui::AnyWindowHandle = window.into(); cx.update_window(window, |_, window, cx| { window.draw(cx).clear(cx); }) .unwrap(); (cx, window) } #[test] fn block_stacks_the_label_above_the_control() { let (cx, window) = field_window(FieldVariant::Block, false); let mut visual = VisualTestContext::from_window(window, &cx); let label = visual .debug_bounds("test-field-label") .expect("label missing"); let control = visual .debug_bounds("test-field-control") .expect("control missing"); assert!( label.bottom() <= control.top(), "label must sit above the control: {label:?} vs {control:?}" ); assert!( (label.left() - control.left()).abs() < gpui::px(1.), "label and control must share the left edge" ); } #[test] fn row_leads_with_the_label_and_trails_the_control() { let (cx, window) = field_window(FieldVariant::Row, false); let mut visual = VisualTestContext::from_window(window, &cx); let label = visual .debug_bounds("test-field-label") .expect("label missing"); let control = visual .debug_bounds("test-field-control") .expect("control missing"); assert!( control.left() >= label.right(), "the control must trail the label: {label:?} vs {control:?}" ); let label_center = (label.top() + label.bottom()) / 2.; let control_center = (control.top() + control.bottom()) / 2.; assert!( (label_center - control_center).abs() < gpui::px(1.5), "the control must center on the title line: {label:?} vs {control:?}" ); } #[test] fn the_error_renders_under_the_control_only_when_set() { let (cx, window) = field_window(FieldVariant::Block, false); let mut visual = VisualTestContext::from_window(window, &cx); assert!( visual.debug_bounds("test-field-error").is_none(), "no error must render when none is set" ); let (cx, window) = field_window(FieldVariant::Block, true); let mut visual = VisualTestContext::from_window(window, &cx); let error = visual .debug_bounds("test-field-error") .expect("error missing"); let control = visual .debug_bounds("test-field-control") .expect("control missing"); assert!( error.top() >= control.bottom(), "the error must sit under the control: {control:?} vs {error:?}" ); }