user_email.rs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. use validator::validate_email;
  2. #[derive(Debug)]
  3. pub struct UserEmail(pub String);
  4. impl UserEmail {
  5. pub fn parse(s: String) -> Result<UserEmail, String> {
  6. if s.trim().is_empty() {
  7. return Err(format!("Email can not be empty or whitespace"));
  8. }
  9. if validate_email(&s) {
  10. Ok(Self(s))
  11. } else {
  12. Err(format!("{} is not a valid email.", s))
  13. }
  14. }
  15. }
  16. impl AsRef<str> for UserEmail {
  17. fn as_ref(&self) -> &str { &self.0 }
  18. }
  19. #[cfg(test)]
  20. mod tests {
  21. use super::*;
  22. use claim::assert_err;
  23. use fake::{faker::internet::en::SafeEmail, Fake};
  24. #[test]
  25. fn empty_string_is_rejected() {
  26. let email = "".to_string();
  27. assert_err!(UserEmail::parse(email));
  28. }
  29. #[test]
  30. fn email_missing_at_symbol_is_rejected() {
  31. let email = "helloworld.com".to_string();
  32. assert_err!(UserEmail::parse(email));
  33. }
  34. #[test]
  35. fn email_missing_subject_is_rejected() {
  36. let email = "@domain.com".to_string();
  37. assert_err!(UserEmail::parse(email));
  38. }
  39. #[derive(Debug, Clone)]
  40. struct ValidEmailFixture(pub String);
  41. impl quickcheck::Arbitrary for ValidEmailFixture {
  42. fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
  43. let email = SafeEmail().fake_with_rng(g);
  44. Self(email)
  45. }
  46. }
  47. #[quickcheck_macros::quickcheck]
  48. fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool {
  49. UserEmail::parse(valid_email.0).is_ok()
  50. }
  51. }