#![cfg(feature = "cloudflare-tests")]
#![allow(clippy::panic, clippy::unwrap_used)]
use serial_test::serial;
use std::time::Duration;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
use zendriver::stealth::StealthProfile;
use zendriver::{Browser, ClearanceOutcome};
const INVISIBLE_TURNSTILE_HTML: &str = r#"<!doctype html>
<html><head><meta charset="utf-8"><title>invisible-turnstile-demo</title></head>
<body>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="1x00000000000000000000AA"></div>
</body></html>"#;
#[tokio::test]
#[serial]
async fn cloudflare_bypass_acquires_token_from_invisible_turnstile() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/"))
.respond_with(
ResponseTemplate::new(200).set_body_raw(INVISIBLE_TURNSTILE_HTML, "text/html"),
)
.mount(&server)
.await;
let browser = Browser::builder()
.stealth(StealthProfile::spoofed())
.headless(true)
.launch()
.await
.expect("launch");
let tab = browser.main_tab();
tab.goto(&server.uri()).await.expect("goto");
tab.wait_for_load().await.expect("load");
let outcome = tab
.cloudflare()
.wait_for_clearance(Duration::from_secs(30))
.await
.expect("clearance");
match outcome {
ClearanceOutcome::TokenAcquired(token) => {
assert!(
!token.is_empty(),
"invisible Turnstile should populate token"
);
}
other => panic!("expected TokenAcquired from invisible sitekey, got {other:?}"),
}
browser.close().await.expect("close");
}