#![allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
use void_crawl_core::{BrowserSession, CaptchaKind, detect_captcha};
async fn headless_session() -> BrowserSession {
BrowserSession::builder().headless().no_sandbox().launch().await.expect("launch")
}
#[tokio::test]
async fn detects_turnstile_when_runtime_is_loaded_but_widget_absent() {
let session = headless_session().await;
let page = session
.new_page("data:text/html,<html><body>placeholder</body></html>")
.await
.expect("new_page");
let _ = page
.evaluate_js(
r#"(() => {
const s = document.createElement('script');
s.id = 'cf-turnstile-script';
s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
document.head.appendChild(s);
window.turnstile = { render: function(){}, ready: function(){} };
return true;
})()"#,
)
.await
.expect("inject");
let kind = detect_captcha(&page).await.expect("detect_captcha");
assert_eq!(
kind,
Some(CaptchaKind::Turnstile),
"Turnstile runtime was loaded (script + window.turnstile); detector should flag it as a captcha wall even before the widget renders"
);
page.close().await.ok();
session.close().await.ok();
}
#[tokio::test]
async fn does_not_false_positive_on_plain_page() {
let session = headless_session().await;
let page =
session.new_page("data:text/html,<html><body>hello</body></html>").await.expect("new_page");
let kind = detect_captcha(&page).await.expect("detect_captcha");
assert_eq!(kind, None, "plain page should not trip the detector");
page.close().await.ok();
session.close().await.ok();
}