captchaforge 0.2.4

Automatic CAPTCHA detection and multi-strategy solving for chromiumoxide-driven headless browsers (Cloudflare Turnstile, reCAPTCHA v2/v3, hCaptcha, image grids, audio, sliders).
Documentation
//! Chaos tests for frame-piercing utilities.

use proptest::prelude::*;
use proptest::test_runner::TestRunner;

#[test]
fn selector_escaping_never_panics() {
    let mut runner = TestRunner::default();
    runner
        .run(&"(?s).*", |sel| {
            let _ = sel.replace('\\', "\\\\").replace('\'', "\\'");
            Ok(())
        })
        .unwrap();
}

#[test]
fn token_name_escaping_never_panics() {
    let mut runner = TestRunner::default();
    runner
        .run(&"(?s).*", |name| {
            let _ = name.replace('"', "\\\"");
            Ok(())
        })
        .unwrap();
}

#[test]
fn selector_escaping_balanced_backslashes() {
    let mut runner = TestRunner::default();
    runner
        .run(&"[a-zA-Z0-9\\\\_\\-]{1,50}", |sel| {
            let escaped = sel.replace('\\', "\\\\").replace('\'', "\\'");
            // No unescaped single quotes should remain.
            prop_assert!(!escaped.contains('\''));
            Ok(())
        })
        .unwrap();
}

#[test]
fn verify_token_js_format_valid() {
    let name = "g-recaptcha-response";
    let js = format!(
        r#"!!document.querySelector('input[name="{}"][value]:not([value=""])')"#,
        name.replace('"', "\\\"")
    );
    assert!(js.starts_with("!!document.querySelector"));
    assert!(js.contains(name));
}

#[test]
fn verify_token_js_with_empty_name() {
    let name = "";
    let js = format!(
        r#"!!document.querySelector('input[name="{}"][value]:not([value=""])')"#,
        name.replace('"', "\\\"")
    );
    assert!(js.contains("input[name=\"\"]"));
}

#[test]
fn verify_token_js_with_special_chars() {
    let name = "token[0]";
    let js = format!(
        r#"!!document.querySelector('input[name="{}"][value]:not([value=""])')"#,
        name.replace('"', "\\\"")
    );
    assert!(js.contains("token[0]"));
}