Add simulate_window_resize.

Fixes up tests for movement in editor/scrolling.

Co-authored-by: Antonio <antonio@zed.dev>
This commit is contained in:
Piotr Osiewicz 2023-12-04 17:27:48 +01:00
parent 68d309e79c
commit b5924d6b11
8 changed files with 399 additions and 334 deletions

View file

@ -8243,6 +8243,11 @@ impl Editor {
self.style = Some(style); self.style = Some(style);
} }
#[cfg(any(test, feature = "test-support"))]
pub fn style(&self) -> Option<&EditorStyle> {
self.style.as_ref()
}
pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool { pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
self.display_map self.display_map
.update(cx, |map, cx| map.set_wrap_width(width, cx)) .update(cx, |map, cx| map.set_wrap_width(width, cx))

View file

@ -1283,357 +1283,376 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
} }
//todo!(simulate_resize) //todo!(simulate_resize)
// #[gpui::test] #[gpui::test]
// async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) { async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) {
// init_test(cx, |_| {}); init_test(cx, |_| {});
// let mut cx = EditorTestContext::new(cx).await; let mut cx = EditorTestContext::new(cx).await;
// let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); let line_height = cx.editor(|editor, cx| {
// let window = cx.window; editor
// window.simulate_resize(gpui::Point::new(100., 4. * line_height), &mut cx); .style()
.unwrap()
.text
.line_height_in_pixels(cx.rem_size())
});
cx.simulate_window_resize(cx.window, size(px(100.), 4. * line_height));
// cx.set_state( cx.set_state(
// &r#"ˇone &r#"ˇone
// two two
// three three
// fourˇ fourˇ
// five five
// six"# six"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"one &r#"one
// two two
// ˇ ˇ
// three three
// four four
// five five
// ˇ ˇ
// six"# six"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"one &r#"one
// two two
// three three
// four four
// five five
// ˇ ˇ
// sixˇ"# sixˇ"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"one &r#"one
// two two
// three three
// four four
// five five
// sixˇ"# sixˇ"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"one &r#"one
// two two
// three three
// four four
// five five
// ˇ ˇ
// six"# six"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"one &r#"one
// two two
// ˇ ˇ
// three three
// four four
// five five
// six"# six"#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#"ˇone &r#"ˇone
// two two
// three three
// four four
// five five
// six"# six"#
// .unindent(), .unindent(),
// ); );
// } }
// #[gpui::test] #[gpui::test]
// async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) { async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) {
// init_test(cx, |_| {}); init_test(cx, |_| {});
// let mut cx = EditorTestContext::new(cx).await; let mut cx = EditorTestContext::new(cx).await;
// let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); let line_height = cx.editor(|editor, cx| {
// let window = cx.window; editor
// window.simulate_resize(Point::new(1000., 4. * line_height + 0.5), &mut cx); .style()
.unwrap()
.text
.line_height_in_pixels(cx.rem_size())
});
let window = cx.window;
cx.simulate_window_resize(window, size(px(1000.), 4. * line_height + px(0.5)));
// cx.set_state( cx.set_state(
// &r#"ˇone &r#"ˇone
// two two
// three three
// four four
// five five
// six six
// seven seven
// eight eight
// nine nine
// ten ten
// "#, "#,
// ); );
// cx.update_editor(|editor, cx| { cx.update_editor(|editor, cx| {
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 0.) gpui::Point::new(0., 0.)
// ); );
// editor.scroll_screen(&ScrollAmount::Page(1.), cx); editor.scroll_screen(&ScrollAmount::Page(1.), cx);
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 3.) gpui::Point::new(0., 3.)
// ); );
// editor.scroll_screen(&ScrollAmount::Page(1.), cx); editor.scroll_screen(&ScrollAmount::Page(1.), cx);
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 6.) gpui::Point::new(0., 6.)
// ); );
// editor.scroll_screen(&ScrollAmount::Page(-1.), cx); editor.scroll_screen(&ScrollAmount::Page(-1.), cx);
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 3.) gpui::Point::new(0., 3.)
// ); );
// editor.scroll_screen(&ScrollAmount::Page(-0.5), cx); editor.scroll_screen(&ScrollAmount::Page(-0.5), cx);
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 1.) gpui::Point::new(0., 1.)
// ); );
// editor.scroll_screen(&ScrollAmount::Page(0.5), cx); editor.scroll_screen(&ScrollAmount::Page(0.5), cx);
// assert_eq!( assert_eq!(
// editor.snapshot(cx).scroll_position(), editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 3.) gpui::Point::new(0., 3.)
// ); );
// }); });
// } }
// #[gpui::test] #[gpui::test]
// async fn test_autoscroll(cx: &mut gpui::TestAppContext) { async fn test_autoscroll(cx: &mut gpui::TestAppContext) {
// init_test(cx, |_| {}); init_test(cx, |_| {});
// let mut cx = EditorTestContext::new(cx).await; let mut cx = EditorTestContext::new(cx).await;
// let line_height = cx.update_editor(|editor, cx| { let line_height = cx.update_editor(|editor, cx| {
// editor.set_vertical_scroll_margin(2, cx); editor.set_vertical_scroll_margin(2, cx);
// editor.style(cx).text.line_height(cx.font_cache()) editor
// }); .style()
.unwrap()
.text
.line_height_in_pixels(cx.rem_size())
});
let window = cx.window;
cx.simulate_window_resize(window, size(px(1000.), 6. * line_height));
// let window = cx.window; cx.set_state(
// window.simulate_resize(gpui::Point::new(1000., 6.0 * line_height), &mut cx); &r#"ˇone
two
three
four
five
six
seven
eight
nine
ten
"#,
);
cx.update_editor(|editor, cx| {
assert_eq!(
editor.snapshot(cx).scroll_position(),
gpui::Point::new(0., 0.0)
);
});
// cx.set_state( // Add a cursor below the visible area. Since both cursors cannot fit
// &r#"ˇone // on screen, the editor autoscrolls to reveal the newest cursor, and
// two // allows the vertical scroll margin below that cursor.
// three cx.update_editor(|editor, cx| {
// four editor.change_selections(Some(Autoscroll::fit()), cx, |selections| {
// five selections.select_ranges([
// six Point::new(0, 0)..Point::new(0, 0),
// seven Point::new(6, 0)..Point::new(6, 0),
// eight ]);
// nine })
// ten });
// "#, cx.update_editor(|editor, cx| {
// ); assert_eq!(
// cx.update_editor(|editor, cx| { editor.snapshot(cx).scroll_position(),
// assert_eq!( gpui::Point::new(0., 3.0)
// editor.snapshot(cx).scroll_position(), );
// gpui::Point::new(0., 0.0) });
// );
// });
// // Add a cursor below the visible area. Since both cursors cannot fit // Move down. The editor cursor scrolls down to track the newest cursor.
// // on screen, the editor autoscrolls to reveal the newest cursor, and cx.update_editor(|editor, cx| {
// // allows the vertical scroll margin below that cursor. editor.move_down(&Default::default(), cx);
// cx.update_editor(|editor, cx| { });
// editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { cx.update_editor(|editor, cx| {
// selections.select_ranges([ assert_eq!(
// Point::new(0, 0)..Point::new(0, 0), editor.snapshot(cx).scroll_position(),
// Point::new(6, 0)..Point::new(6, 0), gpui::Point::new(0., 4.0)
// ]); );
// }) });
// });
// cx.update_editor(|editor, cx| {
// assert_eq!(
// editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 3.0)
// );
// });
// // Move down. The editor cursor scrolls down to track the newest cursor. // Add a cursor above the visible area. Since both cursors fit on screen,
// cx.update_editor(|editor, cx| { // the editor scrolls to show both.
// editor.move_down(&Default::default(), cx); cx.update_editor(|editor, cx| {
// }); editor.change_selections(Some(Autoscroll::fit()), cx, |selections| {
// cx.update_editor(|editor, cx| { selections.select_ranges([
// assert_eq!( Point::new(1, 0)..Point::new(1, 0),
// editor.snapshot(cx).scroll_position(), Point::new(6, 0)..Point::new(6, 0),
// gpui::Point::new(0., 4.0) ]);
// ); })
// }); });
cx.update_editor(|editor, cx| {
assert_eq!(
editor.snapshot(cx).scroll_position(),
gpui::Point::new(0., 1.0)
);
});
}
// // Add a cursor above the visible area. Since both cursors fit on screen, #[gpui::test]
// // the editor scrolls to show both. async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) {
// cx.update_editor(|editor, cx| { init_test(cx, |_| {});
// editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { let mut cx = EditorTestContext::new(cx).await;
// selections.select_ranges([
// Point::new(1, 0)..Point::new(1, 0),
// Point::new(6, 0)..Point::new(6, 0),
// ]);
// })
// });
// cx.update_editor(|editor, cx| {
// assert_eq!(
// editor.snapshot(cx).scroll_position(),
// gpui::Point::new(0., 1.0)
// );
// });
// }
// #[gpui::test] let line_height = cx.editor(|editor, cx| {
// async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) { editor
// init_test(cx, |_| {}); .style()
// let mut cx = EditorTestContext::new(cx).await; .unwrap()
.text
.line_height_in_pixels(cx.rem_size())
});
let window = cx.window;
cx.simulate_window_resize(window, size(px(100.), 4. * line_height));
cx.set_state(
&r#"
ˇone
two
threeˇ
four
five
six
seven
eight
nine
ten
"#
.unindent(),
);
// let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx));
// let window = cx.window; cx.assert_editor_state(
// window.simulate_resize(gpui::Point::new(100., 4. * line_height), &mut cx); &r#"
one
two
three
ˇfour
five
sixˇ
seven
eight
nine
ten
"#
.unindent(),
);
// cx.set_state( cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx));
// &r#" cx.assert_editor_state(
// ˇone &r#"
// two one
// threeˇ two
// four three
// five four
// six five
// seven six
// eight ˇseven
// nine eight
// ten nineˇ
// "# ten
// .unindent(), "#
// ); .unindent(),
);
// cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#" &r#"
// one one
// two two
// three three
// ˇfour ˇfour
// five five
// sixˇ sixˇ
// seven seven
// eight eight
// nine nine
// ten ten
// "# "#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx));
// cx.assert_editor_state( cx.assert_editor_state(
// &r#" &r#"
// one ˇone
// two two
// three threeˇ
// four four
// five five
// six six
// ˇseven seven
// eight eight
// nineˇ nine
// ten ten
// "# "#
// .unindent(), .unindent(),
// ); );
// cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); // Test select collapsing
// cx.assert_editor_state( cx.update_editor(|editor, cx| {
// &r#" editor.move_page_down(&MovePageDown::default(), cx);
// one editor.move_page_down(&MovePageDown::default(), cx);
// two editor.move_page_down(&MovePageDown::default(), cx);
// three });
// ˇfour cx.assert_editor_state(
// five &r#"
// sixˇ one
// seven two
// eight three
// nine four
// ten five
// "# six
// .unindent(), seven
// ); eight
nine
// cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); ˇten
// cx.assert_editor_state( ˇ"#
// &r#" .unindent(),
// ˇone );
// two }
// threeˇ
// four
// five
// six
// seven
// eight
// nine
// ten
// "#
// .unindent(),
// );
// // Test select collapsing
// cx.update_editor(|editor, cx| {
// editor.move_page_down(&MovePageDown::default(), cx);
// editor.move_page_down(&MovePageDown::default(), cx);
// editor.move_page_down(&MovePageDown::default(), cx);
// });
// cx.assert_editor_state(
// &r#"
// one
// two
// three
// four
// five
// six
// seven
// eight
// nine
// ˇten
// ˇ"#
// .unindent(),
// );
// }
#[gpui::test] #[gpui::test]
async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) { async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {

View file

@ -88,7 +88,7 @@ pub fn diff_hunk_to_display(hunk: DiffHunk<u32>, snapshot: &DisplaySnapshot) ->
} }
} }
#[cfg(any(test, feature = "test_support"))] #[cfg(any(test, feature = "test-support"))]
mod tests { mod tests {
use crate::editor_tests::init_test; use crate::editor_tests::init_test;
use crate::Point; use crate::Point;

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
BackgroundExecutor, Context, Div, Entity, EventEmitter, ForegroundExecutor, InputEvent, BackgroundExecutor, Bounds, Context, Div, Entity, EventEmitter, ForegroundExecutor, InputEvent,
KeyDownEvent, Keystroke, Model, ModelContext, Render, Result, Task, TestDispatcher, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, PlatformWindow, Point, Render, Result,
TestPlatform, TestWindow, TestWindowHandlers, View, ViewContext, VisualContext, WindowContext, Size, Task, TestDispatcher, TestPlatform, TestWindow, TestWindowHandlers, View, ViewContext,
WindowHandle, WindowOptions, VisualContext, WindowBounds, WindowContext, WindowHandle, WindowOptions,
}; };
use anyhow::{anyhow, bail}; use anyhow::{anyhow, bail};
use futures::{Stream, StreamExt}; use futures::{Stream, StreamExt};
use std::{future::Future, ops::Deref, rc::Rc, sync::Arc, time::Duration}; use std::{future::Future, mem, ops::Deref, rc::Rc, sync::Arc, time::Duration};
#[derive(Clone)] #[derive(Clone)]
pub struct TestAppContext { pub struct TestAppContext {
@ -170,6 +170,45 @@ impl TestAppContext {
self.test_platform.has_pending_prompt() self.test_platform.has_pending_prompt()
} }
pub fn simulate_window_resize(&self, window_handle: AnyWindowHandle, size: Size<Pixels>) {
let (mut handlers, scale_factor) = self
.app
.borrow_mut()
.update_window(window_handle, |_, cx| {
let platform_window = cx.window.platform_window.as_test().unwrap();
let scale_factor = platform_window.scale_factor();
match &mut platform_window.bounds {
WindowBounds::Fullscreen | WindowBounds::Maximized => {
platform_window.bounds = WindowBounds::Fixed(Bounds {
origin: Point::default(),
size: size.map(|pixels| f64::from(pixels).into()),
});
}
WindowBounds::Fixed(bounds) => {
bounds.size = size.map(|pixels| f64::from(pixels).into());
}
}
(
mem::take(&mut platform_window.handlers.lock().resize),
scale_factor,
)
})
.unwrap();
for handler in &mut handlers {
handler(size, scale_factor);
}
self.app
.borrow_mut()
.update_window(window_handle, |_, cx| {
let platform_window = cx.window.platform_window.as_test().unwrap();
platform_window.handlers.lock().resize = handlers;
})
.unwrap();
}
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R> pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
where where
Fut: Future<Output = R> + 'static, Fut: Future<Output = R> + 'static,

View file

@ -206,13 +206,14 @@ impl BackgroundExecutor {
return Err(future); return Err(future);
} }
let max_ticks = if cfg!(any(test, feature = "test-support")) { #[cfg(any(test, feature = "test-support"))]
self.dispatcher let max_ticks = self
.dispatcher
.as_test() .as_test()
.map_or(usize::MAX, |dispatcher| dispatcher.gen_block_on_ticks()) .map_or(usize::MAX, |dispatcher| dispatcher.gen_block_on_ticks());
} else { #[cfg(not(any(test, feature = "test-support")))]
usize::MAX let max_ticks = usize::MAX;
};
let mut timer = self.timer(duration).fuse(); let mut timer = self.timer(duration).fuse();
let timeout = async { let timeout = async {

View file

@ -160,7 +160,7 @@ pub trait PlatformWindow {
fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas>; fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas>;
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
fn as_test(&self) -> Option<&TestWindow> { fn as_test(&mut self) -> Option<&mut TestWindow> {
None None
} }
} }

View file

@ -19,7 +19,7 @@ pub(crate) struct TestWindowHandlers {
} }
pub struct TestWindow { pub struct TestWindow {
bounds: WindowBounds, pub(crate) bounds: WindowBounds,
current_scene: Mutex<Option<Scene>>, current_scene: Mutex<Option<Scene>>,
display: Rc<dyn PlatformDisplay>, display: Rc<dyn PlatformDisplay>,
pub(crate) window_title: Option<String>, pub(crate) window_title: Option<String>,
@ -170,7 +170,7 @@ impl PlatformWindow for TestWindow {
self.sprite_atlas.clone() self.sprite_atlas.clone()
} }
fn as_test(&self) -> Option<&TestWindow> { fn as_test(&mut self) -> Option<&mut TestWindow> {
Some(self) Some(self)
} }
} }

View file

@ -208,8 +208,9 @@ impl TextStyle {
} }
} }
/// Returns the rounded line height in pixels.
pub fn line_height_in_pixels(&self, rem_size: Pixels) -> Pixels { pub fn line_height_in_pixels(&self, rem_size: Pixels) -> Pixels {
self.line_height.to_pixels(self.font_size, rem_size) self.line_height.to_pixels(self.font_size, rem_size).round()
} }
pub fn to_run(&self, len: usize) -> TextRun { pub fn to_run(&self, len: usize) -> TextRun {