dioxus/packages/desktop/headless_tests/events.rs

555 lines
16 KiB
Rust

use std::{collections::HashMap, ops::Deref};
use dioxus::html::geometry::euclid::Vector3D;
use dioxus::prelude::*;
use dioxus_core::prelude::consume_context;
use dioxus_desktop::DesktopContext;
#[path = "./utils.rs"]
mod utils;
pub fn main() {
utils::check_app_exits(app);
}
static RECEIVED_EVENTS: GlobalSignal<usize> = Signal::global(|| 0);
fn app() -> Element {
let desktop_context: DesktopContext = consume_context();
let received = RECEIVED_EVENTS();
let expected = utils::EXPECTED_EVENTS();
use_effect(move || {
println!("expecting {} events", utils::EXPECTED_EVENTS());
});
if expected != 0 && received == expected {
println!("all events recieved");
desktop_context.close();
}
rsx! {
div {
test_mounted {}
test_button {}
test_mouse_move_div {}
test_mouse_click_div {}
test_mouse_dblclick_div {}
test_mouse_down_div {}
test_mouse_up_div {}
test_mouse_scroll_div {}
test_key_down_div {}
test_key_up_div {}
test_key_press_div {}
test_focus_in_div {}
test_focus_out_div {}
test_form_input {}
test_form_submit {}
test_select_multiple_options {}
}
}
}
fn test_mounted() -> Element {
use_hook(|| utils::EXPECTED_EVENTS.with_mut(|x| *x += 1));
rsx! {
div {
width: "100px",
height: "100px",
onmounted: move |evt| async move {
let rect = evt.get_client_rect().await.unwrap();
println!("rect: {:?}", rect);
assert_eq!(rect.width(), 100.0);
assert_eq!(rect.height(), 100.0);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_button() -> Element {
utils::mock_event(
"button",
r#"new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
button: 0,
})"#,
);
rsx! {
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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_move_div() -> Element {
utils::mock_event(
"mouse_move_div",
r#"new MouseEvent("mousemove", {
view: window,
bubbles: true,
cancelable: true,
buttons: 2,
})"#,
);
rsx! {
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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_click_div() -> Element {
utils::mock_event(
"mouse_click_div",
r#"new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
buttons: 2,
button: 2,
})"#,
);
rsx! {
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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_dblclick_div() -> Element {
utils::mock_event(
"mouse_dblclick_div",
r#"new MouseEvent("dblclick", {
view: window,
bubbles: true,
cancelable: true,
buttons: 1|2,
button: 2,
})"#,
);
rsx! {
div {
id: "mouse_dblclick_div",
ondoubleclick: 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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_down_div() -> Element {
utils::mock_event(
"mouse_down_div",
r#"new MouseEvent("mousedown", {
view: window,
bubbles: true,
cancelable: true,
buttons: 2,
button: 2,
})"#,
);
rsx! {
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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_up_div() -> Element {
utils::mock_event(
"mouse_up_div",
r#"new MouseEvent("mouseup", {
view: window,
bubbles: true,
cancelable: true,
buttons: 0,
button: 0,
})"#,
);
rsx! {
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),
);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_mouse_scroll_div() -> Element {
utils::mock_event(
"wheel_div",
r#"new WheelEvent("wheel", {
view: window,
deltaX: 1.0,
deltaY: 2.0,
deltaZ: 3.0,
deltaMode: 0x00,
bubbles: true,
})"#,
);
rsx! {
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 {
panic!("Expected delta to be in pixels") };
assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0));
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_key_down_div() -> Element {
utils::mock_event(
"key_down_div",
r#"new KeyboardEvent("keydown", {
key: "a",
code: "KeyA",
location: 0,
repeat: true,
keyCode: 65,
charCode: 97,
char: "a",
charCode: 0,
altKey: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
isComposing: true,
which: 65,
bubbles: true,
})"#,
);
rsx! {
input {
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(), Location::Standard);
assert!(event.data.is_auto_repeating());
assert!(event.data.is_composing());
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_key_up_div() -> Element {
utils::mock_event(
"key_up_div",
r#"new KeyboardEvent("keyup", {
key: "a",
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,
})"#,
);
rsx! {
input {
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(), Location::Standard);
assert!(!event.data.is_auto_repeating());
assert!(!event.data.is_composing());
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_key_press_div() -> Element {
utils::mock_event(
"key_press_div",
r#"new KeyboardEvent("keypress", {
key: "a",
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,
})"#,
);
rsx! {
input {
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(), Location::Standard);
assert!(!event.data.is_auto_repeating());
assert!(!event.data.is_composing());
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_focus_in_div() -> Element {
utils::mock_event(
"focus_in_div",
r#"new FocusEvent("focusin", {bubbles: true})"#,
);
rsx! {
input {
id: "focus_in_div",
onfocusin: move |event| {
println!("{:?}", event.data);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_focus_out_div() -> Element {
utils::mock_event(
"focus_out_div",
r#"new FocusEvent("focusout",{bubbles: true})"#,
);
rsx! {
input {
id: "focus_out_div",
onfocusout: move |event| {
println!("{:?}", event.data);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
}
}
}
}
fn test_form_input() -> Element {
let mut values = use_signal(HashMap::new);
utils::mock_event_with_extra(
"form-username",
r#"new Event("input", { bubbles: true, cancelable: true, composed: true })"#,
r#"element.value = "hello";"#,
);
let set_username = move |ev: FormEvent| {
values.set(ev.values());
// The value of the input should match
assert_eq!(ev.value(), "hello");
// And then the value the form gives us should also match
values.with_mut(|x| {
assert_eq!(x.get("username").unwrap().deref(), "hello");
assert_eq!(x.get("full-name").unwrap().deref(), "lorem");
assert_eq!(x.get("password").unwrap().deref(), "ipsum");
assert_eq!(x.get("color").unwrap().deref(), "red");
});
RECEIVED_EVENTS.with_mut(|x| *x += 1);
};
rsx! {
div {
h1 { "Form" }
form {
id: "form",
oninput: move |ev| {
values.set(ev.values());
},
onsubmit: move |ev| {
println!("{:?}", ev);
},
input {
r#type: "text",
name: "username",
id: "form-username",
oninput: set_username,
}
input { r#type: "text", name: "full-name", value: "lorem" }
input { r#type: "password", name: "password", value: "ipsum" }
input { r#type: "radio", name: "color", value: "red", checked: true }
input { r#type: "radio", name: "color", value: "blue" }
button { r#type: "submit", value: "Submit", "Submit the form" }
}
}
}
}
fn test_form_submit() -> Element {
let mut values = use_signal(HashMap::new);
utils::mock_event_with_extra(
"form-submitter",
r#"new Event("submit", { bubbles: true, cancelable: true, composed: true })"#,
r#"element.submit();"#,
);
let set_values = move |ev: FormEvent| {
values.set(ev.values());
values.with_mut(|x| {
assert_eq!(x.get("username").unwrap().deref(), "goodbye");
assert_eq!(x.get("full-name").unwrap().deref(), "lorem");
assert_eq!(x.get("password").unwrap().deref(), "ipsum");
assert_eq!(x.get("color").unwrap().deref(), "red");
});
RECEIVED_EVENTS.with_mut(|x| *x += 1);
};
rsx! {
div {
h1 { "Form" }
form {
id: "form-submitter",
onsubmit: set_values,
input { r#type: "text", name: "username", id: "username", value: "goodbye" }
input { r#type: "text", name: "full-name", value: "lorem" }
input { r#type: "password", name: "password", value: "ipsum" }
input { r#type: "radio", name: "color", value: "red", checked: true }
input { r#type: "radio", name: "color", value: "blue" }
button { r#type: "submit", value: "Submit", "Submit the form" }
}
}
}
}
fn test_select_multiple_options() -> Element {
utils::mock_event_with_extra(
"select-many",
r#"new Event("input", { bubbles: true, cancelable: true, composed: true })"#,
r#"
document.getElementById('usa').selected = true;
document.getElementById('canada').selected = true;
document.getElementById('mexico').selected = false;
"#,
);
rsx! {
select {
id: "select-many",
name: "country",
multiple: true,
oninput: move |ev| {
let values = ev.value();
let values = values.split(',').collect::<Vec<_>>();
assert_eq!(values, vec!["usa", "canada"]);
RECEIVED_EVENTS.with_mut(|x| *x += 1);
},
option { id: "usa", value: "usa", "USA" }
option { id: "canada", value: "canada", "Canada" }
option { id: "mexico", value: "mexico", selected: true, "Mexico" }
}
}
}