captchaforge 0.2.38

[DO NOT USE — UNDER ACTIVE DEVELOPMENT, NOT PRODUCTION-READY] Captcha solver scaffolding for Firefox + BiDi-driven browsers. The architecture is in place (vendor solvers, retry-loop iframe walking, VLM provider abstraction, real-WAF bench harness) but the live-vendor success rate is still 0% — Cloudflare Turnstile / hCaptcha / reCAPTCHA detect us at a TLS / BiDi fingerprint layer that no flag-based stealth has cleared. Watch the repo; do not depend on this for any real workload.
Documentation
//! Stealth profile contract tests — verify that Firefox prefs + JS overrides
//! produce the expected navigator surfaces.
//!
//! These tests launch real Firefox instances with `StealthProfile::FirefoxLinux`
//! and assert that `navigator.userAgent`, `navigator.platform`, `navigator.language`,
//! and `navigator.hardwareConcurrency` match the profile's declared values.

mod common;

#[tokio::test]
async fn stealth_profile_user_agent_matches() {
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    // Apply stealth profile (in addition to any launch-time prefs).
    let profile = captchaforge::StealthProfile::FirefoxLinux;
    let overrides = captchaforge::profile_to_overrides(&profile);
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let ua: String = page
        .evaluate("navigator.userAgent")
        .await
        .unwrap()
        .into_value()
        .unwrap();
    assert!(
        ua == overrides.user_agent,
        "navigator.userAgent mismatch:\n  expected: {}\n  actual:   {}",
        overrides.user_agent,
        ua
    );

    browser.close().await.unwrap();
}

#[tokio::test]
async fn stealth_profile_platform_matches() {
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    let profile = captchaforge::StealthProfile::FirefoxLinux;
    let overrides = captchaforge::profile_to_overrides(&profile);
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let platform: String = page
        .evaluate("navigator.platform")
        .await
        .unwrap()
        .into_value()
        .unwrap();
    assert_eq!(platform, overrides.platform);

    browser.close().await.unwrap();
}

#[tokio::test]
async fn stealth_profile_languages_match() {
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    let profile = captchaforge::StealthProfile::FirefoxLinux;
    let overrides = captchaforge::profile_to_overrides(&profile);
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let langs: Vec<String> = page
        .evaluate("navigator.languages")
        .await
        .unwrap()
        .into_value()
        .unwrap();
    assert_eq!(langs, overrides.languages);

    browser.close().await.unwrap();
}

#[tokio::test]
async fn stealth_profile_hardware_concurrency_matches() {
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    let profile = captchaforge::StealthProfile::FirefoxLinux;
    let overrides = captchaforge::profile_to_overrides(&profile);
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let concurrency: u32 = page
        .evaluate("navigator.hardwareConcurrency")
        .await
        .unwrap()
        .into_value()
        .unwrap();
    assert_eq!(concurrency, overrides.hardware_concurrency);

    browser.close().await.unwrap();
}

#[tokio::test]
async fn stealth_profile_webdriver_is_absent() {
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    let profile = captchaforge::StealthProfile::FirefoxLinux;
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let webdriver: bool = page
        .evaluate("navigator.webdriver === undefined || navigator.webdriver === false")
        .await
        .unwrap()
        .into_value()
        .unwrap();
    assert!(webdriver, "navigator.webdriver should be absent/false");

    browser.close().await.unwrap();
}

#[tokio::test]
async fn stealth_profile_screen_is_self_consistent() {
    // The disguise deliberately does NOT override screen.* — overriding the JS
    // getters desyncs them from the CSS `matchMedia` device-width/height layer
    // (a real, hard tell: incolumitas MQ_SCREEN). The correct contract is that
    // screen is plausible AND self-consistent with the media-query layer, which
    // a real browser always is and a bare headless Firefox already satisfies.
    let browser = common::launch_browser().await;
    let page = browser.new_page("about:blank").await.unwrap();

    let profile = captchaforge::StealthProfile::FirefoxLinux;
    captchaforge::apply_stealth_profile(&page, &profile).await.unwrap();

    let consistent: bool = page
        .evaluate(
            "(() => { const w = screen.width, h = screen.height; \
             if (!(w > 0 && h > 0)) return false; \
             return window.matchMedia('(device-width: ' + w + 'px)').matches \
                 && window.matchMedia('(device-height: ' + h + 'px)').matches; })()",
        )
        .await
        .unwrap()
        .into_value()
        .unwrap();

    assert!(
        consistent,
        "screen.* must be plausible and consistent with the matchMedia device-width/height layer"
    );

    browser.close().await.unwrap();
}