From f381e56ab396542bb4955c9afe3875dc67707b6b Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 27 Apr 2023 16:38:09 -0500 Subject: [PATCH 1/8] test scafolding --- packages/desktop/Cargo.toml | 6 ++++++ packages/desktop/headless_tests/main.rs | 28 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 packages/desktop/headless_tests/main.rs diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index 8b41019e1..af5f3e68f 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -57,4 +57,10 @@ hot-reload = ["dioxus-hot-reload"] [dev-dependencies] dioxus-core-macro = { path = "../core-macro" } dioxus-hooks = { path = "../hooks" } +dioxus = { path = "../dioxus" } # image = "0.24.0" # enable this when generating a new desktop image + +[[test]] +name = "headless_tests" +path = "headless_tests/main.rs" +harness = false \ No newline at end of file diff --git a/packages/desktop/headless_tests/main.rs b/packages/desktop/headless_tests/main.rs new file mode 100644 index 000000000..e07cb08c3 --- /dev/null +++ b/packages/desktop/headless_tests/main.rs @@ -0,0 +1,28 @@ +// Check that all events are being forwarded to the mock. +//! This example roughly shows how events are serialized into Rust from JavaScript. +//! +//! There is some conversion happening when input types are checkbox/radio/select/textarea etc. + +use dioxus::prelude::*; + +mod events; + +fn main() { + events::test_events(); +} + +pub(crate) fn check_app_exits(app: Component) { + // This is a deadman's switch to ensure that the app exits + let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); + let should_panic_clone = should_panic.clone(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_secs(100)); + if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { + panic!("App did not exit successfully") + } + }); + + dioxus_desktop::launch(app); + + should_panic.store(false, std::sync::atomic::Ordering::SeqCst); +} From 01d673e6544c26395d8d719c19a507af2c95f611 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 27 Apr 2023 18:00:43 -0500 Subject: [PATCH 2/8] create event tests --- packages/desktop/Cargo.toml | 2 +- packages/desktop/headless_tests/events.rs | 290 ++++++++++++++++++++++ packages/desktop/headless_tests/main.rs | 4 +- 3 files changed, 293 insertions(+), 3 deletions(-) create mode 100644 packages/desktop/headless_tests/events.rs diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index af5f3e68f..e8812df5a 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -58,7 +58,7 @@ hot-reload = ["dioxus-hot-reload"] dioxus-core-macro = { path = "../core-macro" } dioxus-hooks = { path = "../hooks" } dioxus = { path = "../dioxus" } -# image = "0.24.0" # enable this when generating a new desktop image +exitcode = "1.1.2" [[test]] name = "headless_tests" diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs new file mode 100644 index 000000000..34e29f024 --- /dev/null +++ b/packages/desktop/headless_tests/events.rs @@ -0,0 +1,290 @@ +use crate::check_app_exits; +use dioxus::prelude::*; +use dioxus_desktop::DesktopContext; +use dioxus::html::geometry::euclid::Vector3D; + +pub fn test_events() { + check_app_exits(app); +} + +fn mock_event(cx: &ScopeState, id: &'static str, value: &'static str) { + use_effect(cx, (), |_| { + let desktop_context: DesktopContext = cx.consume_context().unwrap(); + async move { + desktop_context.eval(&format!( + r#"let element = document.getElementById('{}'); + // Dispatch a synthetic event + const event = {}; + element.dispatchEvent(event); + "#, + id, value + )); + } + }); +} + +#[allow(deprecated)] +fn app(cx: Scope) -> Element { + let desktop_context: DesktopContext = cx.consume_context().unwrap(); + let recieved_events = use_state(cx, || 0); + + // button + mock_event( + &cx, + "button", + r#"new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: true, + button: 0, + })"#, + ); + // mouse_move_div + mock_event( + &cx, + "mouse_move_div", + r#"new MouseEvent("mousemove", { + view: window, + bubbles: true, + cancelable: true, + buttons: 2, + })"#, + ); + // mouse_click_div + mock_event( + &cx, + "mouse_click_div", + r#"new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: true, + buttons: 2, + button: 2, + })"# + ); + // mouse_dblclick_div + mock_event( + &cx, + "mouse_dblclick_div", + r#"new MouseEvent("dblclick", { + view: window, + bubbles: true, + cancelable: true, + buttons: 1|2, + button: 2, + })"#, + ); + // mouse_down_div + mock_event( + &cx, + "mouse_down_div", + r#"new MouseEvent("mousedown", { + view: window, + bubbles: true, + cancelable: true, + buttons: 2, + button: 2, + })"#, + ); + // mouse_up_div + mock_event( + &cx, + "mouse_up_div", + r#"new MouseEvent("mouseup", { + view: window, + bubbles: true, + cancelable: true, + buttons: 0, + button: 0, + })"#, + ); + // wheel_div + mock_event( + &cx, + "wheel_div", + r#"new WheelEvent("wheel", { + deltaX: 1.0, + deltaY: 2.0, + deltaZ: 3.0, + })"#, + ); + // key_down_div + mock_event( + &cx, + "key_down_div", + r#"new KeyboardEvent("keydown", { + key: "a", + code: "KeyA", + location: 0, + repeat: true, + })"#, + ); + // key_up_div + mock_event( + &cx, + "key_up_div", + r#"new KeyboardEvent("keyup", { + key: "a", + code: "KeyA", + location: 0, + repeat: false, + })"#, + ); + // key_press_div + mock_event( + &cx, + "key_press_div", + r#"new KeyboardEvent("keypress", { + key: "a", + code: "KeyA", + location: 0, + repeat: false, + })"#, + ); + // focus_in_div + mock_event( + &cx, + "focus_in_div", + r#"new FocusEvent("focusin")"#, + ); + // focus_out_div + mock_event( + &cx, + "focus_out_div", + r#"new FocusEvent("focusout")"#, + ); + + + if **recieved_events == 12 { + desktop_context.close(); + } + + cx.render(rsx! { + div { + button { + id: "button", + onclick: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().is_empty()); + assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Primary)); + recieved_events.modify(|x| *x + 1) + }, + } + div { + id: "mouse_move_div", + onmousemove: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary)); + recieved_events.modify(|x| *x + 1) + }, + } + div { + id: "mouse_click_div", + onclick: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary)); + assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary)); + recieved_events.modify(|x| *x + 1) + }, + } + div{ + id: "mouse_dblclick_div", + ondblclick: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary)); + assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary)); + assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary)); + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "mouse_down_div", + onmousedown: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Secondary)); + assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Secondary)); + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "mouse_up_div", + onmouseup: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert!(event.data.held_buttons().is_empty()); + assert_eq!(event.data.trigger_button(), Some(dioxus_html::input_data::MouseButton::Primary)); + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "wheel_div", + onwheel: move |event| { + println!("{:?}", event.data); + let dioxus_html::geometry::WheelDelta::Pixels(delta)= event.data.delta()else{ + panic!("Expected delta to be in pixels") + }; + assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0)); + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "key_down_div", + onkeydown: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert_eq!(event.data.key().to_string(), "a"); + assert_eq!(event.data.code().to_string(), "KeyA"); + assert_eq!(event.data.location, 0); + assert!(event.data.is_auto_repeating()); + + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "key_up_div", + onkeyup: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert_eq!(event.data.key().to_string(), "a"); + assert_eq!(event.data.code().to_string(), "KeyA"); + assert_eq!(event.data.location, 0); + assert!(!event.data.is_auto_repeating()); + + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "key_press_div", + onkeypress: move |event| { + println!("{:?}", event.data); + assert!(event.data.modifiers().is_empty()); + assert_eq!(event.data.key().to_string(), "a"); + assert_eq!(event.data.code().to_string(), "KeyA"); + assert_eq!(event.data.location, 0); + assert!(!event.data.is_auto_repeating()); + + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "focus_in_div", + onfocusin: move |event| { + println!("{:?}", event.data); + recieved_events.modify(|x| *x + 1) + } + } + div{ + id: "focus_out_div", + onfocusout: move |event| { + println!("{:?}", event.data); + recieved_events.modify(|x| *x + 1) + } + } + } + }) +} diff --git a/packages/desktop/headless_tests/main.rs b/packages/desktop/headless_tests/main.rs index e07cb08c3..65b6c80a3 100644 --- a/packages/desktop/headless_tests/main.rs +++ b/packages/desktop/headless_tests/main.rs @@ -16,9 +16,9 @@ pub(crate) fn check_app_exits(app: Component) { let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); let should_panic_clone = should_panic.clone(); std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(100)); + std::thread::sleep(std::time::Duration::from_secs(10)); if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { - panic!("App did not exit successfully") + std::process::exit(exitcode::SOFTWARE); } }); From 70687748d3577449d101e41a13a033c6cc76aa24 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 27 Apr 2023 18:36:28 -0500 Subject: [PATCH 3/8] fix events test --- packages/desktop/headless_tests/events.rs | 55 ++++++++++++++++++++--- packages/desktop/headless_tests/main.rs | 2 +- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index 34e29f024..60962c868 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -11,10 +11,12 @@ fn mock_event(cx: &ScopeState, id: &'static str, value: &'static str) { use_effect(cx, (), |_| { let desktop_context: DesktopContext = cx.consume_context().unwrap(); async move { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; desktop_context.eval(&format!( r#"let element = document.getElementById('{}'); // Dispatch a synthetic event const event = {}; + console.log(element, event); element.dispatchEvent(event); "#, id, value @@ -103,9 +105,12 @@ fn app(cx: Scope) -> Element { &cx, "wheel_div", r#"new WheelEvent("wheel", { + view: window, deltaX: 1.0, deltaY: 2.0, deltaZ: 3.0, + deltaMode: 0x00, + bubbles: true, })"#, ); // key_down_div @@ -117,6 +122,17 @@ fn app(cx: Scope) -> Element { code: "KeyA", location: 0, repeat: true, + keyCode: 65, + charCode: 97, + char: "a", + charCode: 0, + altKey: false, + ctrlKey: false, + metaKey: false, + shiftKey: false, + isComposing: false, + which: 65, + bubbles: true, })"#, ); // key_up_div @@ -128,6 +144,17 @@ fn app(cx: Scope) -> Element { code: "KeyA", location: 0, repeat: false, + keyCode: 65, + charCode: 97, + char: "a", + charCode: 0, + altKey: false, + ctrlKey: false, + metaKey: false, + shiftKey: false, + isComposing: false, + which: 65, + bubbles: true, })"#, ); // key_press_div @@ -139,19 +166,30 @@ fn app(cx: Scope) -> Element { code: "KeyA", location: 0, repeat: false, + keyCode: 65, + charCode: 97, + char: "a", + charCode: 0, + altKey: false, + ctrlKey: false, + metaKey: false, + shiftKey: false, + isComposing: false, + which: 65, + bubbles: true, })"#, ); // focus_in_div mock_event( &cx, "focus_in_div", - r#"new FocusEvent("focusin")"#, + r#"new FocusEvent("focusin", {bubbles: true})"#, ); // focus_out_div mock_event( &cx, "focus_out_div", - r#"new FocusEvent("focusout")"#, + r#"new FocusEvent("focusout",{bubbles: true})"#, ); @@ -223,6 +261,9 @@ fn app(cx: Scope) -> Element { } div{ id: "wheel_div", + width: "100px", + height: "100px", + background_color: "red", onwheel: move |event| { println!("{:?}", event.data); let dioxus_html::geometry::WheelDelta::Pixels(delta)= event.data.delta()else{ @@ -232,7 +273,7 @@ fn app(cx: Scope) -> Element { recieved_events.modify(|x| *x + 1) } } - div{ + input{ id: "key_down_div", onkeydown: move |event| { println!("{:?}", event.data); @@ -245,7 +286,7 @@ fn app(cx: Scope) -> Element { recieved_events.modify(|x| *x + 1) } } - div{ + input{ id: "key_up_div", onkeyup: move |event| { println!("{:?}", event.data); @@ -258,7 +299,7 @@ fn app(cx: Scope) -> Element { recieved_events.modify(|x| *x + 1) } } - div{ + input{ id: "key_press_div", onkeypress: move |event| { println!("{:?}", event.data); @@ -271,14 +312,14 @@ fn app(cx: Scope) -> Element { recieved_events.modify(|x| *x + 1) } } - div{ + input{ id: "focus_in_div", onfocusin: move |event| { println!("{:?}", event.data); recieved_events.modify(|x| *x + 1) } } - div{ + input{ id: "focus_out_div", onfocusout: move |event| { println!("{:?}", event.data); diff --git a/packages/desktop/headless_tests/main.rs b/packages/desktop/headless_tests/main.rs index 65b6c80a3..a9d9ec61c 100644 --- a/packages/desktop/headless_tests/main.rs +++ b/packages/desktop/headless_tests/main.rs @@ -16,7 +16,7 @@ pub(crate) fn check_app_exits(app: Component) { let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); let should_panic_clone = should_panic.clone(); std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(10)); + std::thread::sleep(std::time::Duration::from_secs(100)); if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { std::process::exit(exitcode::SOFTWARE); } From 1b199977d150176ba9020ef3f7225282c2619de6 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 4 May 2023 11:04:06 -0500 Subject: [PATCH 4/8] add rendering tests --- packages/desktop/Cargo.toml | 13 ++- packages/desktop/headless_tests/events.rs | 21 ++++- packages/desktop/headless_tests/main.rs | 28 ------ packages/desktop/headless_tests/rendering.rs | 89 ++++++++++++++++++++ 4 files changed, 118 insertions(+), 33 deletions(-) delete mode 100644 packages/desktop/headless_tests/main.rs create mode 100644 packages/desktop/headless_tests/rendering.rs diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index e8812df5a..092676322 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -59,8 +59,15 @@ dioxus-core-macro = { path = "../core-macro" } dioxus-hooks = { path = "../hooks" } dioxus = { path = "../dioxus" } exitcode = "1.1.2" +scraper = "0.16.0" + +# These tests need to be run on the main thread, so they cannot use rust's test harness. +[[test]] +name = "check_events" +path = "headless_tests/events.rs" +harness = false [[test]] -name = "headless_tests" -path = "headless_tests/main.rs" -harness = false \ No newline at end of file +name = "check_rendering" +path = "headless_tests/rendering.rs" +harness = false diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index 60962c868..ec77850bd 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -1,9 +1,25 @@ -use crate::check_app_exits; + use dioxus::prelude::*; use dioxus_desktop::DesktopContext; use dioxus::html::geometry::euclid::Vector3D; -pub fn test_events() { +pub(crate) fn check_app_exits(app: Component) { + // This is a deadman's switch to ensure that the app exits + let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); + let should_panic_clone = should_panic.clone(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_secs(100)); + if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { + std::process::exit(exitcode::SOFTWARE); + } + }); + + dioxus_desktop::launch(app); + + should_panic.store(false, std::sync::atomic::Ordering::SeqCst); +} + +pub fn main() { check_app_exits(app); } @@ -194,6 +210,7 @@ fn app(cx: Scope) -> Element { if **recieved_events == 12 { + println!("all events recieved"); desktop_context.close(); } diff --git a/packages/desktop/headless_tests/main.rs b/packages/desktop/headless_tests/main.rs deleted file mode 100644 index a9d9ec61c..000000000 --- a/packages/desktop/headless_tests/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Check that all events are being forwarded to the mock. -//! This example roughly shows how events are serialized into Rust from JavaScript. -//! -//! There is some conversion happening when input types are checkbox/radio/select/textarea etc. - -use dioxus::prelude::*; - -mod events; - -fn main() { - events::test_events(); -} - -pub(crate) fn check_app_exits(app: Component) { - // This is a deadman's switch to ensure that the app exits - let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); - let should_panic_clone = should_panic.clone(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(100)); - if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { - std::process::exit(exitcode::SOFTWARE); - } - }); - - dioxus_desktop::launch(app); - - should_panic.store(false, std::sync::atomic::Ordering::SeqCst); -} diff --git a/packages/desktop/headless_tests/rendering.rs b/packages/desktop/headless_tests/rendering.rs new file mode 100644 index 000000000..9a2c8bf57 --- /dev/null +++ b/packages/desktop/headless_tests/rendering.rs @@ -0,0 +1,89 @@ +use dioxus::prelude::*; +use dioxus_desktop::DesktopContext; + +pub(crate) fn check_app_exits(app: Component) { + // This is a deadman's switch to ensure that the app exits + let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); + let should_panic_clone = should_panic.clone(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_secs(100)); + if should_panic_clone.load(std::sync::atomic::Ordering::SeqCst) { + std::process::exit(exitcode::SOFTWARE); + } + }); + + dioxus_desktop::launch(app); + + should_panic.store(false, std::sync::atomic::Ordering::SeqCst); +} + +fn main() { + check_app_exits(check_html_renders); +} + +fn use_inner_html(cx: &ScopeState, id: &'static str) -> Option { + let value: &UseRef> = use_ref(cx, || None); + use_effect(cx, (), |_| { + to_owned![value]; + let desktop_context: DesktopContext = cx.consume_context().unwrap(); + async move { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + let html = desktop_context + .eval(&format!( + r#"let element = document.getElementById('{}'); + return element.innerHTML;"#, + id + )) + .await; + if let Ok(serde_json::Value::String(html)) = html { + println!("html: {}", html); + value.set(Some(html)); + } + } + }); + value.read().clone() +} + +const EXPECTED_HTML: &str = r#"

