use std::{cell::RefCell, rc::Rc};
use crate::{self as vertigo, dom};
use crate::{
DomNode, Value,
dev::command::DriverDomCommand,
driver_module::{driver::get_driver, get_driver_dom},
exports::mount,
reactive::on_after_transaction,
};
fn app_with_a_binding_built_before_the_root() -> DomNode {
let title = Value::new("a title".to_string());
let label = Value::new("a label".to_string());
let header = dom! { <div>{label}</div> };
dom! {
<html>
<head>
<title>{title}</title>
</head>
<body>
<div>{header}</div>
</body>
</html>
}
}
fn mount_capturing_batches(init_app: impl FnOnce() -> DomNode) -> Vec<Vec<DriverDomCommand>> {
let pending: Rc<RefCell<Vec<DriverDomCommand>>> = Rc::new(RefCell::new(Vec::new()));
let batches: Rc<RefCell<Vec<Vec<DriverDomCommand>>>> = Rc::new(RefCell::new(Vec::new()));
let _tee = get_driver_dom().inspect_command({
let pending = pending.clone();
move |command| pending.borrow_mut().push(command)
});
let _cut = on_after_transaction({
let pending = pending.clone();
let batches = batches.clone();
move || {
let batch = pending.borrow_mut().drain(..).collect::<Vec<_>>();
if !batch.is_empty() {
batches.borrow_mut().push(batch);
}
}
});
mount(init_app);
let tail = pending.borrow_mut().drain(..).collect::<Vec<_>>();
if !tail.is_empty() {
batches.borrow_mut().push(tail);
}
drop(get_driver().take_root());
batches.borrow().clone()
}
#[test]
fn mount_emits_a_single_batch() {
let batches = mount_capturing_batches(app_with_a_binding_built_before_the_root);
assert_eq!(
batches.len(),
1,
"the mount should reach the browser as one batch - hydration only ever sees the first \
one, so a second means the rest of the tree is never matched"
);
}
#[test]
fn first_batch_contains_the_document_roots() {
let batches = mount_capturing_batches(app_with_a_binding_built_before_the_root);
let Some(first) = batches.first() else {
panic!("the mount should emit some commands");
};
let created: Vec<u64> = first
.iter()
.filter_map(|command| match command {
DriverDomCommand::CreateNode { id, .. } => Some(id.to_u64()),
_ => None,
})
.collect();
for (id, name) in [(1, "html"), (2, "head"), (3, "body")] {
assert!(
created.contains(&id),
"<{name}> (id {id}) should be in the first batch, got {created:?}"
);
}
}