events.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. use std::time::Duration;
  2. use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent};
  3. use dioxus_core::VNode;
  4. use dioxus_core::*;
  5. use dioxus_core_macro::*;
  6. use dioxus_hooks::*;
  7. use dioxus_html as dioxus_elements;
  8. use dioxus_tui::TuiContext;
  9. #[test]
  10. fn key_down() {
  11. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  12. fn app(cx: Scope) -> Element {
  13. let render_count = use_state(&cx, || 0);
  14. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  15. let render_count_handle = render_count.clone();
  16. cx.spawn(async move {
  17. tokio::time::sleep(Duration::from_millis(100)).await;
  18. render_count_handle.modify(|x| *x + 1);
  19. });
  20. if *render_count.get() > 2 {
  21. panic!("Event was not received");
  22. }
  23. tui_ctx.inject_event(Event::Key(KeyEvent {
  24. code: KeyCode::Char('a'),
  25. modifiers: KeyModifiers::NONE,
  26. }));
  27. cx.render(rsx! {
  28. div {
  29. width: "100%",
  30. height: "100%",
  31. onkeydown: move |evt| {
  32. assert_eq!(evt.data.key_code, dioxus_html::KeyCode::A);
  33. tui_ctx.quit();
  34. },
  35. }
  36. })
  37. }
  38. }
  39. #[test]
  40. fn mouse_down() {
  41. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  42. fn app(cx: Scope) -> Element {
  43. let render_count = use_state(&cx, || 0);
  44. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  45. let render_count_handle = render_count.clone();
  46. cx.spawn(async move {
  47. tokio::time::sleep(Duration::from_millis(100)).await;
  48. render_count_handle.modify(|x| *x + 1);
  49. });
  50. if *render_count.get() > 2 {
  51. panic!("Event was not received");
  52. }
  53. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  54. column: 0,
  55. row: 0,
  56. kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
  57. modifiers: KeyModifiers::NONE,
  58. }));
  59. cx.render(rsx! {
  60. div {
  61. width: "100%",
  62. height: "100%",
  63. onmousedown: move |evt| {
  64. assert!(evt.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary));
  65. tui_ctx.quit();
  66. },
  67. }
  68. })
  69. }
  70. }
  71. #[test]
  72. fn mouse_up() {
  73. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  74. fn app(cx: Scope) -> Element {
  75. let render_count = use_state(&cx, || 0);
  76. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  77. let render_count_handle = render_count.clone();
  78. cx.spawn(async move {
  79. tokio::time::sleep(Duration::from_millis(100)).await;
  80. render_count_handle.modify(|x| *x + 1);
  81. });
  82. if *render_count.get() > 2 {
  83. panic!("Event was not received");
  84. }
  85. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  86. column: 0,
  87. row: 0,
  88. kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
  89. modifiers: KeyModifiers::NONE,
  90. }));
  91. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  92. column: 0,
  93. row: 0,
  94. kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
  95. modifiers: KeyModifiers::NONE,
  96. }));
  97. cx.render(rsx! {
  98. div {
  99. width: "100%",
  100. height: "100%",
  101. onmouseup: move |_| {
  102. tui_ctx.quit();
  103. },
  104. }
  105. })
  106. }
  107. }
  108. #[test]
  109. fn mouse_enter() {
  110. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  111. fn app(cx: Scope) -> Element {
  112. let render_count = use_state(&cx, || 0);
  113. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  114. let render_count_handle = render_count.clone();
  115. cx.spawn(async move {
  116. tokio::time::sleep(Duration::from_millis(100)).await;
  117. render_count_handle.modify(|x| *x + 1);
  118. });
  119. if *render_count.get() > 2 {
  120. panic!("Event was not received");
  121. }
  122. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  123. column: 100,
  124. row: 100,
  125. kind: crossterm::event::MouseEventKind::Moved,
  126. modifiers: KeyModifiers::NONE,
  127. }));
  128. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  129. column: 0,
  130. row: 0,
  131. kind: crossterm::event::MouseEventKind::Moved,
  132. modifiers: KeyModifiers::NONE,
  133. }));
  134. cx.render(rsx! {
  135. div {
  136. width: "50%",
  137. height: "50%",
  138. onmouseenter: move |_| {
  139. tui_ctx.quit();
  140. },
  141. }
  142. })
  143. }
  144. }
  145. #[test]
  146. fn mouse_exit() {
  147. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  148. fn app(cx: Scope) -> Element {
  149. let render_count = use_state(&cx, || 0);
  150. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  151. let render_count_handle = render_count.clone();
  152. cx.spawn(async move {
  153. tokio::time::sleep(Duration::from_millis(100)).await;
  154. render_count_handle.modify(|x| *x + 1);
  155. });
  156. if *render_count.get() > 2 {
  157. panic!("Event was not received");
  158. }
  159. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  160. column: 0,
  161. row: 0,
  162. kind: crossterm::event::MouseEventKind::Moved,
  163. modifiers: KeyModifiers::NONE,
  164. }));
  165. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  166. column: 100,
  167. row: 100,
  168. kind: crossterm::event::MouseEventKind::Moved,
  169. modifiers: KeyModifiers::NONE,
  170. }));
  171. cx.render(rsx! {
  172. div {
  173. width: "50%",
  174. height: "50%",
  175. onmouseenter: move |_| {
  176. tui_ctx.quit();
  177. },
  178. }
  179. })
  180. }
  181. }
  182. #[test]
  183. fn mouse_move() {
  184. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  185. fn app(cx: Scope) -> Element {
  186. let render_count = use_state(&cx, || 0);
  187. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  188. let render_count_handle = render_count.clone();
  189. cx.spawn(async move {
  190. tokio::time::sleep(Duration::from_millis(100)).await;
  191. render_count_handle.modify(|x| *x + 1);
  192. });
  193. if *render_count.get() > 2 {
  194. panic!("Event was not received");
  195. }
  196. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  197. column: 40,
  198. row: 40,
  199. kind: crossterm::event::MouseEventKind::Moved,
  200. modifiers: KeyModifiers::NONE,
  201. }));
  202. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  203. column: 60,
  204. row: 60,
  205. kind: crossterm::event::MouseEventKind::Moved,
  206. modifiers: KeyModifiers::NONE,
  207. }));
  208. cx.render(rsx! {
  209. div {
  210. width: "100%",
  211. height: "100%",
  212. onmousemove: move |_|{
  213. tui_ctx.quit();
  214. },
  215. }
  216. })
  217. }
  218. }
  219. #[test]
  220. fn wheel() {
  221. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  222. fn app(cx: Scope) -> Element {
  223. let render_count = use_state(&cx, || 0);
  224. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  225. let render_count_handle = render_count.clone();
  226. cx.spawn(async move {
  227. tokio::time::sleep(Duration::from_millis(100)).await;
  228. render_count_handle.modify(|x| *x + 1);
  229. });
  230. if *render_count.get() > 2 {
  231. panic!("Event was not received");
  232. }
  233. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  234. column: 50,
  235. row: 50,
  236. kind: crossterm::event::MouseEventKind::Moved,
  237. modifiers: KeyModifiers::NONE,
  238. }));
  239. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  240. column: 50,
  241. row: 50,
  242. kind: crossterm::event::MouseEventKind::ScrollDown,
  243. modifiers: KeyModifiers::NONE,
  244. }));
  245. cx.render(rsx! {
  246. div {
  247. width: "100%",
  248. height: "100%",
  249. onwheel: move |evt| {
  250. assert!(evt.data.delta_y > 0.0);
  251. tui_ctx.quit();
  252. },
  253. }
  254. })
  255. }
  256. }
  257. #[test]
  258. fn click() {
  259. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  260. fn app(cx: Scope) -> Element {
  261. let render_count = use_state(&cx, || 0);
  262. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  263. let render_count_handle = render_count.clone();
  264. cx.spawn(async move {
  265. tokio::time::sleep(Duration::from_millis(100)).await;
  266. render_count_handle.modify(|x| *x + 1);
  267. });
  268. if *render_count.get() > 2 {
  269. panic!("Event was not received");
  270. }
  271. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  272. column: 50,
  273. row: 50,
  274. kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
  275. modifiers: KeyModifiers::NONE,
  276. }));
  277. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  278. column: 50,
  279. row: 50,
  280. kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
  281. modifiers: KeyModifiers::NONE,
  282. }));
  283. cx.render(rsx! {
  284. div {
  285. width: "100%",
  286. height: "100%",
  287. onclick: move |_|{
  288. tui_ctx.quit();
  289. },
  290. }
  291. })
  292. }
  293. }
  294. #[test]
  295. fn context_menu() {
  296. dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
  297. fn app(cx: Scope) -> Element {
  298. let render_count = use_state(&cx, || 0);
  299. let tui_ctx: TuiContext = cx.consume_context().unwrap();
  300. let render_count_handle = render_count.clone();
  301. cx.spawn(async move {
  302. tokio::time::sleep(Duration::from_millis(100)).await;
  303. render_count_handle.modify(|x| *x + 1);
  304. });
  305. if *render_count.get() > 2 {
  306. panic!("Event was not received");
  307. }
  308. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  309. column: 50,
  310. row: 50,
  311. kind: crossterm::event::MouseEventKind::Down(MouseButton::Right),
  312. modifiers: KeyModifiers::NONE,
  313. }));
  314. tui_ctx.inject_event(Event::Mouse(MouseEvent {
  315. column: 50,
  316. row: 50,
  317. kind: crossterm::event::MouseEventKind::Up(MouseButton::Right),
  318. modifiers: KeyModifiers::NONE,
  319. }));
  320. cx.render(rsx! {
  321. div {
  322. width: "100%",
  323. height: "100%",
  324. oncontextmenu: move |_|{
  325. tui_ctx.quit();
  326. },
  327. }
  328. })
  329. }
  330. }