mod.rs (6969B)
1 #![forbid(unsafe_code)] 2 3 pub mod decode; 4 pub mod encode; 5 pub mod list_sets; 6 7 #[cfg(test)] 8 mod tests { 9 #[cfg(feature = "json")] 10 use crate::coop::decode::coop_from_event; 11 use crate::coop::encode::{coop_build_tags, coop_ref_tags}; 12 use crate::coop::list_sets::{ 13 coop_items_list_set, coop_members_farms_list_set, coop_members_list_set, 14 member_of_coops_list_set, 15 }; 16 use crate::error::EventEncodeError; 17 #[cfg(feature = "json")] 18 use radroots_event::envelope::kind::KIND_COOP; 19 use radroots_event::farm::FarmRef; 20 use radroots_event::farm::change_set::{GcsLocation, GeoJsonPoint, GeoJsonPolygon}; 21 use radroots_event::farm::coop::{Coop, CoopLocation, CoopRef}; 22 23 #[test] 24 fn coop_tags_include_required_fields() { 25 let coop = Coop { 26 d_tag: "BAAAAAAAAAAAAAAAAAAAAA".to_string(), 27 name: "Test Coop".to_string(), 28 about: None, 29 website: None, 30 picture: None, 31 banner: None, 32 location: Some(CoopLocation { 33 primary: None, 34 city: None, 35 region: None, 36 country: None, 37 gcs: GcsLocation { 38 lat: 37.0, 39 lng: -122.0, 40 geohash: "9q8yy".to_string(), 41 point: GeoJsonPoint { 42 r#type: "Point".to_string(), 43 coordinates: [-122.0, 37.0], 44 }, 45 polygon: GeoJsonPolygon { 46 r#type: "Polygon".to_string(), 47 coordinates: vec![vec![ 48 [-122.0, 37.0], 49 [-122.0, 37.0001], 50 [-122.0001, 37.0001], 51 [-122.0, 37.0], 52 ]], 53 }, 54 accuracy: None, 55 altitude: None, 56 tag_0: None, 57 label: None, 58 area: None, 59 elevation: None, 60 soil: None, 61 climate: None, 62 gc_id: None, 63 gc_name: None, 64 gc_admin1_id: None, 65 gc_admin1_name: None, 66 gc_country_id: None, 67 gc_country_name: None, 68 }, 69 }), 70 tags: Some(vec!["regional".to_string()]), 71 }; 72 73 let tags = coop_build_tags(&coop).expect("tags"); 74 assert!(tags.iter().any(|tag| tag.first() == Some(&"d".to_string()))); 75 assert!(tags.iter().any(|tag| tag.first() == Some(&"t".to_string()))); 76 assert!(tags.iter().any(|tag| tag.first() == Some(&"g".to_string()))); 77 } 78 79 #[test] 80 fn coop_ref_tags_include_p_and_a() { 81 let coop = CoopRef { 82 pubkey: "coop_pubkey".to_string(), 83 d_tag: "BAAAAAAAAAAAAAAAAAAAAA".to_string(), 84 }; 85 86 let tags = coop_ref_tags(&coop).expect("coop ref tags"); 87 let has_a = tags 88 .iter() 89 .any(|tag| tag.first().map(|v| v.as_str()) == Some("a")); 90 let has_p = tags 91 .iter() 92 .any(|tag| tag.first().map(|v| v.as_str()) == Some("p")); 93 assert!(has_a); 94 assert!(has_p); 95 96 let err = coop_ref_tags(&CoopRef { 97 pubkey: "coop_pubkey".to_string(), 98 d_tag: "invalid".to_string(), 99 }) 100 .expect_err("expected invalid coop.d_tag"); 101 assert!(matches!(err, EventEncodeError::InvalidField("coop.d_tag"))); 102 } 103 104 #[test] 105 fn coop_build_tags_rejects_invalid_d_tag() { 106 let coop = Coop { 107 d_tag: "invalid".to_string(), 108 name: "Test Coop".to_string(), 109 about: None, 110 website: None, 111 picture: None, 112 banner: None, 113 location: None, 114 tags: None, 115 }; 116 117 let err = coop_build_tags(&coop).expect_err("expected invalid d_tag"); 118 assert!(matches!(err, EventEncodeError::InvalidField("d_tag"))); 119 } 120 121 #[test] 122 #[cfg(feature = "json")] 123 fn coop_decode_rejects_empty_d_tag_and_content() { 124 let coop = Coop { 125 d_tag: "BAAAAAAAAAAAAAAAAAAAAA".to_string(), 126 name: "Test Coop".to_string(), 127 about: None, 128 website: None, 129 picture: None, 130 banner: None, 131 location: None, 132 tags: None, 133 }; 134 let content = serde_json::to_string(&coop).expect("coop content"); 135 136 let empty_d = coop_from_event( 137 KIND_COOP, 138 &[vec!["d".to_string(), " ".to_string()]], 139 &content, 140 ) 141 .expect_err("empty d tag"); 142 assert!(matches!( 143 empty_d, 144 crate::error::EventParseError::InvalidTag("d") 145 )); 146 147 let empty_content = coop_from_event( 148 KIND_COOP, 149 &[vec!["d".to_string(), "BAAAAAAAAAAAAAAAAAAAAA".to_string()]], 150 " ", 151 ) 152 .expect_err("empty content"); 153 assert!(matches!( 154 empty_content, 155 crate::error::EventParseError::InvalidJson("content") 156 )); 157 } 158 159 #[test] 160 fn coop_list_sets_include_expected_tags() { 161 let members = coop_members_list_set("BAAAAAAAAAAAAAAAAAAAAA", ["member_pubkey"]) 162 .expect("members list"); 163 assert_eq!(members.d_tag, "coop:BAAAAAAAAAAAAAAAAAAAAA:members"); 164 assert_eq!(members.entries.len(), 1); 165 assert_eq!(members.entries[0].tag, "p"); 166 167 let err = coop_members_list_set("BAAAAAAAAAAAAAAAAAAAAA", [" "]) 168 .expect_err("expected invalid members entry"); 169 assert!(matches!( 170 err, 171 EventEncodeError::EmptyRequiredField("entry.values") 172 )); 173 174 let farm_members = coop_members_farms_list_set( 175 "BAAAAAAAAAAAAAAAAAAAAA", 176 [FarmRef { 177 pubkey: "farm_pubkey".to_string(), 178 d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), 179 }], 180 ) 181 .expect("farm members list"); 182 assert_eq!( 183 farm_members.d_tag, 184 "coop:BAAAAAAAAAAAAAAAAAAAAA:members.farms" 185 ); 186 assert!(farm_members.entries.iter().any(|entry| entry.tag == "a")); 187 assert!(farm_members.entries.iter().any(|entry| entry.tag == "p")); 188 189 let items = coop_items_list_set( 190 "BAAAAAAAAAAAAAAAAAAAAA", 191 ["30361:coop_pubkey:FAAAAAAAAAAAAAAAAAAAAA"], 192 ) 193 .expect("items list"); 194 assert_eq!(items.d_tag, "coop:BAAAAAAAAAAAAAAAAAAAAA:items"); 195 assert_eq!(items.entries.len(), 1); 196 assert_eq!(items.entries[0].tag, "a"); 197 198 let claims = member_of_coops_list_set(["coop_pubkey"]).expect("claims list"); 199 assert_eq!(claims.d_tag, "member_of.coops"); 200 assert_eq!(claims.entries.len(), 1); 201 assert_eq!(claims.entries[0].tag, "p"); 202 } 203 }