Skip to content

Commit 64ace7e

Browse files
authored
Clean up tests. (#84)
Use a consistent style for XML fixtures, deduplicate some logic, and make use of `Default` implementations in a few more places.
1 parent 336013a commit 64ace7e

13 files changed

Lines changed: 621 additions & 465 deletions

ews/src/test_utils.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,10 @@ where
4040
let deserialized_data: T = serde_path_to_error::deserialize(&mut deserializer).unwrap();
4141
assert_eq!(deserialized_data, expected);
4242
}
43+
44+
/// Turn the given XML into a single line, stripping leading whitespace.
45+
///
46+
/// Useful for turning readable XML into expected serialized output.
47+
pub fn minify_xml(xml: &str) -> String {
48+
xml.lines().map(str::trim_ascii_start).collect()
49+
}

ews/src/types/common.rs

Lines changed: 76 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,112 +1336,58 @@ mod tests {
13361336

13371337
use super::*;
13381338
use crate::{
1339-
test_utils::{assert_deserialized_content, assert_serialized_content},
1339+
test_utils::{assert_deserialized_content, assert_serialized_content, minify_xml},
13401340
Error,
13411341
};
13421342

1343-
/// Tests that an [`ArrayOfRecipients`] correctly serializes into XML. It
1344-
/// should serialize as multiple `<t:Mailbox>` elements, one per [`Recipient`].
1343+
/// Tests that an [`ArrayOfRecipients`] correctly serializes into XML and
1344+
/// back again. There should be a 1-to-1 correspondence between
1345+
/// `<t:Mailbox>` elements and [`Recipient`]s.
13451346
#[test]
1346-
fn serialize_array_of_recipients() -> Result<(), Error> {
1347-
// Define the recipients to serialize.
1348-
let alice = Recipient {
1349-
mailbox: Mailbox {
1350-
name: Some("Alice Test".into()),
1351-
email_address: Some("alice@test.com".into()),
1352-
routing_type: None,
1353-
mailbox_type: None,
1354-
item_id: None,
1355-
},
1356-
};
1357-
1358-
let bob = Recipient {
1359-
mailbox: Mailbox {
1360-
name: Some("Bob Test".into()),
1361-
email_address: Some("bob@test.com".into()),
1362-
routing_type: None,
1363-
mailbox_type: None,
1364-
item_id: None,
1365-
},
1366-
};
1367-
1368-
let charlie = Recipient {
1369-
mailbox: Mailbox {
1370-
name: Some("Charlie Test".into()),
1371-
email_address: None,
1372-
routing_type: None,
1373-
mailbox_type: None,
1374-
item_id: None,
1375-
},
1376-
};
1377-
1378-
let recipients = ArrayOfRecipients(vec![alice, bob, charlie]);
1379-
1380-
// Ensure the structure of the XML document is correct.
1381-
let expected = "<Recipients><t:Mailbox><t:Name>Alice Test</t:Name><t:EmailAddress>alice@test.com</t:EmailAddress></t:Mailbox><t:Mailbox><t:Name>Bob Test</t:Name><t:EmailAddress>bob@test.com</t:EmailAddress></t:Mailbox><t:Mailbox><t:Name>Charlie Test</t:Name></t:Mailbox></Recipients>";
1382-
1383-
assert_serialized_content(&recipients, "Recipients", expected);
1384-
1385-
Ok(())
1386-
}
1347+
fn test_array_of_recipients() -> Result<(), Error> {
1348+
let xml = minify_xml(
1349+
r#"
1350+
<Recipients>
1351+
<t:Mailbox>
1352+
<t:Name>Alice Test</t:Name>
1353+
<t:EmailAddress>alice@test.com</t:EmailAddress>
1354+
</t:Mailbox>
1355+
<t:Mailbox>
1356+
<t:Name>Bob Test</t:Name>
1357+
<t:EmailAddress>bob@test.com</t:EmailAddress>
1358+
</t:Mailbox>
1359+
<t:Mailbox>
1360+
<t:Name>Charlie Test</t:Name>
1361+
</t:Mailbox>
1362+
</Recipients>"#,
1363+
);
13871364

1388-
/// Tests that deserializing a sequence of `<t:Mailbox>` XML elements
1389-
/// results in an [`ArrayOfRecipients`] with one [`Recipient`] per
1390-
/// `<t:Mailbox>` element.
1391-
#[test]
1392-
fn deserialize_array_of_recipients() -> Result<(), Error> {
1393-
// The raw XML to deserialize.
1394-
let xml = "<Recipients><t:Mailbox><t:Name>Alice Test</t:Name><t:EmailAddress>alice@test.com</t:EmailAddress></t:Mailbox><t:Mailbox><t:Name>Bob Test</t:Name><t:EmailAddress>bob@test.com</t:EmailAddress></t:Mailbox><t:Mailbox><t:Name>Charlie Test</t:Name></t:Mailbox></Recipients>";
1395-
1396-
// Deserialize the raw XML, with `serde_path_to_error` to help
1397-
// troubleshoot any issue.
1398-
let mut de = quick_xml::de::Deserializer::from_reader(xml.as_bytes());
1399-
let recipients: ArrayOfRecipients = serde_path_to_error::deserialize(&mut de)?;
1400-
1401-
// Ensure we have the right number of recipients in the resulting
1402-
// `ArrayOfRecipients`.
1403-
assert_eq!(recipients.0.len(), 3);
1404-
1405-
// Ensure the first recipient correctly has a name and address.
1406-
assert_eq!(
1407-
recipients.first().expect("no recipient at index 0"),
1408-
&Recipient {
1365+
let data = ArrayOfRecipients(vec![
1366+
Recipient {
14091367
mailbox: Mailbox {
14101368
name: Some("Alice Test".into()),
14111369
email_address: Some("alice@test.com".into()),
1412-
routing_type: None,
1413-
mailbox_type: None,
1414-
item_id: None,
1370+
..Default::default()
14151371
},
1416-
}
1417-
);
1418-
1419-
// Ensure the second recipient correctly has a name and address.
1420-
assert_eq!(
1421-
recipients.get(1).expect("no recipient at index 1"),
1422-
&Recipient {
1372+
},
1373+
Recipient {
14231374
mailbox: Mailbox {
14241375
name: Some("Bob Test".into()),
14251376
email_address: Some("bob@test.com".into()),
1426-
routing_type: None,
1427-
mailbox_type: None,
1428-
item_id: None,
1377+
..Default::default()
14291378
},
1430-
}
1431-
);
1432-
1433-
assert_eq!(
1434-
recipients.get(2).expect("no recipient at index 2"),
1435-
&Recipient {
1379+
},
1380+
Recipient {
14361381
mailbox: Mailbox {
14371382
name: Some("Charlie Test".into()),
1438-
email_address: None,
1439-
routing_type: None,
1440-
mailbox_type: None,
1441-
item_id: None
1383+
..Default::default()
14421384
},
1443-
}
1444-
);
1385+
},
1386+
]);
1387+
1388+
assert_serialized_content(&data, "Recipients", &xml);
1389+
1390+
assert_deserialized_content(&xml, data);
14451391

14461392
Ok(())
14471393
}
@@ -1461,31 +1407,36 @@ mod tests {
14611407
value: "data goes here".into(),
14621408
};
14631409

1464-
let xml = r#"<ExtendedProperty><t:ExtendedFieldURI PropertyTag="0x007D" PropertyType="String"/><t:Value>data goes here</t:Value></ExtendedProperty>"#;
1410+
let xml = minify_xml(
1411+
r#"
1412+
<ExtendedProperty>
1413+
<t:ExtendedFieldURI PropertyTag="0x007D" PropertyType="String"/>
1414+
<t:Value>data goes here</t:Value>
1415+
</ExtendedProperty>"#,
1416+
);
14651417

14661418
// Make sure data serializes into expected XML.
1467-
assert_serialized_content(&data, "ExtendedProperty", xml);
1419+
assert_serialized_content(&data, "ExtendedProperty", &xml);
14681420

14691421
// Make sure XML deserializes into expected data.
1470-
assert_deserialized_content(xml, data);
1422+
assert_deserialized_content(&xml, data);
14711423
Ok(())
14721424
}
14731425

14741426
/// Test that attachments are parsed properly
14751427
#[test]
14761428
fn test_attachment_parsing() {
14771429
let item_attachment_xml = r#"
1478-
<m:Attachments>
1479-
<t:ItemAttachment>
1480-
<t:AttachmentId Id="Ktum21o=" />
1481-
<t:Name>Attached Message Item</t:Name>
1482-
<t:ContentType>message/rfc822</t:ContentType>
1483-
<t:Message>
1484-
<t:ItemId Id="AAMkAd" ChangeKey="FwAAABY" />
1485-
</t:Message>
1486-
</t:ItemAttachment>
1487-
</m:Attachments>
1488-
"#;
1430+
<m:Attachments>
1431+
<t:ItemAttachment>
1432+
<t:AttachmentId Id="Ktum21o=" />
1433+
<t:Name>Attached Message Item</t:Name>
1434+
<t:ContentType>message/rfc822</t:ContentType>
1435+
<t:Message>
1436+
<t:ItemId Id="AAMkAd" ChangeKey="FwAAABY" />
1437+
</t:Message>
1438+
</t:ItemAttachment>
1439+
</m:Attachments>"#;
14891440

14901441
let data = Attachments {
14911442
inner: vec![Attachment::ItemAttachment {
@@ -1514,16 +1465,15 @@ mod tests {
15141465
assert_deserialized_content(item_attachment_xml, data);
15151466

15161467
let file_attachment_xml = r#"
1517-
<m:Attachments>
1518-
<t:FileAttachment>
1519-
<t:AttachmentId Id="AAAtAEFkbWluaX..."/>
1520-
<t:Name>SomeFile</t:Name>
1521-
<t:ContentType>message/rfc822</t:ContentType>
1522-
<t:Content>AQIDBAU=</t:Content>
1523-
<t:LastModifiedTime>2026-06-26T17:54:39Z</t:LastModifiedTime>
1524-
</t:FileAttachment>
1525-
</m:Attachments>
1526-
"#;
1468+
<m:Attachments>
1469+
<t:FileAttachment>
1470+
<t:AttachmentId Id="AAAtAEFkbWluaX..."/>
1471+
<t:Name>SomeFile</t:Name>
1472+
<t:ContentType>message/rfc822</t:ContentType>
1473+
<t:Content>AQIDBAU=</t:Content>
1474+
<t:LastModifiedTime>2026-06-26T17:54:39Z</t:LastModifiedTime>
1475+
</t:FileAttachment>
1476+
</m:Attachments>"#;
15271477
let data = Attachments {
15281478
inner: vec![Attachment::FileAttachment {
15291479
attachment_id: AttachmentId {
@@ -1551,8 +1501,9 @@ mod tests {
15511501
#[test]
15521502
/// Attachments sometimes have a `last_modified_time` without a timezone.
15531503
fn test_deserialize_date_time_without_time_zone() {
1554-
let content = r#"<t:Message>
1555-
<t:DateTimeReceived>2026-06-26T17:54:39</t:DateTimeReceived>
1504+
let content = r#"
1505+
<t:Message>
1506+
<t:DateTimeReceived>2026-06-26T17:54:39</t:DateTimeReceived>
15561507
</t:Message>"#;
15571508

15581509
let expected = Message {
@@ -1584,12 +1535,13 @@ mod tests {
15841535

15851536
#[test]
15861537
fn test_deserialize_flag_status() {
1587-
let content = r#"<t:Message>
1588-
<t:Flag>
1589-
<t:FlagStatus>Flagged</t:FlagStatus>
1590-
<t:StartDate>2026-01-26T23:00:00Z</t:StartDate>
1591-
<t:DueDate>2026-01-26T23:00:00Z</t:DueDate>
1592-
</t:Flag>
1538+
let content = r#"
1539+
<t:Message>
1540+
<t:Flag>
1541+
<t:FlagStatus>Flagged</t:FlagStatus>
1542+
<t:StartDate>2026-01-26T23:00:00Z</t:StartDate>
1543+
<t:DueDate>2026-01-26T23:00:00Z</t:DueDate>
1544+
</t:Flag>
15931545
</t:Message>"#;
15941546

15951547
let expected = Message {
@@ -1607,7 +1559,8 @@ mod tests {
16071559

16081560
#[test]
16091561
fn test_deserialize_empty_header() {
1610-
let content = r#"<InternetMessageHeader HeaderName="X-Is-Empty"/>"#;
1562+
let content = r#"
1563+
<InternetMessageHeader HeaderName="X-Is-Empty"/>"#;
16111564
let expected = InternetMessageHeader {
16121565
header_name: "X-Is-Empty".to_string(),
16131566
value: None,

ews/src/types/copy_folder.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct CopyFolder {
2222
mod test {
2323
use crate::{
2424
copy_folder::{CopyFolder, CopyFolderResponse},
25-
test_utils::{assert_deserialized_content, assert_serialized_content},
25+
test_utils::{assert_deserialized_content, assert_serialized_content, minify_xml},
2626
BaseFolderId, CopyMoveFolderData, Folder, FolderId, FolderResponseMessage, Folders,
2727
ResponseClass,
2828
};
@@ -48,27 +48,40 @@ mod test {
4848
},
4949
};
5050

51-
let expected = r#"<CopyFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"><ToFolderId><t:DistinguishedFolderId Id="inbox"/></ToFolderId><FolderIds><t:FolderId Id="AS4A=" ChangeKey="fsVU4=="/><t:FolderId Id="AS4AU=" ChangeKey="fsVU4o=="/></FolderIds></CopyFolder>"#;
51+
let expected = minify_xml(
52+
r#"
53+
<CopyFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
54+
<ToFolderId>
55+
<t:DistinguishedFolderId Id="inbox"/>
56+
</ToFolderId>
57+
<FolderIds>
58+
<t:FolderId Id="AS4A=" ChangeKey="fsVU4=="/>
59+
<t:FolderId Id="AS4AU=" ChangeKey="fsVU4o=="/>
60+
</FolderIds>
61+
</CopyFolder>"#,
62+
);
5263

53-
assert_serialized_content(&copy_folder, "CopyFolder", expected);
64+
assert_serialized_content(&copy_folder, "CopyFolder", &expected);
5465
}
5566

5667
#[test]
5768
fn test_deserialize_copy_folder_response() {
58-
let content = r#"<CopyFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
59-
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
60-
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
61-
<m:ResponseMessages>
62-
<m:CopyFolderResponseMessage ResponseClass="Success">
63-
<m:ResponseCode>NoError</m:ResponseCode>
64-
<m:Folders>
65-
<t:Folder>
66-
<t:FolderId Id="AS4AUn=" ChangeKey="fsVU4o==" />
67-
</t:Folder>
68-
</m:Folders>
69-
</m:CopyFolderResponseMessage>
70-
</m:ResponseMessages>
71-
</CopyFolderResponse>"#;
69+
let content = r#"
70+
<CopyFolderResponse
71+
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
72+
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
73+
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
74+
<m:ResponseMessages>
75+
<m:CopyFolderResponseMessage ResponseClass="Success">
76+
<m:ResponseCode>NoError</m:ResponseCode>
77+
<m:Folders>
78+
<t:Folder>
79+
<t:FolderId Id="AS4AUn=" ChangeKey="fsVU4o==" />
80+
</t:Folder>
81+
</m:Folders>
82+
</m:CopyFolderResponseMessage>
83+
</m:ResponseMessages>
84+
</CopyFolderResponse>"#;
7285

7386
let response = CopyFolderResponse {
7487
response_messages: crate::ResponseMessages {

0 commit comments

Comments
 (0)