use super::Refusal;
pub(super) fn pattern_refusal(
key: &str,
pattern: Option<&str>,
accepts: &[String],
typed: &str,
shown: &str,
) -> Option<Refusal> {
let compiled = regex::Regex::new(pattern?).ok()?;
if compiled.is_match(typed) {
return None;
}
let takes = if accepts.is_empty() {
format!("it matches {}", pattern?)
} else {
accepts.join(", ")
};
Some(Refusal {
text: format!("{key} is \"{shown}\", which it does not take; try {takes}"),
})
}
#[cfg(test)]
mod tests {
use super::super::fixtures::text_field;
use super::super::refusal;
#[test]
fn a_dogs_own_pattern_refuses_what_it_does_not_match() {
let mut field = text_field("region");
field.bounds.pattern = Some("^[a-z]{2}-[a-z]+-[0-9]$".to_owned());
assert_eq!(
refusal(&field, "eu-west-1"),
None,
"the pattern's own shape"
);
let refused = refusal(&field, "Europe").expect("Europe does not match");
assert_eq!(
refused.text,
"region is \"Europe\", which it does not take; try it matches ^[a-z]{2}-[a-z]+-[0-9]$"
);
field.accepts = vec!["a region like eu-west-1".to_owned()];
let refused = refusal(&field, "Europe").expect("still refused");
assert_eq!(
refused.text,
"region is \"Europe\", which it does not take; try a region like eu-west-1",
"the author's own words win over the regex"
);
}
#[test]
fn a_pattern_that_does_not_compile_refuses_nothing() {
let broken = ["^[", "a-z"].concat();
assert!(
regex::Regex::new(&broken).is_err(),
"the fixture must be a pattern regex really refuses"
);
let mut field = text_field("region");
field.bounds.pattern = Some(broken);
assert_eq!(refusal(&field, "anything at all"), None);
}
}