diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 87fa9875d4..c180d49ef2 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -8243,6 +8243,11 @@ impl Editor { 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, cx: &mut AppContext) -> bool { self.display_map .update(cx, |map, cx| map.set_wrap_width(width, cx)) diff --git a/crates/editor2/src/editor_tests.rs b/crates/editor2/src/editor_tests.rs index 4925e7c965..7b989a4a2c 100644 --- a/crates/editor2/src/editor_tests.rs +++ b/crates/editor2/src/editor_tests.rs @@ -1283,357 +1283,376 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) { } //todo!(simulate_resize) -// #[gpui::test] -// async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let mut cx = EditorTestContext::new(cx).await; +#[gpui::test] +async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; -// let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); -// let window = cx.window; -// window.simulate_resize(gpui::Point::new(100., 4. * line_height), &mut cx); + let line_height = cx.editor(|editor, cx| { + editor + .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( -// &r#"ˇone -// two + cx.set_state( + &r#"ˇone + two -// three -// fourˇ -// five + three + fourˇ + five -// six"# -// .unindent(), -// ); + six"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"one -// two -// ˇ -// three -// four -// five -// ˇ -// six"# -// .unindent(), -// ); + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + ˇ + three + four + five + ˇ + six"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"one -// two + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two -// three -// four -// five -// ˇ -// sixˇ"# -// .unindent(), -// ); + three + four + five + ˇ + sixˇ"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"one -// two + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two -// three -// four -// five + three + four + five -// sixˇ"# -// .unindent(), -// ); + sixˇ"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"one -// two + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two -// three -// four -// five -// ˇ -// six"# -// .unindent(), -// ); + three + four + five + ˇ + six"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"one -// two -// ˇ -// three -// four -// five + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + ˇ + three + four + five -// six"# -// .unindent(), -// ); + six"# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); -// cx.assert_editor_state( -// &r#"ˇone -// two + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"ˇone + two -// three -// four -// five + three + four + five -// six"# -// .unindent(), -// ); -// } + six"# + .unindent(), + ); +} -// #[gpui::test] -// async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let mut cx = EditorTestContext::new(cx).await; -// let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); -// let window = cx.window; -// window.simulate_resize(Point::new(1000., 4. * line_height + 0.5), &mut cx); +#[gpui::test] +async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; + let line_height = cx.editor(|editor, cx| { + editor + .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( -// &r#"ˇone -// two -// three -// four -// five -// six -// seven -// eight -// nine -// ten -// "#, -// ); + cx.set_state( + &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.) -// ); -// editor.scroll_screen(&ScrollAmount::Page(1.), cx); -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 3.) -// ); -// editor.scroll_screen(&ScrollAmount::Page(1.), cx); -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 6.) -// ); -// editor.scroll_screen(&ScrollAmount::Page(-1.), cx); -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 3.) -// ); + cx.update_editor(|editor, cx| { + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 0.) + ); + editor.scroll_screen(&ScrollAmount::Page(1.), cx); + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 3.) + ); + editor.scroll_screen(&ScrollAmount::Page(1.), cx); + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 6.) + ); + editor.scroll_screen(&ScrollAmount::Page(-1.), cx); + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 3.) + ); -// editor.scroll_screen(&ScrollAmount::Page(-0.5), cx); -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 1.) -// ); -// editor.scroll_screen(&ScrollAmount::Page(0.5), cx); -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 3.) -// ); -// }); -// } + editor.scroll_screen(&ScrollAmount::Page(-0.5), cx); + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 1.) + ); + editor.scroll_screen(&ScrollAmount::Page(0.5), cx); + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 3.) + ); + }); +} -// #[gpui::test] -// async fn test_autoscroll(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let mut cx = EditorTestContext::new(cx).await; +#[gpui::test] +async fn test_autoscroll(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; -// let line_height = cx.update_editor(|editor, cx| { -// editor.set_vertical_scroll_margin(2, cx); -// editor.style(cx).text.line_height(cx.font_cache()) -// }); + let line_height = cx.update_editor(|editor, cx| { + editor.set_vertical_scroll_margin(2, cx); + 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; -// window.simulate_resize(gpui::Point::new(1000., 6.0 * line_height), &mut cx); + cx.set_state( + &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( -// &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) -// ); -// }); + // Add a cursor below the visible area. Since both cursors cannot fit + // on screen, the editor autoscrolls to reveal the newest cursor, and + // allows the vertical scroll margin below that cursor. + cx.update_editor(|editor, cx| { + editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { + selections.select_ranges([ + Point::new(0, 0)..Point::new(0, 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., 3.0) + ); + }); -// // Add a cursor below the visible area. Since both cursors cannot fit -// // on screen, the editor autoscrolls to reveal the newest cursor, and -// // allows the vertical scroll margin below that cursor. -// cx.update_editor(|editor, cx| { -// editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { -// selections.select_ranges([ -// Point::new(0, 0)..Point::new(0, 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., 3.0) -// ); -// }); + // Move down. The editor cursor scrolls down to track the newest cursor. + cx.update_editor(|editor, cx| { + editor.move_down(&Default::default(), cx); + }); + cx.update_editor(|editor, cx| { + assert_eq!( + editor.snapshot(cx).scroll_position(), + gpui::Point::new(0., 4.0) + ); + }); -// // Move down. The editor cursor scrolls down to track the newest cursor. -// cx.update_editor(|editor, cx| { -// editor.move_down(&Default::default(), cx); -// }); -// cx.update_editor(|editor, cx| { -// assert_eq!( -// editor.snapshot(cx).scroll_position(), -// gpui::Point::new(0., 4.0) -// ); -// }); + // Add a cursor above the visible area. Since both cursors fit on screen, + // the editor scrolls to show both. + cx.update_editor(|editor, cx| { + editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { + 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) + ); + }); +} -// // Add a cursor above the visible area. Since both cursors fit on screen, -// // the editor scrolls to show both. -// cx.update_editor(|editor, cx| { -// editor.change_selections(Some(Autoscroll::fit()), cx, |selections| { -// 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] +async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; -// #[gpui::test] -// async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let mut cx = EditorTestContext::new(cx).await; + let line_height = cx.editor(|editor, cx| { + editor + .style() + .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())); -// let window = cx.window; -// window.simulate_resize(gpui::Point::new(100., 4. * line_height), &mut cx); + cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); + cx.assert_editor_state( + &r#" + one + two + three + ˇfour + five + sixˇ + seven + eight + nine + ten + "# + .unindent(), + ); -// cx.set_state( -// &r#" -// ˇone -// two -// threeˇ -// four -// five -// six -// seven -// eight -// nine -// ten -// "# -// .unindent(), -// ); + cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); + cx.assert_editor_state( + &r#" + one + two + three + four + five + six + ˇseven + eight + nineˇ + ten + "# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); -// cx.assert_editor_state( -// &r#" -// one -// two -// three -// ˇfour -// five -// sixˇ -// seven -// eight -// nine -// ten -// "# -// .unindent(), -// ); + cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); + cx.assert_editor_state( + &r#" + one + two + three + ˇfour + five + sixˇ + seven + eight + nine + ten + "# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx)); -// cx.assert_editor_state( -// &r#" -// one -// two -// three -// four -// five -// six -// ˇseven -// eight -// nineˇ -// ten -// "# -// .unindent(), -// ); + cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); + cx.assert_editor_state( + &r#" + ˇone + two + threeˇ + four + five + six + seven + eight + nine + ten + "# + .unindent(), + ); -// cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); -// cx.assert_editor_state( -// &r#" -// one -// two -// three -// ˇfour -// five -// sixˇ -// seven -// eight -// nine -// ten -// "# -// .unindent(), -// ); - -// cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx)); -// cx.assert_editor_state( -// &r#" -// ˇ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(), -// ); -// } + // 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] async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) { diff --git a/crates/editor2/src/git.rs b/crates/editor2/src/git.rs index 9190eed05a..0e7501c169 100644 --- a/crates/editor2/src/git.rs +++ b/crates/editor2/src/git.rs @@ -88,7 +88,7 @@ pub fn diff_hunk_to_display(hunk: DiffHunk, snapshot: &DisplaySnapshot) -> } } -#[cfg(any(test, feature = "test_support"))] +#[cfg(any(test, feature = "test-support"))] mod tests { use crate::editor_tests::init_test; use crate::Point; diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 908a418635..a9403de9bc 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -1,13 +1,13 @@ use crate::{ div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, - BackgroundExecutor, Context, Div, Entity, EventEmitter, ForegroundExecutor, InputEvent, - KeyDownEvent, Keystroke, Model, ModelContext, Render, Result, Task, TestDispatcher, - TestPlatform, TestWindow, TestWindowHandlers, View, ViewContext, VisualContext, WindowContext, - WindowHandle, WindowOptions, + BackgroundExecutor, Bounds, Context, Div, Entity, EventEmitter, ForegroundExecutor, InputEvent, + KeyDownEvent, Keystroke, Model, ModelContext, Pixels, PlatformWindow, Point, Render, Result, + Size, Task, TestDispatcher, TestPlatform, TestWindow, TestWindowHandlers, View, ViewContext, + VisualContext, WindowBounds, WindowContext, WindowHandle, WindowOptions, }; use anyhow::{anyhow, bail}; 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)] pub struct TestAppContext { @@ -170,6 +170,45 @@ impl TestAppContext { self.test_platform.has_pending_prompt() } + pub fn simulate_window_resize(&self, window_handle: AnyWindowHandle, size: Size) { + 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(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task where Fut: Future + 'static, diff --git a/crates/gpui2/src/executor.rs b/crates/gpui2/src/executor.rs index e446a0cb1e..e01846c404 100644 --- a/crates/gpui2/src/executor.rs +++ b/crates/gpui2/src/executor.rs @@ -206,13 +206,14 @@ impl BackgroundExecutor { return Err(future); } - let max_ticks = if cfg!(any(test, feature = "test-support")) { - self.dispatcher - .as_test() - .map_or(usize::MAX, |dispatcher| dispatcher.gen_block_on_ticks()) - } else { - usize::MAX - }; + #[cfg(any(test, feature = "test-support"))] + let max_ticks = self + .dispatcher + .as_test() + .map_or(usize::MAX, |dispatcher| dispatcher.gen_block_on_ticks()); + #[cfg(not(any(test, feature = "test-support")))] + let max_ticks = usize::MAX; + let mut timer = self.timer(duration).fuse(); let timeout = async { diff --git a/crates/gpui2/src/platform.rs b/crates/gpui2/src/platform.rs index 37b156e348..ed45d7bab2 100644 --- a/crates/gpui2/src/platform.rs +++ b/crates/gpui2/src/platform.rs @@ -160,7 +160,7 @@ pub trait PlatformWindow { fn sprite_atlas(&self) -> Arc; #[cfg(any(test, feature = "test-support"))] - fn as_test(&self) -> Option<&TestWindow> { + fn as_test(&mut self) -> Option<&mut TestWindow> { None } } diff --git a/crates/gpui2/src/platform/test/window.rs b/crates/gpui2/src/platform/test/window.rs index 2ad54eff0d..b1bfebad06 100644 --- a/crates/gpui2/src/platform/test/window.rs +++ b/crates/gpui2/src/platform/test/window.rs @@ -19,7 +19,7 @@ pub(crate) struct TestWindowHandlers { } pub struct TestWindow { - bounds: WindowBounds, + pub(crate) bounds: WindowBounds, current_scene: Mutex>, display: Rc, pub(crate) window_title: Option, @@ -170,7 +170,7 @@ impl PlatformWindow for TestWindow { self.sprite_atlas.clone() } - fn as_test(&self) -> Option<&TestWindow> { + fn as_test(&mut self) -> Option<&mut TestWindow> { Some(self) } } diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 640538fff0..9254eaeb85 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -208,8 +208,9 @@ impl TextStyle { } } + /// Returns the rounded line height in 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 {