captchaforge 0.2.36

[DO NOT USE — UNDER ACTIVE DEVELOPMENT, NOT PRODUCTION-READY] Captcha solver scaffolding for chromiumoxide-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 / CDP fingerprint layer that no flag-based stealth has cleared. Watch the repo; do not depend on this for any real workload.
Documentation
//! Property-based tests for URL / domain extraction.

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

/// Reproduce the private extract_domain logic for testing.
fn extract_domain(page_url: &str) -> String {
    if let Ok(u) = url::Url::parse(page_url) {
        if let Some(host) = u.host_str() {
            return host.to_string();
        }
    }
    // Fallback: strip protocol and path manually.
    page_url
        .split("://")
        .nth(1)
        .unwrap_or(page_url)
        .split('/')
        .next()
        .unwrap_or(page_url)
        .split(':')
        .next()
        .unwrap_or(page_url)
        .to_string()
}

#[test]
fn extract_domain_never_panics() {
    let mut runner = TestRunner::default();
    runner
        .run(&"(?s).*", |url| {
            let domain = extract_domain(&url);
            prop_assert!(!domain.contains("://"));
            Ok(())
        })
        .unwrap();
}

#[test]
fn extract_domain_preserves_host() {
    let mut runner = TestRunner::default();
    runner.run(&
        "https?://[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*(/[a-zA-Z0-9/_-]*)?",
        |url| {
            let domain = extract_domain(&url);
            prop_assert!(!domain.is_empty());
            prop_assert!(!domain.starts_with("http"));
            prop_assert!(!domain.contains('/'));
            Ok(())
        }
    ).unwrap();
}

#[test]
fn extract_domain_strips_port() {
    let mut runner = TestRunner::default();
    runner
        .run(
            &"https?://[a-z0-9.-]{1,64}:[1-9][0-9]{0,4}(/[a-zA-Z0-9/_-]*)?",
            |url| {
                let domain = extract_domain(&url);
                prop_assert!(!domain.contains(':'));
                Ok(())
            },
        )
        .unwrap();
}

#[test]
fn extract_domain_idempotent() {
    let mut runner = TestRunner::default();
    runner
        .run(&"https?://[a-z0-9.-]{1,64}(/[a-zA-Z0-9/_-]*)?", |url| {
            let d1 = extract_domain(&url);
            let d2 = extract_domain(&format!("https://{}/path", d1));
            prop_assert_eq!(d1, d2);
            Ok(())
        })
        .unwrap();
}

#[test]
fn extract_domain_empty_input() {
    assert_eq!(extract_domain(""), "");
}

#[test]
fn extract_domain_ipv4() {
    assert_eq!(
        extract_domain("http://192.168.1.1:8080/path"),
        "192.168.1.1"
    );
}

#[test]
fn extract_domain_ipv6() {
    assert_eq!(extract_domain("http://[::1]:8080/path"), "[::1]");
}

#[test]
fn extract_domain_punycode() {
    assert_eq!(
        extract_domain("https://xn--exmple-cua.com/path"),
        "xn--exmple-cua.com"
    );
}

#[test]
fn extract_domain_fragment_and_query_stripped() {
    assert_eq!(
        extract_domain("https://example.com/path?foo=bar#section"),
        "example.com"
    );
}

#[test]
fn extract_domain_subdomain_depth() {
    assert_eq!(
        extract_domain("https://a.b.c.d.e.example.com/path"),
        "a.b.c.d.e.example.com"
    );
}