use std::{
fmt::Display,
net::{IpAddr, Ipv4Addr},
};
use captcha_sdk::{CaptchaToken, CaptchaTokenError, MAX_CAPTCHA_TOKEN_LEN, VerificationRequest};
use serde::{Serialize, de::DeserializeOwned};
use static_assertions::assert_not_impl_any;
assert_not_impl_any!(CaptchaToken: Clone, Display, Serialize, DeserializeOwned);
assert_not_impl_any!(VerificationRequest: Clone, Display, Serialize, DeserializeOwned);
#[test]
fn captcha_tokens_validate_non_empty_bounded_input() {
assert!(matches!(
CaptchaToken::new(""),
Err(CaptchaTokenError::Empty)
));
assert!(CaptchaToken::new("a".repeat(MAX_CAPTCHA_TOKEN_LEN)).is_ok());
assert!(matches!(
CaptchaToken::new("a".repeat(MAX_CAPTCHA_TOKEN_LEN + 1)),
Err(CaptchaTokenError::TooLong)
));
}
#[test]
fn request_construction_exposes_opaque_token_and_optional_remote_ip() {
let ip = IpAddr::V4(Ipv4Addr::LOCALHOST);
let token = CaptchaToken::new("request-test-token").expect("token should be valid");
let request = VerificationRequest::new(token).with_remote_ip(ip);
assert_eq!(request.remote_ip(), Some(ip));
let _: &CaptchaToken = request.token();
}
#[test]
fn tokens_and_requests_redact_debug_output() {
let raw_token = "debug-must-not-contain-this-token";
let token = CaptchaToken::new(raw_token).expect("token should be valid");
let token_debug = format!("{token:?}");
assert!(token_debug.contains("[REDACTED]"));
assert!(!token_debug.contains(raw_token));
let request = VerificationRequest::new(token);
let request_debug = format!("{request:?}");
assert!(request_debug.contains("[REDACTED]"));
assert!(!request_debug.contains(raw_token));
}