use editor::Editor;
use gpui::{
Context, Entity, Focusable, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent,
MouseUpEvent, Pixels, Point, Render, TestAppContext, VisualTestContext, Window, div, point,
prelude::*, px, size,
};
const PADDING: f32 = 60.0;
struct Page {
editor: Entity<Editor>,
}
impl Render for Page {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let editor = self.editor.clone();
div()
.size_full()
.p(px(PADDING))
.on_mouse_down(MouseButton::Left, move |event, window, cx| {
editor.update(cx, |editor, cx| {
editor.press(
event.position,
event.click_count,
event.modifiers,
window,
cx,
)
});
})
.child(self.editor.clone())
}
}
fn open(source: &str, cx: &mut TestAppContext) -> (Entity<Editor>, VisualTestContext) {
cx.update(|cx| {
theme::Theme::install(theme::Appearance::Dark, cx);
editor::init(cx);
});
let window = cx.add_window(|_, cx| Page {
editor: cx.new(|cx| Editor::new(source, cx)),
});
let page = window.root(cx).unwrap();
let editor = cx.update(|cx| page.read(cx).editor.clone());
let mut visual = VisualTestContext::from_window(window.into(), cx);
visual.simulate_resize(size(px(400.0), px(600.0)));
visual.update(|window, cx| {
let handle = editor.read(cx).focus_handle(cx);
window.focus(&handle, cx);
});
visual.run_until_parked();
(editor, visual)
}
fn down(cx: &mut VisualTestContext, at: Point<Pixels>) {
cx.simulate_event(MouseDownEvent {
position: at,
button: MouseButton::Left,
modifiers: Modifiers::default(),
click_count: 1,
first_mouse: false,
});
}
fn drag(cx: &mut VisualTestContext, to: Point<Pixels>) {
cx.simulate_event(MouseMoveEvent {
position: to,
pressed_button: Some(MouseButton::Left),
modifiers: Modifiers::default(),
});
}
fn up(cx: &mut VisualTestContext, at: Point<Pixels>) {
cx.simulate_event(MouseUpEvent {
position: at,
button: MouseButton::Left,
modifiers: Modifiers::default(),
click_count: 1,
});
}
fn in_block(editor: &Entity<Editor>, cx: &mut VisualTestContext, ix: usize) -> Point<Pixels> {
let bounds = cx
.update(|_, cx| editor.read(cx).layouts().block_bounds(ix))
.expect("the block painted");
point(bounds.origin.x + px(4.0), bounds.origin.y + px(4.0))
}
#[gpui::test]
fn a_selection_keeps_extending_past_the_editors_edge(cx: &mut TestAppContext) {
let (editor, mut cx) = open("first\n\nsecond\n\nthird", cx);
let start = in_block(&editor, &mut cx, 0);
down(&mut cx, start);
let outside = point(px(PADDING / 2.0), px(580.0));
drag(&mut cx, outside);
up(&mut cx, outside);
let selection = cx.update(|_, cx| editor.read(cx).selection());
assert_eq!(selection.head.block, 2, "the drag reached the last block");
}
#[gpui::test]
fn a_press_on_the_page_places_a_caret_and_drags(cx: &mut TestAppContext) {
let (editor, mut cx) = open("first\n\nsecond\n\nthird", cx);
let target = in_block(&editor, &mut cx, 1);
let beside = point(px(PADDING / 2.0), target.y);
down(&mut cx, beside);
let selection = cx.update(|_, cx| editor.read(cx).selection());
assert!(selection.is_collapsed());
assert_eq!(
selection.head.block, 1,
"the caret went to the row beside it"
);
let end = in_block(&editor, &mut cx, 2);
drag(&mut cx, end);
up(&mut cx, end);
let selection = cx.update(|_, cx| editor.read(cx).selection());
assert_eq!(
(selection.anchor.block, selection.head.block),
(1, 2),
"and a drag from there selects"
);
}
#[gpui::test]
fn a_press_on_the_editor_is_not_taken_twice(cx: &mut TestAppContext) {
let (editor, mut cx) = open("- [ ] open", cx);
let box_ = cx
.update(|_, cx| editor.read(cx).layouts().checkbox_bounds(0))
.expect("the checkbox painted");
cx.simulate_click(box_.center(), Modifiers::default());
let source = cx.update(|_, cx| editor.read(cx).source());
assert_eq!(source, "- [x] open", "one toggle, not two");
}