mod common;
use jmap_metadata_types::{
DataTypeMetadataInfo, JMAP_METADATA_URI, MetadataTextMatch, WithMetadata,
is_registered_namespace, is_valid_namespace, is_vendor_namespace,
};
#[test]
fn capability_uri_matches_draft_02() {
assert_eq!(JMAP_METADATA_URI, "urn:ietf:params:jmap:metadata");
}
#[test]
fn data_type_metadata_info_draft_02_section_6_1() {
let json = &common::fixture("data_type_metadata_info_draft_02_section_6_1.json");
let info: DataTypeMetadataInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.namespaces, vec!["photography"]);
assert!(!info.supports_vendor_namespaces);
assert!(!info.supports_private);
assert_eq!(info.max_depth, Some(3));
}
#[test]
fn data_type_metadata_info_draft_02_full_support() {
let json = &common::fixture("data_type_metadata_info_draft_02_full_support.json");
let info: DataTypeMetadataInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.namespaces, vec!["photography", "workflow"]);
assert!(info.supports_vendor_namespaces);
assert!(info.supports_private);
assert_eq!(info.max_depth, None);
}
#[test]
fn data_type_metadata_info_defaults() {
let json = &common::fixture("data_type_metadata_info_defaults.json");
let info: DataTypeMetadataInfo = serde_json::from_str(json).unwrap();
assert!(info.namespaces.is_empty());
assert!(!info.supports_vendor_namespaces);
assert!(!info.supports_private);
assert_eq!(info.max_depth, None);
}
#[test]
fn data_type_metadata_info_round_trip() {
let json = &common::fixture("data_type_metadata_info_round_trip.json");
let info: DataTypeMetadataInfo = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_value(&info).unwrap();
let reparsed: DataTypeMetadataInfo = serde_json::from_value(serialized).unwrap();
assert_eq!(info, reparsed);
}
#[test]
fn data_type_metadata_info_max_depth_null_round_trips() {
let json = &common::fixture("data_type_metadata_info_max_depth_null_round_trips.json");
let info: DataTypeMetadataInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.max_depth, None);
let reser = serde_json::to_value(&info).unwrap();
assert!(reser["maxDepth"].is_null());
}
#[test]
fn metadata_text_match_draft_02_section_6_7() {
let json = &common::fixture("metadata_text_match_draft_02_section_6_7.json");
let m: MetadataTextMatch = serde_json::from_str(json).unwrap();
assert_eq!(m.path, "acme.example.com/memo");
assert_eq!(m.value, "follow up");
}
#[test]
fn metadata_text_match_round_trip() {
let json = &common::fixture("metadata_text_match_round_trip.json");
let m: MetadataTextMatch = serde_json::from_str(json).unwrap();
let reser = serde_json::to_value(&m).unwrap();
let reparsed: MetadataTextMatch = serde_json::from_value(reser).unwrap();
assert_eq!(m, reparsed);
}
#[test]
fn metadata_text_match_namespace_only_path() {
let json = &common::fixture("metadata_text_match_namespace_only_path.json");
let m: MetadataTextMatch = serde_json::from_str(json).unwrap();
assert_eq!(m.path, "photography");
assert_eq!(m.value, "beach");
}
#[test]
fn registered_namespace_accepts_valid() {
assert!(is_registered_namespace("photography"));
assert!(is_registered_namespace("my-namespace_v2"));
assert!(is_registered_namespace("a"));
assert!(is_registered_namespace("a1-b2_c3"));
}
#[test]
fn registered_namespace_rejects_invalid() {
assert!(!is_registered_namespace(""));
assert!(!is_registered_namespace("has.dot"));
assert!(!is_registered_namespace("has space"));
assert!(!is_registered_namespace("foo@bar"));
assert!(!is_registered_namespace("A1-b2_c3"));
}
#[test]
fn vendor_namespace_accepts_valid() {
assert!(is_vendor_namespace("acme.example.com"));
assert!(is_vendor_namespace("a.b"));
}
#[test]
fn vendor_namespace_rejects_invalid() {
assert!(!is_vendor_namespace("nodot"));
assert!(!is_vendor_namespace(""));
assert!(!is_vendor_namespace(".leading"));
assert!(!is_vendor_namespace("trailing."));
assert!(!is_vendor_namespace("a..b"));
assert!(!is_vendor_namespace("a. b"));
assert!(!is_vendor_namespace("Acme.example.com"));
}
#[test]
fn valid_namespace_accepts_both_kinds() {
assert!(is_valid_namespace("photography"));
assert!(is_valid_namespace("acme.example.com"));
}
#[test]
fn valid_namespace_rejects_invalid() {
assert!(!is_valid_namespace(""));
assert!(!is_valid_namespace("has space"));
assert!(!is_valid_namespace(".leading"));
}
#[derive(Default, serde::Serialize)]
#[serde(rename_all = "camelCase")]
struct EmailCondStub {
#[serde(skip_serializing_if = "Option::is_none")]
in_mailbox: Option<String>,
}
#[test]
fn with_metadata_draft_02_section_3_5_all_fields() {
let mut cond = WithMetadata::<EmailCondStub>::default();
cond.base.in_mailbox = Some("MB-inbox".into());
cond.metadata_exists = Some("photography".into());
cond.private_metadata_exists = Some("acme.example.com/memo".into());
cond.metadata_text_contains = Some(MetadataTextMatch::new("photography/album", "sun"));
cond.private_metadata_text_contains =
Some(MetadataTextMatch::new("acme.example.com/memo", "follow up"));
cond.metadata_text_equals = Some(MetadataTextMatch::new("photography/album", "Sunset"));
cond.private_metadata_text_equals = Some(MetadataTextMatch::new("acme.example.com/tag", "x"));
let expected = serde_json::json!({
"inMailbox": "MB-inbox",
"metadataExists": "photography",
"privateMetadataExists": "acme.example.com/memo",
"metadataTextContains": {"path": "photography/album", "value": "sun"},
"privateMetadataTextContains": {"path": "acme.example.com/memo", "value": "follow up"},
"metadataTextEquals": {"path": "photography/album", "value": "Sunset"},
"privateMetadataTextEquals": {"path": "acme.example.com/tag", "value": "x"}
});
assert_eq!(serde_json::to_value(&cond).unwrap(), expected);
}
#[test]
fn with_metadata_unset_fields_are_omitted() {
let mut cond = WithMetadata::<EmailCondStub>::default();
cond.metadata_exists = Some("photography".into());
assert_eq!(
serde_json::to_value(&cond).unwrap(),
serde_json::json!({"metadataExists": "photography"})
);
}