use captcha_sdk::{
InvalidProviderId, MAX_PROVIDER_ID_LEN, MAX_PROVIDER_ID_SEGMENT_LEN, ProviderId,
};
#[test]
fn provider_ids_reject_invalid_syntax_and_bounds() {
let oversized_id = format!("com.{}", "a".repeat(MAX_PROVIDER_ID_LEN));
let oversized_segment = format!(
"com.{}.captcha",
"a".repeat(MAX_PROVIDER_ID_SEGMENT_LEN + 1)
);
let cases = [
("", InvalidProviderId::Empty),
("example", InvalidProviderId::InvalidSyntax),
(".example", InvalidProviderId::InvalidSyntax),
("com.example.", InvalidProviderId::InvalidSyntax),
("com..example", InvalidProviderId::InvalidSyntax),
("Com.example", InvalidProviderId::InvalidSyntax),
("com.exámple", InvalidProviderId::InvalidSyntax),
("com.-example", InvalidProviderId::InvalidSyntax),
("com.example-", InvalidProviderId::InvalidSyntax),
("com.example_name", InvalidProviderId::InvalidSyntax),
];
for (value, expected) in cases {
assert_eq!(ProviderId::new(value), Err(expected), "value: {value:?}");
}
assert_eq!(
ProviderId::new(oversized_id),
Err(InvalidProviderId::TooLong)
);
assert_eq!(
ProviderId::new(oversized_segment),
Err(InvalidProviderId::SegmentTooLong)
);
}
#[test]
fn provider_ids_accept_boundaries_hyphens_and_external_namespaces() {
let boundary_segment = "a".repeat(MAX_PROVIDER_ID_SEGMENT_LEN);
let values = [
"com.example.captcha.product".to_owned(),
"io.example.my-captcha.v2".to_owned(),
format!("io.{boundary_segment}"),
];
for value in values {
let id = ProviderId::try_from(value.as_str()).expect("identifier should be accepted");
assert_eq!(id.as_str(), value);
assert_eq!(id.to_string(), value);
}
}
#[test]
fn provider_ids_publish_stable_builtins_and_reserve_their_authorities() {
let builtins = [
(ProviderId::ALTCHA_CUSTOM, "altcha.custom"),
(ProviderId::ALTCHA_SENTINEL, "altcha.sentinel"),
(ProviderId::CAPTCHAFOX_STANDARD, "captchafox.standard"),
(ProviderId::CLOUDFLARE_TURNSTILE, "cloudflare.turnstile"),
(ProviderId::FRIENDLYCAPTCHA_V2, "friendlycaptcha.v2"),
(
ProviderId::GOOGLE_RECAPTCHA_ENTERPRISE,
"google.recaptcha.enterprise",
),
(ProviderId::GOOGLE_RECAPTCHA_V2, "google.recaptcha.v2"),
(ProviderId::GOOGLE_RECAPTCHA_V3, "google.recaptcha.v3"),
(ProviderId::HCAPTCHA_ENTERPRISE, "hcaptcha.enterprise"),
(ProviderId::HCAPTCHA_STANDARD, "hcaptcha.standard"),
(ProviderId::MTCAPTCHA_STANDARD, "mtcaptcha.standard"),
(ProviderId::PROSOPO_PROCAPTCHA, "prosopo.procaptcha"),
];
for (provider, identifier) in builtins {
assert_eq!(provider.as_str(), identifier);
let json = serde_json::to_string(&provider).expect("provider should serialize");
assert_eq!(json, format!("\"{identifier}\""));
assert_eq!(
serde_json::from_str::<ProviderId>(&json).expect("provider should deserialize"),
provider
);
}
assert_eq!(
ProviderId::new("google.unrecognized-product"),
Err(InvalidProviderId::ReservedAuthority)
);
}