events.rs 11 KB

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