add rendering tests

This commit is contained in:
Evan Almloff 2023-05-04 11:04:06 -05:00
parent 70687748d3
commit 1b199977d1
4 changed files with 118 additions and 33 deletions

View file

@ -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
name = "check_rendering"
path = "headless_tests/rendering.rs"
harness = false

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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<String> {
let value: &UseRef<Option<String>> = 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#"<div id="5" style="width: 100px; height: 100px; color: rgb(0, 0, 0);"><input type="checkbox"><h1>text</h1><div><p>hello world</p></div></div>"#;
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: "<p>hello world</p>",
}
};
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
}
}
}
}