fix(examples): repair html dynamic partial interactions
Preserve data-hemx-revealed through hemx-build and make html_examples lazy/load-more/infinite/search interactions return server-driven partial updates with regression coverage. req: convention/005 req: htmx_equivalents/002 req: examples/001
This commit is contained in:
@@ -498,10 +498,12 @@ mod gallery_handlers {
|
||||
) -> impl IntoEffect {
|
||||
let _ = input.request;
|
||||
let mut count = state.infinite_count.lock().unwrap();
|
||||
let first_new = *count + 1;
|
||||
*count += 3;
|
||||
let rows = loaded_rows(*count)
|
||||
.into_iter()
|
||||
.map(|row| gallery::infinite_row.replace(row))
|
||||
.filter(|row| row.id.0 >= first_new as u64)
|
||||
.map(|row| gallery::infinite_row.append(row))
|
||||
.collect::<Vec<_>>();
|
||||
let mut effects = rows;
|
||||
effects.push(gallery::infinite_status.set(format!("Showing {} rows", *count)));
|
||||
@@ -538,10 +540,12 @@ mod gallery_handlers {
|
||||
) -> impl IntoEffect {
|
||||
let _ = input.request;
|
||||
let mut loaded = state.loaded_count.lock().unwrap();
|
||||
let first_new = *loaded + 1;
|
||||
*loaded += 2;
|
||||
let rows = loaded_rows(*loaded)
|
||||
.into_iter()
|
||||
.map(|row| gallery::loaded_row.replace(row))
|
||||
.filter(|row| row.id.0 >= first_new as u64)
|
||||
.map(|row| gallery::loaded_row.append(row))
|
||||
.collect::<Vec<_>>();
|
||||
let mut effects = rows;
|
||||
effects.push(gallery::load_status.set(format!("Showing {} rows", *loaded)));
|
||||
@@ -554,12 +558,22 @@ mod gallery_handlers {
|
||||
Form(input): Form<SearchInput>,
|
||||
) -> impl IntoEffect {
|
||||
let query = input.query.trim().to_owned();
|
||||
*state.query.lock().unwrap() = query.clone();
|
||||
let results = search_results_for(&query)
|
||||
let previous_query = {
|
||||
let mut stored_query = state.query.lock().unwrap();
|
||||
let previous_query = stored_query.clone();
|
||||
*stored_query = query.clone();
|
||||
previous_query
|
||||
};
|
||||
let previous_results = search_results_for(&previous_query);
|
||||
let mut effects = previous_results
|
||||
.into_iter()
|
||||
.map(|result| gallery::search_result.replace(result))
|
||||
.map(|result| gallery::search_result.remove(result.id.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
let mut effects = results;
|
||||
effects.extend(
|
||||
search_results_for(&query)
|
||||
.into_iter()
|
||||
.map(|result| gallery::search_result.append(result)),
|
||||
);
|
||||
effects.push(gallery::search_status.set(if query.is_empty() {
|
||||
"Showing all results".into()
|
||||
} else {
|
||||
@@ -675,6 +689,17 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn revealed_forms_preserve_data_hemx_revealed_attribute() {
|
||||
// req: convention/005
|
||||
let state = Arc::new(GalleryState::seeded());
|
||||
let html = gallery_view(&state).render().expect("render gallery");
|
||||
assert!(
|
||||
html.contains("data-hemx-revealed=\"true\""),
|
||||
"lazy-load and infinite-scroll forms must preserve data-hemx-revealed attribute"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn readme_maps_every_htmx_example_slug() {
|
||||
let readme = include_str!("../README.md");
|
||||
@@ -782,6 +807,17 @@ mod tests {
|
||||
assert!(lazy.updates_text(gallery::lazy_panel));
|
||||
assert!(lazy.payload_contains("Lazy content loaded"));
|
||||
|
||||
let more = inspect_batch(
|
||||
InteractionRequest::from(form(gallery::load_more, &[("request", "more")]))
|
||||
.dispatch_async(handlers(state.clone()))
|
||||
.await
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(more.payload_contains("Loaded row 3"));
|
||||
assert!(more.payload_contains("Loaded row 4"));
|
||||
assert!(more.updates_text(gallery::load_status));
|
||||
|
||||
let invalid = inspect_batch(
|
||||
InteractionRequest::from(form(gallery::validate_email, &[("email", "bad")]))
|
||||
.dispatch_async(handlers(state.clone()))
|
||||
@@ -792,6 +828,20 @@ mod tests {
|
||||
assert!(invalid.payload_contains("Use a real email address"));
|
||||
assert!(invalid.updates_text(gallery::email_status));
|
||||
|
||||
let valid = inspect_batch(
|
||||
InteractionRequest::from(form(
|
||||
gallery::validate_email,
|
||||
&[("email", "xyz@example.com")],
|
||||
))
|
||||
.dispatch_async(handlers(state.clone()))
|
||||
.await
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(valid.payload_contains("xyz@example.com is valid"));
|
||||
assert!(!valid.payload_contains("Use a real email address"));
|
||||
assert!(valid.updates_text(gallery::email_status));
|
||||
|
||||
let infinite = inspect_batch(
|
||||
InteractionRequest::from(form(gallery::infinite_scroll, &[("request", "more")]))
|
||||
.dispatch_async(handlers(state.clone()))
|
||||
@@ -799,11 +849,8 @@ mod tests {
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(infinite.replaces_keyed_html_containing(
|
||||
gallery::infinite_row,
|
||||
"6",
|
||||
"Loaded row 6"
|
||||
));
|
||||
assert!(infinite.payload_contains("Loaded row 4"));
|
||||
assert!(infinite.payload_contains("Loaded row 6"));
|
||||
|
||||
let progress = inspect_batch(
|
||||
InteractionRequest::from(form(gallery::tick_progress, &[("request", "tick")]))
|
||||
@@ -841,7 +888,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(load.replaces_keyed_html_containing(gallery::loaded_row, "4", "Loaded row 4"));
|
||||
assert!(load.payload_contains("Loaded row 6"));
|
||||
|
||||
let search = inspect_batch(
|
||||
InteractionRequest::from(form(gallery::search, &[("query", "ga")]))
|
||||
@@ -850,7 +897,24 @@ mod tests {
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(search.replaces_keyed_html_containing(gallery::search_result, "3", "Gamma"));
|
||||
assert!(search.removes_key(gallery::search_result, "1"));
|
||||
assert!(search.inserts_html_containing(gallery::search_result, "3", "Gamma"));
|
||||
|
||||
let row_save = inspect_batch(
|
||||
InteractionRequest::from(form(
|
||||
editable_row::save_row,
|
||||
&[("id", "1"), ("title", "Write dynamic HTML")],
|
||||
))
|
||||
.dispatch_async(handlers(state.clone()))
|
||||
.await
|
||||
.unwrap()
|
||||
.batch,
|
||||
);
|
||||
assert!(row_save.replaces_keyed_html_containing(
|
||||
gallery::editable_row,
|
||||
"1",
|
||||
"Write dynamic HTML"
|
||||
));
|
||||
|
||||
let delete = inspect_batch(
|
||||
InteractionRequest::from(form(editable_row::delete_row, &[("id", "1")]))
|
||||
|
||||
Reference in New Issue
Block a user