Add command palette tests and simulate_keystrokes (#3330)
Release Notes: - N/A
This commit is contained in:
@@ -54,6 +54,9 @@ pub trait Action: std::fmt::Debug + 'static {
|
||||
where
|
||||
Self: Sized;
|
||||
fn build(value: Option<serde_json::Value>) -> Result<Box<dyn Action>>
|
||||
where
|
||||
Self: Sized;
|
||||
fn is_registered() -> bool
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
@@ -88,6 +91,14 @@ where
|
||||
Ok(Box::new(action))
|
||||
}
|
||||
|
||||
fn is_registered() -> bool {
|
||||
ACTION_REGISTRY
|
||||
.read()
|
||||
.names_by_type_id
|
||||
.get(&TypeId::of::<A>())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn partial_eq(&self, action: &dyn Action) -> bool {
|
||||
action
|
||||
.as_any()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
||||
BackgroundExecutor, Context, Div, EventEmitter, ForegroundExecutor, InputEvent, KeyDownEvent,
|
||||
Keystroke, Model, ModelContext, Render, Result, Task, TestDispatcher, TestPlatform, View,
|
||||
ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||
Keystroke, Model, ModelContext, Render, Result, Task, TestDispatcher, TestPlatform, TestWindow,
|
||||
View, ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
use futures::{Stream, StreamExt};
|
||||
@@ -220,7 +220,21 @@ impl TestAppContext {
|
||||
{
|
||||
window
|
||||
.update(self, |_, cx| cx.dispatch_action(action.boxed_clone()))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
self.background_executor.run_until_parked()
|
||||
}
|
||||
|
||||
pub fn simulate_keystrokes(&mut self, window: AnyWindowHandle, keystrokes: &str) {
|
||||
for keystroke in keystrokes
|
||||
.split(" ")
|
||||
.map(Keystroke::parse)
|
||||
.map(Result::unwrap)
|
||||
{
|
||||
self.dispatch_keystroke(window, keystroke.into(), false);
|
||||
}
|
||||
|
||||
self.background_executor.run_until_parked()
|
||||
}
|
||||
|
||||
pub fn dispatch_keystroke(
|
||||
@@ -229,15 +243,41 @@ impl TestAppContext {
|
||||
keystroke: Keystroke,
|
||||
is_held: bool,
|
||||
) {
|
||||
let keystroke2 = keystroke.clone();
|
||||
let handled = window
|
||||
.update(self, |_, cx| {
|
||||
cx.dispatch_event(InputEvent::KeyDown(KeyDownEvent { keystroke, is_held }))
|
||||
})
|
||||
.is_ok_and(|handled| handled);
|
||||
|
||||
if !handled {
|
||||
// todo!() simluate input here
|
||||
if handled {
|
||||
return;
|
||||
}
|
||||
|
||||
let input_handler = self.update_test_window(window, |window| window.input_handler.clone());
|
||||
let Some(input_handler) = input_handler else {
|
||||
panic!(
|
||||
"dispatch_keystroke {:?} failed to dispatch action or input",
|
||||
&keystroke2
|
||||
);
|
||||
};
|
||||
let text = keystroke2.ime_key.unwrap_or(keystroke2.key);
|
||||
input_handler.lock().replace_text_in_range(None, &text);
|
||||
}
|
||||
|
||||
pub fn update_test_window<R>(
|
||||
&mut self,
|
||||
window: AnyWindowHandle,
|
||||
f: impl FnOnce(&mut TestWindow) -> R,
|
||||
) -> R {
|
||||
window
|
||||
.update(self, |_, cx| {
|
||||
f(cx.window
|
||||
.platform_window
|
||||
.as_any_mut()
|
||||
.downcast_mut::<TestWindow>()
|
||||
.unwrap())
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn notifications<T: 'static>(&mut self, entity: &Model<T>) -> impl Stream<Item = ()> {
|
||||
@@ -401,12 +441,20 @@ impl<'a> VisualTestContext<'a> {
|
||||
Self { cx, window }
|
||||
}
|
||||
|
||||
pub fn run_until_parked(&self) {
|
||||
self.cx.background_executor.run_until_parked();
|
||||
}
|
||||
|
||||
pub fn dispatch_action<A>(&mut self, action: A)
|
||||
where
|
||||
A: Action,
|
||||
{
|
||||
self.cx.dispatch_action(self.window, action)
|
||||
}
|
||||
|
||||
pub fn simulate_keystrokes(&mut self, keystrokes: &str) {
|
||||
self.cx.simulate_keystrokes(self.window, keystrokes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Context for VisualTestContext<'a> {
|
||||
|
||||
@@ -229,6 +229,20 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
|
||||
mut self,
|
||||
listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
|
||||
) -> Self {
|
||||
// NOTE: this debug assert has the side-effect of working around
|
||||
// a bug where a crate consisting only of action definitions does
|
||||
// not register the actions in debug builds:
|
||||
//
|
||||
// https://github.com/rust-lang/rust/issues/47384
|
||||
// https://github.com/mmastrac/rust-ctor/issues/280
|
||||
//
|
||||
// if we are relying on this side-effect still, removing the debug_assert!
|
||||
// likely breaks the command_palette tests.
|
||||
debug_assert!(
|
||||
A::is_registered(),
|
||||
"{:?} is not registered as an action",
|
||||
A::qualified_name()
|
||||
);
|
||||
self.interactivity().action_listeners.push((
|
||||
TypeId::of::<A>(),
|
||||
Box::new(move |view, action, phase, cx| {
|
||||
|
||||
@@ -337,7 +337,6 @@ mod test {
|
||||
.update(cx, |test_view, cx| cx.focus(&test_view.focus_handle))
|
||||
.unwrap();
|
||||
|
||||
cx.dispatch_keystroke(*window, Keystroke::parse("space").unwrap(), false);
|
||||
cx.dispatch_keystroke(*window, Keystroke::parse("ctrl-g").unwrap(), false);
|
||||
|
||||
window
|
||||
|
||||
@@ -22,7 +22,7 @@ pub struct TestWindow {
|
||||
bounds: WindowBounds,
|
||||
current_scene: Mutex<Option<Scene>>,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
input_handler: Option<Box<dyn PlatformInputHandler>>,
|
||||
pub(crate) input_handler: Option<Arc<Mutex<Box<dyn PlatformInputHandler>>>>,
|
||||
handlers: Mutex<Handlers>,
|
||||
platform: Weak<TestPlatform>,
|
||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||
@@ -80,11 +80,11 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
todo!()
|
||||
self
|
||||
}
|
||||
|
||||
fn set_input_handler(&mut self, input_handler: Box<dyn crate::PlatformInputHandler>) {
|
||||
self.input_handler = Some(input_handler);
|
||||
self.input_handler = Some(Arc::new(Mutex::new(input_handler)));
|
||||
}
|
||||
|
||||
fn prompt(
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Drop for FocusHandle {
|
||||
pub struct Window {
|
||||
pub(crate) handle: AnyWindowHandle,
|
||||
pub(crate) removed: bool,
|
||||
platform_window: Box<dyn PlatformWindow>,
|
||||
pub(crate) platform_window: Box<dyn PlatformWindow>,
|
||||
display_id: DisplayId,
|
||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||
rem_size: Pixels,
|
||||
|
||||
Reference in New Issue
Block a user