Explorar el Código

Merge pull request #445 from Demonthos/test_tui_events

test tui events
Jon Kelley hace 3 años
padre
commit
c3e573b7cb
Se han modificado 3 ficheros con 363 adiciones y 3 borrados
  1. 5 0
      packages/tui/Cargo.toml
  2. 9 3
      packages/tui/src/lib.rs
  3. 349 0
      packages/tui/tests/events.rs

+ 5 - 0
packages/tui/Cargo.toml

@@ -27,3 +27,8 @@ taffy = "0.1.0"
 smallvec = "1.6"
 fxhash = "0.2"
 anymap = "0.12.1"
+
+[dev-dependencies]
+dioxus-core-macro = { path = "../core-macro", version = "^0.2.1" }
+dioxus-hooks = { path = "../hooks", version = "^0.2.1" }
+tokio = { version = "1" }

+ 9 - 3
packages/tui/src/lib.rs

@@ -41,6 +41,12 @@ impl TuiContext {
     pub fn quit(&self) {
         self.tx.unbounded_send(InputEvent::Close).unwrap();
     }
+
+    pub fn inject_event(&self, event: crossterm::event::Event) {
+        self.tx
+            .unbounded_send(InputEvent::UserInput(event))
+            .unwrap();
+    }
 }
 
 pub fn launch(app: Component<()>) {
@@ -60,7 +66,6 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
             let tick_rate = Duration::from_millis(1000);
             loop {
                 if crossterm::event::poll(tick_rate).unwrap() {
-                    // if crossterm::event::poll(timeout).unwrap() {
                     let evt = crossterm::event::read().unwrap();
                     if event_tx.unbounded_send(InputEvent::UserInput(evt)).is_err() {
                         break;
@@ -169,8 +174,8 @@ fn render_vdom(
                             Rect {
                                 x: 0,
                                 y: 0,
-                                width: 300,
-                                height: 300,
+                                width: 100,
+                                height: 100,
                             },
                             &mut taffy.borrow_mut(),
                             &rdom,
@@ -246,6 +251,7 @@ fn render_vdom(
         })
 }
 
+#[derive(Debug)]
 enum InputEvent {
     UserInput(TermEvent),
     Close,

+ 349 - 0
packages/tui/tests/events.rs

@@ -0,0 +1,349 @@
+use std::time::Duration;
+
+use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent};
+use dioxus_core::VNode;
+use dioxus_core::*;
+use dioxus_core_macro::*;
+use dioxus_hooks::*;
+use dioxus_html as dioxus_elements;
+use dioxus_tui::TuiContext;
+
+#[test]
+fn key_down() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Key(KeyEvent {
+            code: KeyCode::Char('a'),
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onkeydown: move |evt| {
+                    assert_eq!(evt.data.key_code, dioxus_html::KeyCode::A);
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn mouse_down() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 0,
+            row: 0,
+            kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onmousedown: move |evt| {
+                    assert!(evt.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary));
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn mouse_up() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 0,
+            row: 0,
+            kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 0,
+            row: 0,
+            kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onmouseup: move |_| {
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn mouse_enter() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 100,
+            row: 100,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 0,
+            row: 0,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "50%",
+                height: "50%",
+                onmouseenter: move |_| {
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn mouse_exit() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 0,
+            row: 0,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 100,
+            row: 100,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "50%",
+                height: "50%",
+                onmouseenter: move |_| {
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn mouse_move() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 40,
+            row: 40,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 60,
+            row: 60,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onmousemove: move |_|{
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn wheel() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::Moved,
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::ScrollDown,
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onwheel: move |evt| {
+                    assert!(evt.data.delta_y > 0.0);
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn click() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                onclick: move |_|{
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}
+
+#[test]
+fn context_menu() {
+    dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
+
+    fn app(cx: Scope) -> Element {
+        let render_count = use_state(&cx, || 0);
+        let tui_ctx: TuiContext = cx.consume_context().unwrap();
+        let render_count_handle = render_count.clone();
+        cx.spawn(async move {
+            tokio::time::sleep(Duration::from_millis(100)).await;
+            render_count_handle.modify(|x| *x + 1);
+        });
+        if *render_count.get() > 2 {
+            panic!("Event was not received");
+        }
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::Down(MouseButton::Right),
+            modifiers: KeyModifiers::NONE,
+        }));
+        tui_ctx.inject_event(Event::Mouse(MouseEvent {
+            column: 50,
+            row: 50,
+            kind: crossterm::event::MouseEventKind::Up(MouseButton::Right),
+            modifiers: KeyModifiers::NONE,
+        }));
+        cx.render(rsx! {
+            div {
+                width: "100%",
+                height: "100%",
+                oncontextmenu: move |_|{
+                    tui_ctx.quit();
+                },
+            }
+        })
+    }
+}