Files
Ely-GPUI-Components/src/debug/tests.rs
T
ZacharyZhang-NY 4c3ed1bbb9 Port · Build: Zed's gpui at 1a28cff
gpui and gpui_platform now come from Zed's repo by git at 1a28cff,
the code gpui-pre 0.3.7 republishes, so the gallery can later build
for the browser. gpui takes stacker, as 0.2.2 always did, and
gpui_platform takes font-kit, without which macOS draws no text;
runtime_shaders moves to gpui_platform.

The API moved: focus, blur and Tab steps take cx, Corner is Anchor,
shaped lines paint with an alignment, defer_draw takes a content
mask, the inspector registers a factory, async updates return their
value, and wrapped lines are shared, not cloned. Updates through a
window context go through the window, so a closed window still ends
them as it did.

Where the new gpui behaves differently, Ely keeps its old intent.
Holds and reveals under a resting pointer survive typing through
gpui's input-modality-independent hover; previews the keyboard also
moves keep the default, and the calendar's leave ignores a key press.
Enter reaches a button inside the code editor, since gpui now arms a
key click on the press. The event logger skips a lone modifier. A
video and an image grid keep their shape in a flex column under
taffy 0.13, as a picture does.

AGENTS.md records the new stack and the rules this port changes; the
rest of the old gpui and taffy rules are re-tested in T44c.
2026-09-28 20:30:17 -04:00

141 lines
4.4 KiB
Rust

use std::{cell::RefCell, rc::Rc};
use gpui::{
Context, IntoElement, KeyUpEvent, Keystroke, Modifiers, ParentElement, Render, Styled,
TestAppContext, VisualTestContext, Window, div, point, px,
};
use super::{Breakpoint, BreakpointList, Disassembly, Instruction, Span, TimelineProfiler};
use crate::theme::Theme;
fn settle(cx: &mut VisualTestContext) {
cx.run_until_parked();
cx.update(|window, _| window.refresh());
cx.run_until_parked();
}
/// Two plain instructions; it keeps the gutter presses.
struct Listing(Rc<RefCell<Vec<usize>>>);
impl Render for Listing {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let store = self.0.clone();
let plain = |address| Instruction {
address,
bytes: vec![0x90],
mnemonic: "nop".into(),
operands: "".into(),
comment: None,
source: None,
};
div().w(px(400.0)).h(px(200.0)).child(
Disassembly::new("listing", vec![plain(0x10), plain(0x11)])
.on_breakpoint(move |ix, _, _| store.borrow_mut().push(ix)),
)
}
}
#[gpui::test]
fn an_empty_gutter_takes_a_press_across_its_row(cx: &mut TestAppContext) {
cx.update(Theme::init);
let seen = Rc::new(RefCell::new(Vec::new()));
let store = seen.clone();
let (_, cx) = cx.add_window_view(|_, _| Listing(store));
settle(cx);
cx.simulate_click(point(px(10.0), px(2.0)), Modifiers::none());
settle(cx);
assert_eq!(*seen.borrow(), [0]);
}
/// One breakpoint; it keeps what its toggle and open report.
struct Points {
toggles: Rc<RefCell<Vec<(usize, bool)>>>,
opens: Rc<RefCell<Vec<usize>>>,
}
impl Render for Points {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let (toggles, opens) = (self.toggles.clone(), self.opens.clone());
let point = Breakpoint {
path: "src/lift.rs".into(),
line: 3,
enabled: true,
condition: None,
hits: 0,
};
div().w(px(400.0)).child(
BreakpointList::new("points", [point])
.on_toggle(move |ix, on, _, _| toggles.borrow_mut().push((ix, on)))
.on_open(move |ix, _, _| opens.borrow_mut().push(ix)),
)
}
}
#[gpui::test]
fn a_breakpoints_box_toggles_without_opening_it(cx: &mut TestAppContext) {
cx.update(Theme::init);
let (toggles, opens) = (
Rc::new(RefCell::new(Vec::new())),
Rc::new(RefCell::new(Vec::new())),
);
let view = Points {
toggles: toggles.clone(),
opens: opens.clone(),
};
let (_, cx) = cx.add_window_view(|_, _| view);
settle(cx);
cx.simulate_click(point(px(14.0), px(12.0)), Modifiers::none());
settle(cx);
assert_eq!(*toggles.borrow(), [(0, false)]);
assert!(
opens.borrow().is_empty(),
"the box press stays with the box"
);
cx.simulate_click(point(px(200.0), px(12.0)), Modifiers::none());
settle(cx);
assert_eq!(*opens.borrow(), [0], "the row still opens");
}
/// Two spans on one track; it keeps the spans picked.
struct Spans(Rc<RefCell<Vec<usize>>>);
impl Render for Spans {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let store = self.0.clone();
let span = |name: &str, start, end| Span {
track: 0,
name: name.to_string().into(),
start,
end,
};
let spans = vec![span("a", 0.0, 4.0), span("b", 5.0, 9.0)];
div().w(px(400.0)).child(
TimelineProfiler::new("spans", ["Main"], spans, (0.0, 10.0))
.on_select(move |ix, _, _| store.borrow_mut().push(ix)),
)
}
}
#[gpui::test]
fn tab_reaches_each_span_and_enter_picks_it(cx: &mut TestAppContext) {
cx.update(Theme::init);
let picked = Rc::new(RefCell::new(Vec::new()));
let store = picked.clone();
let (_, cx) = cx.add_window_view(|_, _| Spans(store));
cx.update(|window, _| window.activate_window());
settle(cx);
cx.update(|window, cx| window.focus_next(cx));
cx.update(|window, cx| window.focus_next(cx));
cx.simulate_keystrokes("enter");
settle(cx);
cx.simulate_event(KeyUpEvent {
keystroke: Keystroke::parse("enter").expect("a key"),
});
settle(cx);
assert_eq!(
*picked.borrow(),
[1],
"the second Tab stands on the second span"
);
}