text

hello world

"#; + +fn check_html_renders(cx: Scope) -> Element { + let inner_html = use_inner_html(cx, "main_div"); + let desktop_context: DesktopContext = cx.consume_context().unwrap(); + + if let Some(raw_html) = inner_html.as_deref() { + let fragment = scraper::Html::parse_fragment(raw_html); + println!("fragment: {:?}", fragment.html()); + let expected = scraper::Html::parse_fragment(EXPECTED_HTML); + println!("fragment: {:?}", expected.html()); + if fragment == expected { + println!("html matches"); + desktop_context.close(); + } + } + + let dyn_value = 0; + let dyn_element = rsx! { + div { + dangerous_inner_html: "

hello world

", + } + }; + + render! { + div { + id: "main_div", + div { + width: "100px", + height: "100px", + color: "rgb({dyn_value}, {dyn_value}, {dyn_value})", + id: 5, + input { + "type": "checkbox", + }, + h1 { + "text" + } + dyn_element + } + } + } +} From ea5e664364b9a1e8ab62a41198dc4afb053977ce Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 4 May 2023 11:39:46 -0500 Subject: [PATCH 5/8] fix formatting --- packages/desktop/headless_tests/events.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index ec77850bd..c0933921a 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -1,7 +1,6 @@ - +use dioxus::html::geometry::euclid::Vector3D; use dioxus::prelude::*; use dioxus_desktop::DesktopContext; -use dioxus::html::geometry::euclid::Vector3D; pub(crate) fn check_app_exits(app: Component) { // This is a deadman's switch to ensure that the app exits @@ -67,7 +66,7 @@ fn app(cx: Scope) -> Element { cancelable: true, buttons: 2, })"#, - ); + ); // mouse_click_div mock_event( &cx, @@ -78,7 +77,7 @@ fn app(cx: Scope) -> Element { cancelable: true, buttons: 2, button: 2, - })"# + })"#, ); // mouse_dblclick_div mock_event( @@ -207,7 +206,6 @@ fn app(cx: Scope) -> Element { "focus_out_div", r#"new FocusEvent("focusout",{bubbles: true})"#, ); - if **recieved_events == 12 { println!("all events recieved"); @@ -299,7 +297,7 @@ fn app(cx: Scope) -> Element { assert_eq!(event.data.code().to_string(), "KeyA"); assert_eq!(event.data.location, 0); assert!(event.data.is_auto_repeating()); - + recieved_events.modify(|x| *x + 1) } } @@ -325,7 +323,7 @@ fn app(cx: Scope) -> Element { assert_eq!(event.data.code().to_string(), "KeyA"); assert_eq!(event.data.location, 0); assert!(!event.data.is_auto_repeating()); - + recieved_events.modify(|x| *x + 1) } } From ae71e4ce339d729ae3e930ece4e63688b7e8a924 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 5 May 2023 11:11:50 -0500 Subject: [PATCH 6/8] don't render headless tests --- packages/desktop/headless_tests/events.rs | 7 ++++++- packages/desktop/headless_tests/rendering.rs | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index c0933921a..5a3fc44b6 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -3,6 +3,8 @@ use dioxus::prelude::*; use dioxus_desktop::DesktopContext; pub(crate) fn check_app_exits(app: Component) { + use dioxus_desktop::tao::window::WindowBuilder; + use dioxus_desktop::Config; // This is a deadman's switch to ensure that the app exits let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); let should_panic_clone = should_panic.clone(); @@ -13,7 +15,10 @@ pub(crate) fn check_app_exits(app: Component) { } }); - dioxus_desktop::launch(app); + dioxus_desktop::launch_cfg( + app, + Config::new().with_window(WindowBuilder::new().with_visible(false)), + ); should_panic.store(false, std::sync::atomic::Ordering::SeqCst); } diff --git a/packages/desktop/headless_tests/rendering.rs b/packages/desktop/headless_tests/rendering.rs index 9a2c8bf57..635da9c23 100644 --- a/packages/desktop/headless_tests/rendering.rs +++ b/packages/desktop/headless_tests/rendering.rs @@ -2,6 +2,8 @@ use dioxus::prelude::*; use dioxus_desktop::DesktopContext; pub(crate) fn check_app_exits(app: Component) { + use dioxus_desktop::tao::window::WindowBuilder; + use dioxus_desktop::Config; // This is a deadman's switch to ensure that the app exits let should_panic = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true)); let should_panic_clone = should_panic.clone(); @@ -12,7 +14,10 @@ pub(crate) fn check_app_exits(app: Component) { } }); - dioxus_desktop::launch(app); + dioxus_desktop::launch_cfg( + app, + Config::new().with_window(WindowBuilder::new().with_visible(false)), + ); should_panic.store(false, std::sync::atomic::Ordering::SeqCst); } From ec5999b3b4546a21aed4ac2b27f268d06e095cd4 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 5 May 2023 15:45:38 -0500 Subject: [PATCH 7/8] fix clippy --- packages/desktop/headless_tests/events.rs | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index 5a3fc44b6..0281969ec 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -52,7 +52,7 @@ fn app(cx: Scope) -> Element { // button mock_event( - &cx, + cx, "button", r#"new MouseEvent("click", { view: window, @@ -63,7 +63,7 @@ fn app(cx: Scope) -> Element { ); // mouse_move_div mock_event( - &cx, + cx, "mouse_move_div", r#"new MouseEvent("mousemove", { view: window, @@ -74,7 +74,7 @@ fn app(cx: Scope) -> Element { ); // mouse_click_div mock_event( - &cx, + cx, "mouse_click_div", r#"new MouseEvent("click", { view: window, @@ -86,7 +86,7 @@ fn app(cx: Scope) -> Element { ); // mouse_dblclick_div mock_event( - &cx, + cx, "mouse_dblclick_div", r#"new MouseEvent("dblclick", { view: window, @@ -98,7 +98,7 @@ fn app(cx: Scope) -> Element { ); // mouse_down_div mock_event( - &cx, + cx, "mouse_down_div", r#"new MouseEvent("mousedown", { view: window, @@ -110,7 +110,7 @@ fn app(cx: Scope) -> Element { ); // mouse_up_div mock_event( - &cx, + cx, "mouse_up_div", r#"new MouseEvent("mouseup", { view: window, @@ -122,7 +122,7 @@ fn app(cx: Scope) -> Element { ); // wheel_div mock_event( - &cx, + cx, "wheel_div", r#"new WheelEvent("wheel", { view: window, @@ -135,7 +135,7 @@ fn app(cx: Scope) -> Element { ); // key_down_div mock_event( - &cx, + cx, "key_down_div", r#"new KeyboardEvent("keydown", { key: "a", @@ -157,7 +157,7 @@ fn app(cx: Scope) -> Element { ); // key_up_div mock_event( - &cx, + cx, "key_up_div", r#"new KeyboardEvent("keyup", { key: "a", @@ -179,7 +179,7 @@ fn app(cx: Scope) -> Element { ); // key_press_div mock_event( - &cx, + cx, "key_press_div", r#"new KeyboardEvent("keypress", { key: "a", @@ -201,13 +201,13 @@ fn app(cx: Scope) -> Element { ); // focus_in_div mock_event( - &cx, + cx, "focus_in_div", r#"new FocusEvent("focusin", {bubbles: true})"#, ); // focus_out_div mock_event( - &cx, + cx, "focus_out_div", r#"new FocusEvent("focusout",{bubbles: true})"#, ); From 1959da1ec682844c0979f399b4b21512c0f1995c Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sat, 6 May 2023 09:15:09 -0500 Subject: [PATCH 8/8] include desktop tests in test with browser --- Makefile.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index 8ecbe6b2e..6f331b98f 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -42,10 +42,10 @@ private = true [tasks.test] dependencies = ["build"] command = "cargo" -args = ["test", "--lib", "--bins", "--tests", "--examples", "--workspace", "--exclude", "dioxus-router"] +args = ["test", "--lib", "--bins", "--tests", "--examples", "--workspace", "--exclude", "dioxus-router", "--exclude", "dioxus-desktop"] private = true [tasks.test-with-browser] -env = { CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS = ["**/packages/router"] } +env = { CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS = ["**/packages/router", "**/packages/desktop"] } private = true workspace = true