1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub enum FeedCardStatus {
6 #[serde(rename = "active")]
8 Active,
9 #[serde(rename = "inactive")]
11 Inactive,
12}
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
16pub enum UserIdType {
17 #[serde(rename = "user_id")]
19 UserId,
20 #[serde(rename = "union_id")]
22 UnionId,
23 #[serde(rename = "open_id")]
25 OpenId,
26}
27
28impl UserIdType {
29 pub fn as_str(&self) -> &'static str {
30 match self {
31 UserIdType::UserId => "user_id",
32 UserIdType::UnionId => "union_id",
33 UserIdType::OpenId => "open_id",
34 }
35 }
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct FeedCard {
41 pub card_id: String,
43 pub title: Option<String>,
45 pub content: Option<String>,
47 pub status: Option<FeedCardStatus>,
49 pub create_time: Option<String>,
51 pub update_time: Option<String>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ButtonInfo {
58 pub button_id: String,
60 pub text: String,
62 pub button_type: Option<String>,
64 pub action: Option<String>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct TimelyNotification {
71 pub notification_type: String,
73 pub message: String,
75 pub target_users: Vec<String>,
77}
78
79#[cfg(test)]
80#[allow(unused_variables, unused_unsafe)]
81mod tests {
82 use super::*;
83 use serde_json;
84
85 #[test]
86 fn test_feed_card_status_serialization() {
87 let active = FeedCardStatus::Active;
88 let inactive = FeedCardStatus::Inactive;
89
90 let active_json = serde_json::to_string(&active).unwrap();
91 let inactive_json = serde_json::to_string(&inactive).unwrap();
92
93 assert_eq!(active_json, "\"active\"");
94 assert_eq!(inactive_json, "\"inactive\"");
95 }
96
97 #[test]
98 fn test_feed_card_status_deserialization() {
99 let active_result: FeedCardStatus = serde_json::from_str("\"active\"").unwrap();
100 let inactive_result: FeedCardStatus = serde_json::from_str("\"inactive\"").unwrap();
101
102 assert_eq!(active_result, FeedCardStatus::Active);
103 assert_eq!(inactive_result, FeedCardStatus::Inactive);
104 }
105
106 #[test]
107 fn test_feed_card_status_clone_and_debug() {
108 let status = FeedCardStatus::Active;
109 let cloned_status = status.clone();
110
111 assert_eq!(status, cloned_status);
112 assert!(format!("{:?}", status).contains("Active"));
113 }
114
115 #[test]
116 fn test_user_id_type_as_str() {
117 assert_eq!(UserIdType::UserId.as_str(), "user_id");
118 assert_eq!(UserIdType::UnionId.as_str(), "union_id");
119 assert_eq!(UserIdType::OpenId.as_str(), "open_id");
120 }
121
122 #[test]
123 fn test_user_id_type_serialization() {
124 let user_id = UserIdType::UserId;
125 let union_id = UserIdType::UnionId;
126 let open_id = UserIdType::OpenId;
127
128 let user_id_json = serde_json::to_string(&user_id).unwrap();
129 let union_id_json = serde_json::to_string(&union_id).unwrap();
130 let open_id_json = serde_json::to_string(&open_id).unwrap();
131
132 assert_eq!(user_id_json, "\"user_id\"");
133 assert_eq!(union_id_json, "\"union_id\"");
134 assert_eq!(open_id_json, "\"open_id\"");
135 }
136
137 #[test]
138 fn test_user_id_type_deserialization() {
139 let user_id_result: UserIdType = serde_json::from_str("\"user_id\"").unwrap();
140 let union_id_result: UserIdType = serde_json::from_str("\"union_id\"").unwrap();
141 let open_id_result: UserIdType = serde_json::from_str("\"open_id\"").unwrap();
142
143 assert_eq!(user_id_result, UserIdType::UserId);
144 assert_eq!(union_id_result, UserIdType::UnionId);
145 assert_eq!(open_id_result, UserIdType::OpenId);
146 }
147
148 #[test]
149 fn test_user_id_type_clone_debug_and_partial_eq() {
150 let id_type = UserIdType::UserId;
151 let cloned_type = id_type.clone();
152
153 assert_eq!(id_type, cloned_type);
154 assert!(format!("{:?}", id_type).contains("UserId"));
155 assert_ne!(UserIdType::UserId, UserIdType::UnionId);
156 }
157
158 #[test]
159 fn test_feed_card_serialization() {
160 let feed_card = FeedCard {
161 card_id: "card123".to_string(),
162 title: Some("Test Card".to_string()),
163 content: Some("Test Content".to_string()),
164 status: Some(FeedCardStatus::Active),
165 create_time: Some("2023-01-01T00:00:00Z".to_string()),
166 update_time: Some("2023-01-02T00:00:00Z".to_string()),
167 };
168
169 let json = serde_json::to_string(&feed_card).unwrap();
170 assert!(json.contains("card123"));
171 assert!(json.contains("Test Card"));
172 assert!(json.contains("Test Content"));
173 assert!(json.contains("active"));
174 }
175
176 #[test]
177 fn test_feed_card_deserialization() {
178 let json = r#"{
179 "card_id": "card123",
180 "title": "Test Card",
181 "content": "Test Content",
182 "status": "active",
183 "create_time": "2023-01-01T00:00:00Z",
184 "update_time": "2023-01-02T00:00:00Z"
185 }"#;
186
187 let feed_card: FeedCard = serde_json::from_str(json).unwrap();
188 assert_eq!(feed_card.card_id, "card123");
189 assert_eq!(feed_card.title, Some("Test Card".to_string()));
190 assert_eq!(feed_card.content, Some("Test Content".to_string()));
191 assert_eq!(feed_card.status, Some(FeedCardStatus::Active));
192 assert_eq!(
193 feed_card.create_time,
194 Some("2023-01-01T00:00:00Z".to_string())
195 );
196 assert_eq!(
197 feed_card.update_time,
198 Some("2023-01-02T00:00:00Z".to_string())
199 );
200 }
201
202 #[test]
203 fn test_feed_card_with_none_values() {
204 let feed_card = FeedCard {
205 card_id: "card456".to_string(),
206 title: None,
207 content: None,
208 status: None,
209 create_time: None,
210 update_time: None,
211 };
212
213 let json = serde_json::to_string(&feed_card).unwrap();
214 let deserialized: FeedCard = serde_json::from_str(&json).unwrap();
215
216 assert_eq!(deserialized.card_id, "card456");
217 assert_eq!(deserialized.title, None);
218 assert_eq!(deserialized.content, None);
219 assert_eq!(deserialized.status, None);
220 assert_eq!(deserialized.create_time, None);
221 assert_eq!(deserialized.update_time, None);
222 }
223
224 #[test]
225 fn test_feed_card_clone_and_debug() {
226 let feed_card = FeedCard {
227 card_id: "card789".to_string(),
228 title: Some("Clone Test".to_string()),
229 content: Some("Clone Content".to_string()),
230 status: Some(FeedCardStatus::Inactive),
231 create_time: Some("2023-01-03T00:00:00Z".to_string()),
232 update_time: Some("2023-01-04T00:00:00Z".to_string()),
233 };
234
235 let cloned_card = feed_card.clone();
236 assert_eq!(feed_card.card_id, cloned_card.card_id);
237 assert_eq!(feed_card.title, cloned_card.title);
238 assert_eq!(feed_card.status, cloned_card.status);
239
240 let debug_output = format!("{:?}", feed_card);
241 assert!(debug_output.contains("card789"));
242 assert!(debug_output.contains("Clone Test"));
243 }
244
245 #[test]
246 fn test_button_info_serialization() {
247 let button = ButtonInfo {
248 button_id: "btn123".to_string(),
249 text: "Click Me".to_string(),
250 button_type: Some("primary".to_string()),
251 action: Some("submit".to_string()),
252 };
253
254 let json = serde_json::to_string(&button).unwrap();
255 assert!(json.contains("btn123"));
256 assert!(json.contains("Click Me"));
257 assert!(json.contains("primary"));
258 assert!(json.contains("submit"));
259 }
260
261 #[test]
262 fn test_button_info_deserialization() {
263 let json = r#"{
264 "button_id": "btn456",
265 "text": "Submit",
266 "button_type": "secondary",
267 "action": "cancel"
268 }"#;
269
270 let button: ButtonInfo = serde_json::from_str(json).unwrap();
271 assert_eq!(button.button_id, "btn456");
272 assert_eq!(button.text, "Submit");
273 assert_eq!(button.button_type, Some("secondary".to_string()));
274 assert_eq!(button.action, Some("cancel".to_string()));
275 }
276
277 #[test]
278 fn test_button_info_with_none_values() {
279 let button = ButtonInfo {
280 button_id: "btn789".to_string(),
281 text: "Basic Button".to_string(),
282 button_type: None,
283 action: None,
284 };
285
286 let json = serde_json::to_string(&button).unwrap();
287 let deserialized: ButtonInfo = serde_json::from_str(&json).unwrap();
288
289 assert_eq!(deserialized.button_id, "btn789");
290 assert_eq!(deserialized.text, "Basic Button");
291 assert_eq!(deserialized.button_type, None);
292 assert_eq!(deserialized.action, None);
293 }
294
295 #[test]
296 fn test_button_info_clone_and_debug() {
297 let button = ButtonInfo {
298 button_id: "btn_clone".to_string(),
299 text: "Clone Test".to_string(),
300 button_type: Some("test".to_string()),
301 action: Some("test_action".to_string()),
302 };
303
304 let cloned_button = button.clone();
305 assert_eq!(button.button_id, cloned_button.button_id);
306 assert_eq!(button.text, cloned_button.text);
307 assert_eq!(button.button_type, cloned_button.button_type);
308 assert_eq!(button.action, cloned_button.action);
309
310 let debug_output = format!("{:?}", button);
311 assert!(debug_output.contains("btn_clone"));
312 assert!(debug_output.contains("Clone Test"));
313 }
314
315 #[test]
316 fn test_timely_notification_serialization() {
317 let notification = TimelyNotification {
318 notification_type: "urgent".to_string(),
319 message: "Important notification".to_string(),
320 target_users: vec!["user1".to_string(), "user2".to_string()],
321 };
322
323 let json = serde_json::to_string(¬ification).unwrap();
324 assert!(json.contains("urgent"));
325 assert!(json.contains("Important notification"));
326 assert!(json.contains("user1"));
327 assert!(json.contains("user2"));
328 }
329
330 #[test]
331 fn test_timely_notification_deserialization() {
332 let json = r#"{
333 "notification_type": "reminder",
334 "message": "Meeting in 5 minutes",
335 "target_users": ["alice", "bob", "charlie"]
336 }"#;
337
338 let notification: TimelyNotification = serde_json::from_str(json).unwrap();
339 assert_eq!(notification.notification_type, "reminder");
340 assert_eq!(notification.message, "Meeting in 5 minutes");
341 assert_eq!(notification.target_users, vec!["alice", "bob", "charlie"]);
342 }
343
344 #[test]
345 fn test_timely_notification_with_empty_users() {
346 let notification = TimelyNotification {
347 notification_type: "info".to_string(),
348 message: "System maintenance".to_string(),
349 target_users: vec![],
350 };
351
352 let json = serde_json::to_string(¬ification).unwrap();
353 let deserialized: TimelyNotification = serde_json::from_str(&json).unwrap();
354
355 assert_eq!(deserialized.notification_type, "info");
356 assert_eq!(deserialized.message, "System maintenance");
357 assert!(deserialized.target_users.is_empty());
358 }
359
360 #[test]
361 fn test_timely_notification_clone_and_debug() {
362 let notification = TimelyNotification {
363 notification_type: "test".to_string(),
364 message: "Test message".to_string(),
365 target_users: vec!["test_user".to_string()],
366 };
367
368 let cloned_notification = notification.clone();
369 assert_eq!(
370 notification.notification_type,
371 cloned_notification.notification_type
372 );
373 assert_eq!(notification.message, cloned_notification.message);
374 assert_eq!(notification.target_users, cloned_notification.target_users);
375
376 let debug_output = format!("{:?}", notification);
377 assert!(debug_output.contains("test"));
378 assert!(debug_output.contains("Test message"));
379 assert!(debug_output.contains("test_user"));
380 }
381
382 #[test]
383 fn test_timely_notification_with_unicode() {
384 let notification = TimelyNotification {
385 notification_type: "提醒".to_string(),
386 message: "会议将在5分钟后开始".to_string(),
387 target_users: vec!["张三".to_string(), "李四".to_string()],
388 };
389
390 let json = serde_json::to_string(¬ification).unwrap();
391 let deserialized: TimelyNotification = serde_json::from_str(&json).unwrap();
392
393 assert_eq!(deserialized.notification_type, "提醒");
394 assert_eq!(deserialized.message, "会议将在5分钟后开始");
395 assert_eq!(deserialized.target_users, vec!["张三", "李四"]);
396 }
397
398 #[test]
399 fn test_complex_feed_card_status_combinations() {
400 let test_cases = vec![
401 (FeedCardStatus::Active, "active"),
402 (FeedCardStatus::Inactive, "inactive"),
403 ];
404
405 for (status, expected_str) in test_cases {
406 let json = serde_json::to_string(&status).unwrap();
407 assert_eq!(json, format!("\"{}\"", expected_str));
408
409 let deserialized: FeedCardStatus = serde_json::from_str(&json).unwrap();
410 assert_eq!(deserialized, status);
411 }
412 }
413
414 #[test]
415 fn test_all_user_id_types() {
416 let types = vec![UserIdType::UserId, UserIdType::UnionId, UserIdType::OpenId];
417
418 for user_type in types {
419 let json = serde_json::to_string(&user_type).unwrap();
420 let deserialized: UserIdType = serde_json::from_str(&json).unwrap();
421 assert_eq!(deserialized, user_type);
422
423 let str_value = user_type.as_str();
425 assert!(!str_value.is_empty());
426 assert!(str_value.contains("_id") || str_value == "open_id");
427 }
428 }
429}