test(v0): prove dynamic reusable row updates

Use one TodoRow projection for initial render and generated dynamic Vec<IntoEffect> row replacement batches, keeping the normal path on generated helpers instead of raw effects or registry plumbing.

req: canonical_authoring/003
This commit is contained in:
slhx agent
2026-06-12 14:43:47 +02:00
parent d0dc9729fd
commit 3b5de85319
+52 -7
View File
@@ -427,16 +427,30 @@ fn todos_view(todos: &[TodoRecord]) -> Todos {
// req: html_safety/002 req: view/001 req: canonical_authoring/003 // req: html_safety/002 req: view/001 req: canonical_authoring/003
Todos { Todos {
summary: todo_summary(todos), summary: todo_summary(todos),
rows: todos rows: todo_rows(todos),
.iter()
.map(|todo| TodoRow {
id: TodoId(todo.id),
title: todo.title.clone(),
})
.collect(),
} }
} }
#[cfg(test)]
fn refresh_todo_rows_effect(todos: &[TodoRecord]) -> impl IntoEffect {
// req: canonical_authoring/003
let row_updates = todo_rows(todos)
.into_iter()
.map(|row| todos::todo_row.replace(row))
.collect::<Vec<_>>();
(row_updates, todos::summary.set(todo_summary(todos)))
}
fn todo_rows(todos: &[TodoRecord]) -> Vec<TodoRow> {
todos
.iter()
.map(|todo| TodoRow {
id: TodoId(todo.id),
title: todo.title.clone(),
})
.collect()
}
fn todo_summary(todos: &[TodoRecord]) -> String { fn todo_summary(todos: &[TodoRecord]) -> String {
match todos.len() { match todos.len() {
0 => "No todos".to_owned(), 0 => "No todos".to_owned(),
@@ -587,6 +601,37 @@ mod tests {
.is_none()); .is_none());
} }
// req: canonical_authoring/003 req: test/005
#[test]
fn reusable_todo_partial_supports_dynamic_replace_batches() {
let todos = vec![
TodoRecord {
id: 7,
title: "Ship v0".to_owned(),
},
TodoRecord {
id: 8,
title: "Write docs".to_owned(),
},
];
let initial = ui::page(&todos_view(&todos));
let document = Html::parse_fragment(initial.as_str());
assert_eq!(
document
.select(&selector(&keyed_items_selector("li")))
.count(),
2
);
let refresh =
inspect_batch(refresh_todo_rows_effect(&todos).into_batch(ui::BUILD_FINGERPRINT));
assert_eq!(refresh.op_count(), 3);
assert!(refresh.replaces_keyed_html_containing(todos::todo_row, "7", "Ship v0"));
assert!(refresh.replaces_keyed_html_containing(todos::todo_row, "8", "Write docs"));
assert!(refresh.updates_text(todos::summary));
}
// req: html_safety/002 req: view/001 req: test/005 // req: html_safety/002 req: view/001 req: test/005
#[test] #[test]
fn empty_todos_payload_is_rendered_by_a_hemplate_view() { fn empty_todos_payload_is_rendered_by_a_hemplate_view() {