1pub mod error;
2pub mod id;
3pub mod provider;
4pub mod types;
5
6pub use error::MxrError;
7pub use id::*;
8pub use provider::*;
9pub use types::*;
10
11#[cfg(test)]
12mod tests {
13 use super::*;
14
15 #[test]
16 fn typed_id_roundtrip() {
17 let id = MessageId::new();
18 let json = serde_json::to_string(&id).unwrap();
19 let parsed: MessageId = serde_json::from_str(&json).unwrap();
20 assert_eq!(id, parsed);
21 }
22
23 #[test]
24 fn typed_id_display() {
25 let id = AccountId::new();
26 let display = format!("{}", id);
27 assert!(!display.is_empty());
28 assert_eq!(display, id.as_str());
29 }
30
31 #[test]
32 fn message_flags_bitwise() {
33 let flags = MessageFlags::READ | MessageFlags::STARRED;
34 assert!(flags.contains(MessageFlags::READ));
35 assert!(flags.contains(MessageFlags::STARRED));
36 assert!(!flags.contains(MessageFlags::DRAFT));
37 assert_eq!(flags.bits(), 0b0000_0011);
38 }
39
40 #[test]
41 fn message_flags_serde() {
42 let flags = MessageFlags::READ | MessageFlags::STARRED;
43 let json = serde_json::to_string(&flags).unwrap();
44 let parsed: MessageFlags = serde_json::from_str(&json).unwrap();
45 assert_eq!(flags, parsed);
46 }
47
48 #[test]
49 fn envelope_serde_roundtrip() {
50 let env = Envelope {
51 id: MessageId::new(),
52 account_id: AccountId::new(),
53 provider_id: "test-1".to_string(),
54 thread_id: ThreadId::new(),
55 message_id_header: Some("<test@example.com>".to_string()),
56 in_reply_to: None,
57 references: vec![],
58 from: Address {
59 name: Some("Alice".to_string()),
60 email: "alice@example.com".to_string(),
61 },
62 to: vec![Address {
63 name: None,
64 email: "bob@example.com".to_string(),
65 }],
66 cc: vec![],
67 bcc: vec![],
68 subject: "Test subject".to_string(),
69 date: chrono::Utc::now(),
70 flags: MessageFlags::READ | MessageFlags::STARRED,
71 snippet: "Preview text".to_string(),
72 has_attachments: false,
73 size_bytes: 1024,
74 unsubscribe: UnsubscribeMethod::None,
75 label_provider_ids: vec![],
76 };
77 let json = serde_json::to_string(&env).unwrap();
78 let parsed: Envelope = serde_json::from_str(&json).unwrap();
79 assert_eq!(env.id, parsed.id);
80 assert_eq!(env.subject, parsed.subject);
81 assert_eq!(env.flags, parsed.flags);
82 assert_eq!(env.from, parsed.from);
83 }
84
85 #[test]
86 fn unsubscribe_method_variants() {
87 let variants = vec![
88 UnsubscribeMethod::OneClick {
89 url: "https://unsub.example.com".to_string(),
90 },
91 UnsubscribeMethod::HttpLink {
92 url: "https://unsub.example.com/link".to_string(),
93 },
94 UnsubscribeMethod::Mailto {
95 address: "unsub@example.com".to_string(),
96 subject: Some("unsubscribe".to_string()),
97 },
98 UnsubscribeMethod::BodyLink {
99 url: "https://body.example.com".to_string(),
100 },
101 UnsubscribeMethod::None,
102 ];
103 for v in variants {
104 let json = serde_json::to_string(&v).unwrap();
105 let parsed: UnsubscribeMethod = serde_json::from_str(&json).unwrap();
106 assert_eq!(v, parsed);
107 }
108 }
109
110 #[test]
111 fn sync_cursor_variants() {
112 let cursors = vec![
113 SyncCursor::Gmail { history_id: 12345 },
114 SyncCursor::Imap {
115 uid_validity: 1,
116 uid_next: 100,
117 mailboxes: vec![ImapMailboxCursor {
118 mailbox: "INBOX".into(),
119 uid_validity: 1,
120 uid_next: 100,
121 highest_modseq: Some(123),
122 }],
123 capabilities: Some(ImapCapabilityState {
124 move_ext: true,
125 uidplus: true,
126 idle: true,
127 condstore: false,
128 qresync: false,
129 namespace: true,
130 list_status: false,
131 utf8_accept: false,
132 imap4rev2: false,
133 }),
134 },
135 SyncCursor::Initial,
136 ];
137 for c in cursors {
138 let json = serde_json::to_string(&c).unwrap();
139 let _parsed: SyncCursor = serde_json::from_str(&json).unwrap();
140 }
141 }
142}