zero_bounce/utility/structures/
validation.rs1use chrono::NaiveDateTime;
2use serde::Deserialize;
3
4use crate::utility::structures::custom_deserialize::deserialize_naive_date;
5use crate::utility::structures::validate_enums::{ZBValidateStatus, ZBValidateSubStatus};
6
7
8#[derive(Clone, Debug, Deserialize)]
9pub struct ZBValidation {
10 pub address: String,
11 pub status: String,
12 pub sub_status: String,
13 pub free_email: bool,
14 pub did_you_mean: Option<String>,
15 pub account: Option<String>,
16 pub domain: Option<String>,
17 pub domain_age_days: Option<String>,
18 pub smtp_provider: Option<String>,
19 pub mx_record: Option<String>,
20 pub mx_found: Option<String>,
21 pub firstname: Option<String>,
22 pub lastname: Option<String>,
23 pub gender: Option<String>,
24 pub country: Option<String>,
25 pub region: Option<String>,
26 pub city: Option<String>,
27 pub zipcode: Option<String>,
28
29 #[serde(deserialize_with="deserialize_naive_date")]
30 pub processed_at: NaiveDateTime,
31}
32
33impl ZBValidation {
34 pub fn status_enum(&self) -> ZBValidateStatus {
36 self.status.parse().unwrap_or_else(|_| ZBValidateStatus::UnknownValue(self.status.clone()))
37 }
38
39 pub fn sub_status_enum(&self) -> ZBValidateSubStatus {
41 self.sub_status.parse().unwrap_or_else(|_| ZBValidateSubStatus::UnknownValue(self.sub_status.clone()))
42 }
43}
44
45
46#[derive(Clone, Debug, Deserialize)]
47pub struct ZBBatchError {
48 pub error: String,
49 pub email_address: String,
50}
51
52
53#[derive(Clone, Debug, Deserialize)]
54pub struct ZBBatchValidation {
55 pub email_batch: Vec<ZBValidation>,
56 pub errors: Vec<ZBBatchError>,
57}
58
59#[cfg(test)]
60mod test {
61 use serde_json::{Result as SerdeResult, from_str};
62
63 use super::*;
64 use crate::utility::mock_constants::VALIDATION_RESPONSE_VALID;
65 use crate::utility::mock_constants::VALIDATION_RESPONSE_INVALID;
66 use crate::utility::mock_constants::VALIDATION_RESPONSE_NULL_FIELDS;
67 use crate::utility::mock_constants::BATCH_VALIDATION_WITH_ERROR;
68 use crate::utility::mock_constants::BATCH_VALIDATION_ERROR_ONLY;
69 use crate::utility::mock_constants::BATCH_VALIDATION_NO_ERROR;
70
71 #[test]
72 fn test_validation_invalid_json() {
73 let validation_res: SerdeResult<ZBValidation> = from_str("");
74 assert!(validation_res.is_err());
75 }
76
77 #[test]
78 fn test_validation_missing_expected_fields() {
79 let validation_res: SerdeResult<ZBValidation> = from_str(VALIDATION_RESPONSE_NULL_FIELDS);
80 assert!(validation_res.is_ok());
81
82 let validation = validation_res.unwrap();
83 assert_eq!(validation.did_you_mean, None);
84 assert_eq!(validation.domain_age_days, Some("".to_string()));
85 }
86
87 #[test]
88 fn test_validation_invalid_email_status() {
89 let validation_res: SerdeResult<ZBValidation> = from_str(VALIDATION_RESPONSE_INVALID);
90 assert!(validation_res.is_ok());
91
92 let validation = validation_res.unwrap();
93 assert_eq!(validation.status, "invalid".to_string());
94 assert_eq!(validation.sub_status, "mailbox_not_found".to_string());
95 assert_eq!(validation.did_you_mean, None);
96 assert_eq!(validation.smtp_provider, Some("example".to_string()));
97 assert_eq!(validation.free_email, false);
98
99 let expected_date = NaiveDateTime::new(
100 chrono::NaiveDate::from_ymd_opt(2023, 3, 23).unwrap(),
101 chrono::NaiveTime::from_hms_milli_opt(12, 30, 28, 3).unwrap(),
102 );
103 assert_eq!(validation.processed_at, expected_date);
104 }
105
106 #[test]
107 fn test_validation_valid_email_status() {
108 let validation_res: SerdeResult<ZBValidation> = from_str(VALIDATION_RESPONSE_VALID);
109 assert!(validation_res.is_ok());
110
111 let validation = validation_res.unwrap();
112 assert_eq!(validation.status, "valid".to_string());
113 assert_eq!(validation.sub_status, "".to_string());
114 assert_eq!(validation.did_you_mean, None);
115 assert_eq!(validation.smtp_provider, Some("example".to_string()));
116 assert_eq!(validation.free_email, false);
117
118 let expected_date = NaiveDateTime::new(
119 chrono::NaiveDate::from_ymd_opt(2023, 3, 23).unwrap(),
120 chrono::NaiveTime::from_hms_milli_opt(13, 30, 28, 105).unwrap(),
121 );
122 assert_eq!(validation.processed_at, expected_date);
123 }
124
125 #[test]
126 fn test_batch_error_only_content() {
127 let batch: SerdeResult<ZBBatchValidation> = from_str(BATCH_VALIDATION_ERROR_ONLY);
128 assert!(batch.is_ok());
129
130 let batch_object = batch.unwrap();
131 assert_eq!(batch_object.email_batch.len(), 0);
132 assert_eq!(batch_object.errors.len(), 1);
133 }
134
135 #[test]
136 fn test_batch_validation_and_error_content() {
137 let batch: SerdeResult<ZBBatchValidation> = from_str(BATCH_VALIDATION_WITH_ERROR);
138 assert!(batch.is_ok());
139
140 let batch_object = batch.unwrap();
141 assert_eq!(batch_object.email_batch.len(), 1);
142 assert_eq!(batch_object.errors.len(), 1);
143 }
144
145 #[test]
146 fn test_batch_validation_only_content() {
147 let batch: SerdeResult<ZBBatchValidation> = from_str(BATCH_VALIDATION_NO_ERROR);
148 assert!(batch.is_ok());
149
150 let batch_object = batch.unwrap();
151 assert_eq!(batch_object.email_batch.len(), 1);
152 assert_eq!(batch_object.errors.len(), 0);
153 }
154
155}