use validator::validate_email; #[derive(Debug, Clone)] pub struct SubscriberEmail(String); impl SubscriberEmail { pub fn parse(s: String) -> Result { if validate_email(&s) { Ok(Self(s)) } else { Err(format!("{} is not a valid subscriber email.", s)) } } } impl AsRef for SubscriberEmail { fn as_ref(&self) -> &str { &self.0 } } #[cfg(test)] mod tests { use super::SubscriberEmail; use claims::assert_err; use fake::faker::internet::en::SafeEmail; use fake::Fake; use rand::{rngs::StdRng, SeedableRng}; #[derive(Debug, Clone)] struct ValidEmailFixture(pub String); impl quickcheck::Arbitrary for ValidEmailFixture { fn arbitrary(g: &mut quickcheck::Gen) -> Self { let mut rng = StdRng::seed_from_u64(u64::arbitrary(g)); let email = SafeEmail().fake_with_rng(&mut rng); Self(email) } } #[quickcheck_macros::quickcheck] fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool { dbg!(&valid_email.0); SubscriberEmail::parse(valid_email.0).is_ok() } #[test] fn empty_string_is_rejected() { let email = "".to_string(); assert_err!(SubscriberEmail::parse(email)); } #[test] fn email_missing_at_symbol_is_rejected() { let email = "ursuladomain.com".to_string(); assert_err!(SubscriberEmail::parse(email)); } #[test] fn email_missing_subject_is_rejected() { let email = "@domain.com".to_string(); assert_err!(SubscriberEmail::parse(email)); } #[test] fn email_sharp_s_prefix_is_rejected() { let email = "joe.ßchmidt@example.com".to_string(); assert_err!(SubscriberEmail::parse(email)); } #[test] fn email_with_invalid_characters_is_rejected() { let email = "joe.smith@ex ample.com".to_string(); assert_err!(SubscriberEmail::parse(email)); } }