dioxus/packages/rsx_interpreter/tests/render.rs
2022-06-17 15:15:02 -05:00

353 lines
9.7 KiB
Rust

use dioxus_core::prelude::*;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
use dioxus_rsx_interpreter::{
captuered_context::{CapturedContext, FormattedArg, IfmtArgs},
CodeLocation,
};
#[test]
#[allow(non_snake_case)]
fn render_basic() {
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let static_vnodes = rsx!(div{"hello world"});
let location = CodeLocation {
file: String::new(),
line: 0,
column: 0,
};
let empty_context = CapturedContext {
captured: IfmtArgs {
named_args: Vec::new(),
},
components: Vec::new(),
iterators: Vec::new(),
expressions: Vec::new(),
listeners: Vec::new(),
location: location.clone(),
};
let interperted_vnodes = LazyNodes::new(|factory| {
dioxus_rsx_interpreter::resolve_scope(
location,
"div{\"hello world\"}",
empty_context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
#[test]
#[allow(non_snake_case)]
fn render_nested() {
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let static_vnodes = rsx! {
div {
p { "hello world" }
div {
p { "hello world" }
}
}
};
let location = CodeLocation {
file: String::new(),
line: 1,
column: 0,
};
let empty_context = CapturedContext {
captured: IfmtArgs {
named_args: Vec::new(),
},
components: Vec::new(),
iterators: Vec::new(),
expressions: Vec::new(),
listeners: Vec::new(),
location: location.clone(),
};
let interperted_vnodes = LazyNodes::new(|factory| {
dioxus_rsx_interpreter::resolve_scope(
location,
r#"div {
p { "hello world" }
div {
p { "hello world" }
}
}"#,
empty_context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
#[test]
#[allow(non_snake_case)]
fn render_component() {
fn Comp(cx: Scope) -> Element {
rsx!(cx, div {})
}
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let static_vnodes = rsx! {
div {
Comp {}
}
};
let location = CodeLocation {
file: String::new(),
line: 2,
column: 0,
};
let interperted_vnodes = LazyNodes::new(|factory| {
let context = CapturedContext {
captured: IfmtArgs {
named_args: Vec::new(),
},
components: vec![(
r#"__cx.component(Comp, fc_to_builder(Comp).build(), None, "Comp")"#,
factory.component(Comp, (), None, "Comp"),
)],
iterators: Vec::new(),
expressions: Vec::new(),
listeners: Vec::new(),
location: location.clone(),
};
dioxus_rsx_interpreter::resolve_scope(
location,
r#"div {
Comp {}
}"#,
context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
println!("{:#?}", interperted_vnodes);
println!("{:#?}", static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
#[test]
#[allow(non_snake_case)]
fn render_iterator() {
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let iter = (0..10).map(|i| dom.render_vnodes(rsx! {"{i}"}));
let static_vnodes = rsx! {
div {
iter
}
};
let location = CodeLocation {
file: String::new(),
line: 3,
column: 0,
};
let interperted_vnodes = LazyNodes::new(|factory| {
let context = CapturedContext {
captured: IfmtArgs {
named_args: Vec::new(),
},
components: Vec::new(),
iterators: vec![(
r#"
(0..10).map(|i| dom.render_vnodes(rsx!{"{i}"}))"#,
factory.fragment_from_iter((0..10).map(|i| factory.text(format_args!("{i}")))),
)],
expressions: Vec::new(),
listeners: Vec::new(),
location: location.clone(),
};
dioxus_rsx_interpreter::resolve_scope(
location,
r#"div {
(0..10).map(|i| dom.render_vnodes(rsx!{"{i}"}))
}"#,
context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
println!("{:#?}", interperted_vnodes);
println!("{:#?}", static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
#[test]
#[allow(non_snake_case)]
fn render_captured_variable() {
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let x = 10;
let static_vnodes = rsx! {
div {
"{x}"
}
};
let location = CodeLocation {
file: String::new(),
line: 4,
column: 0,
};
let interperted_vnodes = LazyNodes::new(|factory| {
let context = CapturedContext {
captured: IfmtArgs {
named_args: vec![FormattedArg {
expr: "x",
format_args: "",
result: x.to_string(),
}],
},
components: Vec::new(),
iterators: Vec::new(),
expressions: Vec::new(),
listeners: Vec::new(),
location: location.clone(),
};
dioxus_rsx_interpreter::resolve_scope(
location,
r#"div {
"{x}"
}"#,
context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
println!("{:#?}", interperted_vnodes);
println!("{:#?}", static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
#[test]
#[allow(non_snake_case)]
fn render_listener() {
fn Base(cx: Scope) -> Element {
rsx!(cx, div {})
}
let dom = VirtualDom::new(Base);
let static_vnodes = rsx! {
div {
onclick: |_| println!("clicked")
}
};
let location = CodeLocation {
file: String::new(),
line: 5,
column: 0,
};
let interperted_vnodes = LazyNodes::new(|factory| {
let f = |_| println!("clicked");
let f = factory.bump().alloc(f);
let context = CapturedContext {
captured: IfmtArgs {
named_args: Vec::new(),
},
components: Vec::new(),
iterators: Vec::new(),
expressions: Vec::new(),
listeners: vec![(
r#"dioxus_elements::on::onclick(__cx, |_| println!("clicked"))"#,
dioxus_elements::on::onclick(factory, f),
)],
location: location.clone(),
};
dioxus_rsx_interpreter::resolve_scope(
location,
r#"div {
onclick: |_| println!("clicked")
}"#,
context,
factory,
)
});
let interperted_vnodes = dom.render_vnodes(interperted_vnodes);
let static_vnodes = dom.render_vnodes(static_vnodes);
println!("{:#?}", interperted_vnodes);
println!("{:#?}", static_vnodes);
assert!(check_eq(interperted_vnodes, static_vnodes));
}
fn check_eq<'a>(a: &'a VNode<'a>, b: &'a VNode<'a>) -> bool {
match (a, b) {
(VNode::Text(t_a), VNode::Text(t_b)) => t_a.text == t_b.text,
(VNode::Element(e_a), VNode::Element(e_b)) => {
e_a.attributes
.iter()
.zip(e_b.attributes.iter())
.all(|(a, b)| {
a.is_static == b.is_static
&& a.is_volatile == b.is_volatile
&& a.name == b.name
&& a.value == b.value
&& a.namespace == b.namespace
})
&& e_a
.children
.iter()
.zip(e_b.children.iter())
.all(|(a, b)| check_eq(a, b))
&& e_a.key == e_b.key
&& e_a.tag == e_b.tag
&& e_a.namespace == e_b.namespace
&& e_a
.listeners
.iter()
.zip(e_b.listeners.iter())
.all(|(a, b)| a.event == b.event)
}
(VNode::Fragment(f_a), VNode::Fragment(f_b)) => {
f_a.key == f_b.key
&& f_a
.children
.iter()
.zip(f_b.children.iter())
.all(|(a, b)| check_eq(a, b))
}
(VNode::Component(c_a), VNode::Component(c_b)) => {
c_a.can_memoize == c_b.can_memoize
&& c_a.key == c_b.key
&& c_a.fn_name == c_b.fn_name
&& c_a.user_fc == c_b.user_fc
}
(VNode::Placeholder(_), VNode::Placeholder(_)) => true,
_ => false,
}
}