update wasm-bindgen testing approaches
This commit is contained in:
parent
88ab9693db
commit
c360f0ed0d
|
@ -18,3 +18,4 @@ console_error_panic_hook = "0.1.7"
|
|||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
web-sys = "0.3"
|
||||
gloo-timers = { version = "0.3", features = ["futures"] }
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
use counter::*;
|
||||
use leptos::*;
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
use leptos::mount::mount_to;
|
||||
use leptos::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn clear() {
|
||||
let document = leptos::document();
|
||||
async fn clear() {
|
||||
let document = document();
|
||||
let test_wrapper = document.create_element("section").unwrap();
|
||||
let _ = document.body().unwrap().append_child(&test_wrapper);
|
||||
|
||||
// start by rendering our counter and mounting it to the DOM
|
||||
// note that we start at the initial value of 10
|
||||
mount_to(
|
||||
let _dispose = mount_to(
|
||||
test_wrapper.clone().unchecked_into(),
|
||||
|| view! { <SimpleCounter initial_value=10 step=1/> },
|
||||
);
|
||||
|
@ -30,16 +32,17 @@ fn clear() {
|
|||
// now let's click the `clear` button
|
||||
clear.click();
|
||||
|
||||
// the reactive system is built on top of the async system, so changes are not reflected
|
||||
// synchronously in the DOM
|
||||
// in order to detect the changes here, we'll just yield for a brief time after each change,
|
||||
// allowing the effects that update the view to run
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
// now let's test the <div> against the expected value
|
||||
// we can do this by testing its `outerHTML`
|
||||
let runtime = create_runtime();
|
||||
assert_eq!(
|
||||
div.outer_html(),
|
||||
// here we spawn a mini reactive system, just to render the
|
||||
// test case
|
||||
{
|
||||
assert_eq!(div.outer_html(), {
|
||||
// it's as if we're creating it with a value of 0, right?
|
||||
let (value, _set_value) = create_signal(0);
|
||||
let (value, _set_value) = signal(0);
|
||||
|
||||
// we can remove the event listeners because they're not rendered to HTML
|
||||
view! {
|
||||
|
@ -50,39 +53,42 @@ fn clear() {
|
|||
<button>"+1"</button>
|
||||
</div>
|
||||
}
|
||||
// the view returned an HtmlElement<Div>, which is a smart pointer for
|
||||
// a DOM element. So we can still just call .outer_html()
|
||||
// Leptos supports multiple backend renderers for HTML elements
|
||||
// .into_view() here is just a convenient way of specifying "use the regular DOM renderer"
|
||||
.into_view()
|
||||
// views are lazy -- they describe a DOM tree but don't create it yet
|
||||
// calling .build() will actually build the DOM elements
|
||||
.build()
|
||||
// .build() returned an ElementState, which is a smart pointer for
|
||||
// a DOM element. So we can still just call .outer_html(), which access the outerHTML on
|
||||
// the actual DOM element
|
||||
.outer_html()
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// There's actually an easier way to do this...
|
||||
// We can just test against a <SimpleCounter/> with the initial value 0
|
||||
assert_eq!(test_wrapper.inner_html(), {
|
||||
let comparison_wrapper = document.create_element("section").unwrap();
|
||||
leptos::mount_to(
|
||||
let _dispose = mount_to(
|
||||
comparison_wrapper.clone().unchecked_into(),
|
||||
|| view! { <SimpleCounter initial_value=0 step=1/>},
|
||||
);
|
||||
comparison_wrapper.inner_html()
|
||||
});
|
||||
|
||||
runtime.dispose();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn inc() {
|
||||
let document = leptos::document();
|
||||
async fn inc() {
|
||||
let document = document();
|
||||
let test_wrapper = document.create_element("section").unwrap();
|
||||
let _ = document.body().unwrap().append_child(&test_wrapper);
|
||||
|
||||
mount_to(
|
||||
let _dispose = mount_to(
|
||||
test_wrapper.clone().unchecked_into(),
|
||||
|| view! { <SimpleCounter initial_value=0 step=1/> },
|
||||
);
|
||||
|
||||
// You can do testing with vanilla DOM operations
|
||||
let _document = leptos::document();
|
||||
let div = test_wrapper.query_selector("div").unwrap().unwrap();
|
||||
let clear = div
|
||||
.first_child()
|
||||
|
@ -108,6 +114,8 @@ fn inc() {
|
|||
inc.click();
|
||||
inc.click();
|
||||
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(text.text_content(), Some("Value: 2!".to_string()));
|
||||
|
||||
dec.click();
|
||||
|
@ -115,19 +123,21 @@ fn inc() {
|
|||
dec.click();
|
||||
dec.click();
|
||||
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(text.text_content(), Some("Value: -2!".to_string()));
|
||||
|
||||
clear.click();
|
||||
|
||||
assert_eq!(text.text_content(), Some("Value: 0!".to_string()));
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
let runtime = create_runtime();
|
||||
assert_eq!(text.text_content(), Some("Value: 0!".to_string()));
|
||||
|
||||
// Or you can test against a sample view!
|
||||
assert_eq!(
|
||||
div.outer_html(),
|
||||
{
|
||||
let (value, _) = create_signal(0);
|
||||
let (value, _) = signal(0);
|
||||
view! {
|
||||
<div>
|
||||
<button>"Clear"</button>
|
||||
|
@ -137,16 +147,20 @@ fn inc() {
|
|||
</div>
|
||||
}
|
||||
}
|
||||
.into_view()
|
||||
.build()
|
||||
.outer_html()
|
||||
);
|
||||
|
||||
inc.click();
|
||||
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(
|
||||
div.outer_html(),
|
||||
{
|
||||
// because we've clicked, it's as if the signal is starting at 1
|
||||
let (value, _) = create_signal(1);
|
||||
let (value, _) = signal(1);
|
||||
view! {
|
||||
<div>
|
||||
<button>"Clear"</button>
|
||||
|
@ -156,8 +170,8 @@ fn inc() {
|
|||
</div>
|
||||
}
|
||||
}
|
||||
.into_view()
|
||||
.build()
|
||||
.outer_html()
|
||||
);
|
||||
|
||||
runtime.dispose();
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ lto = true
|
|||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos" }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -19,6 +17,7 @@ wasm-bindgen = "0.2"
|
|||
wasm-bindgen-test = "0.3.34"
|
||||
pretty_assertions = "1.3.0"
|
||||
rstest = "0.17.0"
|
||||
gloo-timers = { version = "0.3", features = ["futures"] }
|
||||
|
||||
[dev-dependencies.web-sys]
|
||||
features = ["HtmlElement", "XPathResult"]
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use counter_without_macros::counter;
|
||||
use leptos::*;
|
||||
|
||||
/// Show the counter
|
||||
pub fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
console_error_panic_hook::set_once();
|
||||
mount::mount_to_body(|| counter(0, 1))
|
||||
leptos::mount::mount_to_body(|| counter(0, 1))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use counter_without_macros::counter;
|
||||
use leptos::*;
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
use leptos::prelude::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_test::*;
|
||||
|
@ -8,27 +9,32 @@ use web_sys::HtmlElement;
|
|||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn should_increment_counter() {
|
||||
async fn should_increment_counter() {
|
||||
open_counter();
|
||||
|
||||
click_increment();
|
||||
click_increment();
|
||||
|
||||
// reactive changes run asynchronously, so yield briefly before observing the DOM
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(see_text(), Some("Value: 2!".to_string()));
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn should_decrement_counter() {
|
||||
async fn should_decrement_counter() {
|
||||
open_counter();
|
||||
|
||||
click_decrement();
|
||||
click_decrement();
|
||||
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(see_text(), Some("Value: -2!".to_string()));
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn should_clear_counter() {
|
||||
async fn should_clear_counter() {
|
||||
open_counter();
|
||||
|
||||
click_increment();
|
||||
|
@ -36,18 +42,18 @@ fn should_clear_counter() {
|
|||
|
||||
click_clear();
|
||||
|
||||
TimeoutFuture::new(10).await;
|
||||
|
||||
assert_eq!(see_text(), Some("Value: 0!".to_string()));
|
||||
}
|
||||
|
||||
fn open_counter() {
|
||||
remove_existing_counter();
|
||||
mount_to_body(move || counter(0, 1));
|
||||
leptos::mount::mount_to_body(move || counter(0, 1));
|
||||
}
|
||||
|
||||
fn remove_existing_counter() {
|
||||
if let Some(counter) =
|
||||
leptos::document().query_selector("body div").unwrap()
|
||||
{
|
||||
if let Some(counter) = document().query_selector("body div").unwrap() {
|
||||
counter.remove();
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +80,7 @@ fn see_text() -> Option<String> {
|
|||
|
||||
fn find_by_text(text: &str) -> HtmlElement {
|
||||
let xpath = format!("//*[text()='{}']", text);
|
||||
let document = leptos::document();
|
||||
let document = document();
|
||||
document
|
||||
.evaluate(&xpath, &document)
|
||||
.unwrap()
|
||||
|
|
|
@ -12,7 +12,7 @@ use const_str_slice_concat::{
|
|||
const_concat, const_concat_with_prefix, str_from_buffer,
|
||||
};
|
||||
use next_tuple::NextTuple;
|
||||
use std::marker::PhantomData;
|
||||
use std::{marker::PhantomData, ops::Deref};
|
||||
|
||||
mod custom;
|
||||
mod elements;
|
||||
|
@ -413,6 +413,14 @@ pub struct ElementState<At, Ch, R: Renderer> {
|
|||
rndr: PhantomData<R>,
|
||||
}
|
||||
|
||||
impl<At, Ch, R: Renderer> Deref for ElementState<At, Ch, R> {
|
||||
type Target = R::Element;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.el
|
||||
}
|
||||
}
|
||||
|
||||
impl<At, Ch, R> Mountable<R> for ElementState<At, Ch, R>
|
||||
where
|
||||
R: Renderer,
|
||||
|
|
Loading…
Reference in New Issue