braze_sync/resource/
tag.rs1use serde::{Deserialize, Serialize};
18
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20pub struct TagRegistry {
21 pub tags: Vec<Tag>,
22}
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25pub struct Tag {
26 pub name: String,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub description: Option<String>,
29}
30
31impl TagRegistry {
32 pub fn normalized(&self) -> Self {
33 let mut sorted = self.clone();
34 sorted.tags.sort_by(|a, b| a.name.cmp(&b.name));
35 sorted
36 }
37
38 pub fn contains(&self, name: &str) -> bool {
39 self.tags.iter().any(|t| t.name == name)
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn registry_yaml_roundtrip() {
49 let r = TagRegistry {
50 tags: vec![
51 Tag {
52 name: "campaign".into(),
53 description: None,
54 },
55 Tag {
56 name: "ad_slot/dialog".into(),
57 description: Some("Dialog ad slot".into()),
58 },
59 ],
60 };
61 let yaml = serde_norway::to_string(&r).unwrap();
62 let parsed: TagRegistry = serde_norway::from_str(&yaml).unwrap();
63 assert_eq!(r, parsed);
64 }
65
66 #[test]
67 fn normalized_sorts_tags_by_name() {
68 let r = TagRegistry {
69 tags: vec![
70 Tag {
71 name: "z".into(),
72 description: None,
73 },
74 Tag {
75 name: "a".into(),
76 description: None,
77 },
78 ],
79 };
80 let n = r.normalized();
81 assert_eq!(n.tags[0].name, "a");
82 assert_eq!(n.tags[1].name, "z");
83 }
84
85 #[test]
86 fn description_none_is_omitted_in_output() {
87 let r = TagRegistry {
88 tags: vec![Tag {
89 name: "x".into(),
90 description: None,
91 }],
92 };
93 let yaml = serde_norway::to_string(&r).unwrap();
94 assert!(!yaml.contains("description"));
95 }
96
97 #[test]
98 fn contains_finds_existing_name() {
99 let r = TagRegistry {
100 tags: vec![Tag {
101 name: "promo".into(),
102 description: None,
103 }],
104 };
105 assert!(r.contains("promo"));
106 assert!(!r.contains("missing"));
107 }
108}