use topcoat::{
context::Cx,
runtime::procedure,
view::{ViewExt, view},
};
#[tokio::test]
async fn toggle_reaches_the_generated_javascript() {
let cx = &Cx::default();
let html = view! {
cx =>
signal open = false;
<button @click=$(|_e| open.toggle())>"x"</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(".toggle()"), "{html}");
}
#[tokio::test]
async fn bool_then_avoids_javascript_thenable_assimilation() {
let cx = &Cx::default();
let html = view! { cx => $(true.then(|| "yes").unwrap()) }
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(".then_("), "{html}");
assert!(!html.contains(".then("), "{html}");
}
#[tokio::test]
async fn increment_and_decrement_reach_the_generated_javascript() {
let cx = &Cx::default();
let html = view! {
cx =>
signal count = 0.0;
<button @click=$(|_e| count.increment())>"+"</button>
<button @click=$(|_e| count.decrement())>"-"</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(".increment()"), "{html}");
assert!(html.contains(".decrement()"), "{html}");
}
#[tokio::test]
async fn push_str_reaches_the_generated_javascript_with_its_argument() {
let cx = &Cx::default();
let html = view! {
cx =>
signal name = String::new();
<button @click=$(|_e| name.push_str("!"))>"x"</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(".push_str("), "{html}");
}
#[procedure]
async fn test_procedure(v: String) -> Result<String, std::convert::Infallible> {
Ok(v)
}
#[tokio::test]
async fn procedure_call_inside_if_is_an_async_func() {
let cx = &Cx::default();
let html = view! {
cx =>
<button
@click=$(async |_e| {
if true {
let _v = test_procedure("hello test".to_owned()).await;
}
})
>
"Test"
</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(
html.contains("(await (async ()"),
"if block containing an await must be an async anonymous function: {html}"
);
}
#[tokio::test]
async fn procedure_call_inside_block_is_an_async_func() {
let cx = &Cx::default();
let html = view! {
cx =>
<button
@click=$(async |_e| {
{
let _v = test_procedure("hello test".to_owned()).await;
}
})
>
"Test"
</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(
html.contains("(await (async ()"),
"block containing an await must be an async anonymous function: {html}"
);
}
#[tokio::test]
async fn push_str_accepts_the_owned_string_from_an_event() {
let cx = &Cx::default();
let html = view! {
cx =>
signal message = String::new();
<input
@input=$(|e: topcoat::runtime::Event| { message.push_str(e.target.value) })
>
}
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(".push_str("), "{html}");
}
#[tokio::test]
async fn a_captured_value_cannot_break_out_of_its_marker_comment() {
let cx = &Cx::default();
let spicy = String::from(r#"-->"<&"#);
let html = view! { cx => <p>$(spicy.to_owned())</p> }
.single()
.await
.unwrap()
.render(cx);
assert!(
html.contains(r"cx.hydrate("-->\"<&")"),
"{html}"
);
assert!(html.contains(r#"-->-->"<&<!--"#), "{html}");
assert!(!html.contains(r#"-->"<&"#), "{html}");
}
#[tokio::test]
async fn a_string_literal_with_quotes_stays_inside_the_handler_attribute() {
let cx = &Cx::default();
let html = view! {
cx =>
signal name = String::new();
<button @click=$(|_e| name.push_str("say \"hi\""))>"x"</button>
}
.single()
.await
.unwrap()
.render(cx);
assert!(html.contains(r"say \"hi\""), "{html}");
assert!(!html.contains(r#"say \"hi"#), "{html}");
}