use std::time::Duration;
use captchaforge::warmup::warm_session;
mod common;
#[tokio::test]
async fn warm_session_emits_only_trusted_events() {
let browser = common::launch_browser().await;
let page = browser.new_page("about:blank").await.unwrap();
let setup: String = page
.evaluate(
r#"(() => {
document.body.innerHTML =
'<h1>warm</h1><p>lorem ipsum dolor sit amet</p>' +
'<a id="lnk">a link</a><button id="b">btn</button>' +
'<div style="height:3000px"></div>';
window.__rec = { move: 0, wheel: 0, untrusted: [] };
const note = (e) => {
if (e.type === 'mousemove') window.__rec.move++;
if (e.type === 'wheel') window.__rec.wheel++;
if (e.isTrusted !== true) window.__rec.untrusted.push(e.type);
};
document.addEventListener('mousemove', note, true);
window.addEventListener('wheel', note, { capture: true, passive: true });
return 'ready';
})()"#,
)
.await
.unwrap()
.into_value()
.unwrap();
assert_eq!(setup, "ready");
warm_session(&page, Duration::from_millis(2500))
.await
.expect("warm_session should succeed on a healthy page");
let rec = page
.evaluate("window.__rec")
.await
.unwrap()
.into_value::<serde_json::Value>()
.unwrap();
let moves = rec["move"].as_u64().unwrap_or(0);
let wheels = rec["wheel"].as_u64().unwrap_or(0);
let untrusted = rec["untrusted"].as_array().cloned().unwrap_or_default();
browser.close().await.unwrap();
assert!(
untrusted.is_empty(),
"warm_session emitted untrusted (isTrusted=false) event(s): {untrusted:?}. \
a synthetic-JS regression; every pointer/scroll must be trusted BiDi input"
);
assert!(
moves > 0,
"warm_session produced no mousemove events (moves={moves}, wheels={wheels}). \
the trusted pointer path is not reaching the page"
);
}
#[tokio::test]
async fn drag_primitives_emit_only_trusted_events() {
let browser = common::launch_browser().await;
let page = browser.new_page("about:blank").await.unwrap();
let setup: String = page
.evaluate(
r#"(() => {
document.body.innerHTML =
'<div id="k" style="position:absolute;left:30px;top:30px;width:60px;height:60px;background:#ccc"></div>';
window.__d = { down: 0, move: 0, up: 0, untrusted: [] };
const note = (e) => {
if (e.type === 'mousedown') window.__d.down++;
if (e.type === 'mousemove') window.__d.move++;
if (e.type === 'mouseup') window.__d.up++;
if (e.isTrusted !== true) window.__d.untrusted.push(e.type);
};
for (const t of ['mousedown', 'mousemove', 'mouseup']) {
document.addEventListener(t, note, true);
}
return 'ready';
})()"#,
)
.await
.unwrap()
.into_value()
.unwrap();
assert_eq!(setup, "ready");
page.mouse_down(50.0, 50.0).await.unwrap();
for i in 1..=10 {
page.move_mouse_to(50.0 + i as f64 * 8.0, 50.0)
.await
.unwrap();
}
page.mouse_up(130.0, 50.0).await.unwrap();
let d = page
.evaluate("window.__d")
.await
.unwrap()
.into_value::<serde_json::Value>()
.unwrap();
browser.close().await.unwrap();
let untrusted = d["untrusted"].as_array().cloned().unwrap_or_default();
assert!(
untrusted.is_empty(),
"drag primitives emitted untrusted event(s): {untrusted:?}, slider drag must be trusted BiDi input"
);
assert!(
d["down"].as_u64().unwrap_or(0) >= 1,
"no trusted mousedown delivered"
);
assert!(
d["move"].as_u64().unwrap_or(0) >= 1,
"no trusted mousemove delivered"
);
assert!(
d["up"].as_u64().unwrap_or(0) >= 1,
"no trusted mouseup delivered"
);
}