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 tests for SolveMethod.

use captchaforge::solver::SolveMethod;
use proptest::test_runner::TestRunner;

#[test]
fn solve_method_serde_roundtrip_all_variants() {
    for variant in [
        SolveMethod::VisionLLM,
        SolveMethod::AudioBypass,
        SolveMethod::BehavioralBypass,
        SolveMethod::ThirdPartyService,
        SolveMethod::CrowdSourced,
    ] {
        let json = serde_json::to_string(&variant).unwrap();
        let back: SolveMethod = serde_json::from_str(&json).unwrap();
        assert_eq!(variant, back, "roundtrip failed for {:?}", variant);
    }
}

#[test]
fn solve_method_serde_never_panics() {
    let mut runner = TestRunner::default();
    runner
        .run(&"[a-z_]{1,30}", |tag| {
            let json = format!("\"{}\"", tag);
            let _result: Result<SolveMethod, _> = serde_json::from_str(&json);
            Ok(())
        })
        .unwrap();
}

#[test]
fn solve_method_clone_eq() {
    let m = SolveMethod::BehavioralBypass;
    assert_eq!(m, m.clone());
}

#[test]
fn solve_method_debug_non_empty() {
    let s = format!("{:?}", SolveMethod::VisionLLM);
    assert!(!s.is_empty());
}

#[test]
fn solve_method_hash_consistent() {
    use std::collections::HashSet;
    let mut set = HashSet::new();
    set.insert(SolveMethod::BehavioralBypass);
    set.insert(SolveMethod::BehavioralBypass);
    assert_eq!(set.len(), 1);
}