feat(wasm): suppress stale client completions

req: client_local/011\nreq: client_local/012\nreq: operations/003
This commit is contained in:
slhx agent
2026-07-13 13:17:58 +02:00
parent ac525fe572
commit dd5ea0827f
6 changed files with 146 additions and 7 deletions
+84 -3
View File
@@ -15,6 +15,7 @@ const STARTUP_TIMEOUT: Duration = Duration::from_secs(12);
#[tokio::test]
async fn client_handler_applies_effect_batch_without_network() -> WebDriverResult<()> {
// req: client_local/005 req: client_local/009 req: client_local/010
// req: client_local/011 req: client_local/012
// test: client_local/014
let workspace = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
@@ -45,11 +46,47 @@ async fn client_handler_applies_effect_batch_without_network() -> WebDriverResul
)
.await?;
let network_before = resource_count(&driver).await?;
driver
.execute(
r#"
window.__resolveClientRuns = [];
const actual = window.hemx.registerClientHandler('increment', (...args) => new Promise((resolve) => {
window.__resolveClientRuns.push(() => resolve(actual(...args)));
}));
window.__actualClientHandler = actual;
return true;
"#,
Vec::new(),
)
.await?;
let button = driver
.find(By::Css("[data-hemx-client='increment']"))
.await?
.click()
.await?;
button.click().await?;
button.click().await?;
wait_until(&driver, "return window.__resolveClientRuns.length === 2").await?;
driver
.execute(
"window.__resolveClientRuns[0](); return true",
Vec::new(),
)
.await?;
tokio::time::sleep(Duration::from_millis(100)).await;
assert_eq!(
driver
.find(By::Css("[data-sid]"))
.await?
.prop("textContent")
.await?
.unwrap_or_default(),
"idle",
"superseded completion applied stale effects"
);
driver
.execute(
"window.__resolveClientRuns[1](); return true",
Vec::new(),
)
.await?;
wait_until(
&driver,
@@ -63,6 +100,12 @@ async fn client_handler_applies_effect_batch_without_network() -> WebDriverResul
"client handler made a network request"
);
driver
.execute(
"window.hemx.registerClientHandler('increment', window.__actualClientHandler); return true",
Vec::new(),
)
.await?;
driver
.execute(
"document.querySelector('[data-hemx-root]').setAttribute('data-hemx-client-state-version', '2'); return true",
@@ -102,6 +145,44 @@ async fn client_handler_applies_effect_batch_without_network() -> WebDriverResul
.unwrap_or(false),
"invalid input must restore pending UI"
);
driver
.execute(
r#"
window.__resolveUnmount = null;
const actual = window.hemx.registerClientHandler('increment', (...args) => new Promise((resolve) => {
window.__resolveUnmount = () => resolve(actual(...args));
}));
document.querySelector('[data-hemx-root]').setAttribute('data-hemx-client-state-version', '1');
return true;
"#,
Vec::new(),
)
.await?;
driver
.find(By::Css("[data-hemx-client='increment']"))
.await?
.click()
.await?;
driver
.execute(
"const root = document.querySelector('[data-hemx-root]'); window.__removedRoot = root; root.remove(); window.__resolveUnmount(); return true",
Vec::new(),
)
.await?;
tokio::time::sleep(Duration::from_millis(100)).await;
assert!(
driver
.execute(
"return !window.__removedRoot.textContent.includes('updated by Rust/WASM')",
Vec::new(),
)
.await?
.json()
.as_bool()
.unwrap_or(false),
"unmounted root accepted a late effect"
);
Ok::<(), WebDriverError>(())
}
.await;