lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

gift_wrap.rs (8222B)


      1 #[path = "../src/test_fixtures.rs"]
      2 mod test_fixtures;
      3 
      4 use radroots_events::gift_wrap::{RadrootsGiftWrap, RadrootsGiftWrapRecipient};
      5 use radroots_events::kinds::{KIND_GIFT_WRAP, KIND_MESSAGE};
      6 
      7 use radroots_events_codec::error::{EventEncodeError, EventParseError};
      8 use radroots_events_codec::gift_wrap::decode::{
      9     data_from_event, gift_wrap_from_tags, parsed_from_event,
     10 };
     11 use radroots_events_codec::gift_wrap::encode::{
     12     gift_wrap_build_tags, to_wire_parts, to_wire_parts_with_kind,
     13 };
     14 use test_fixtures::RELAY_PRIMARY_WSS;
     15 
     16 fn sample_gift_wrap() -> RadrootsGiftWrap {
     17     RadrootsGiftWrap {
     18         recipient: RadrootsGiftWrapRecipient {
     19             public_key: "pubkey".to_string(),
     20             relay_url: Some(RELAY_PRIMARY_WSS.to_string()),
     21         },
     22         content: "encrypted".to_string(),
     23         expiration: Some(1700000000),
     24     }
     25 }
     26 
     27 #[test]
     28 fn gift_wrap_build_tags_requires_recipient() {
     29     let mut gift_wrap = sample_gift_wrap();
     30     gift_wrap.recipient.public_key = "  ".to_string();
     31 
     32     let err = gift_wrap_build_tags(&gift_wrap).unwrap_err();
     33     assert!(matches!(
     34         err,
     35         EventEncodeError::EmptyRequiredField("recipient.public_key")
     36     ));
     37 }
     38 
     39 #[test]
     40 fn gift_wrap_to_wire_parts_sets_kind_content_and_tags() {
     41     let gift_wrap = sample_gift_wrap();
     42     let parts = to_wire_parts(&gift_wrap).unwrap();
     43 
     44     assert_eq!(parts.kind, KIND_GIFT_WRAP);
     45     assert_eq!(parts.content, "encrypted");
     46     assert_eq!(
     47         parts.tags,
     48         vec![
     49             vec![
     50                 "p".to_string(),
     51                 "pubkey".to_string(),
     52                 RELAY_PRIMARY_WSS.to_string()
     53             ],
     54             vec!["expiration".to_string(), "1700000000".to_string()],
     55         ]
     56     );
     57 }
     58 
     59 #[test]
     60 fn gift_wrap_from_tags_rejects_wrong_kind() {
     61     let gift_wrap = sample_gift_wrap();
     62     let parts = to_wire_parts(&gift_wrap).unwrap();
     63 
     64     let err = gift_wrap_from_tags(KIND_MESSAGE, &parts.tags, &parts.content).unwrap_err();
     65     assert!(matches!(
     66         err,
     67         EventParseError::InvalidKind {
     68             expected: "1059",
     69             got: KIND_MESSAGE
     70         }
     71     ));
     72 }
     73 
     74 #[test]
     75 fn gift_wrap_from_tags_requires_p_tag() {
     76     let err = gift_wrap_from_tags(KIND_GIFT_WRAP, &[], "payload").unwrap_err();
     77     assert!(matches!(err, EventParseError::MissingTag("p")));
     78 
     79     let err = gift_wrap_from_tags(KIND_GIFT_WRAP, &[vec!["p".to_string()]], "payload").unwrap_err();
     80     assert!(matches!(err, EventParseError::InvalidTag("p")));
     81 }
     82 
     83 #[test]
     84 fn gift_wrap_from_tags_rejects_invalid_expiration_and_relay() {
     85     let err = gift_wrap_from_tags(
     86         KIND_GIFT_WRAP,
     87         &[
     88             vec![
     89                 "p".to_string(),
     90                 "pubkey".to_string(),
     91                 RELAY_PRIMARY_WSS.to_string(),
     92             ],
     93             vec!["expiration".to_string(), " ".to_string()],
     94         ],
     95         "payload",
     96     )
     97     .unwrap_err();
     98     assert!(matches!(err, EventParseError::InvalidTag("expiration")));
     99 
    100     let err = gift_wrap_from_tags(
    101         KIND_GIFT_WRAP,
    102         &[
    103             vec![
    104                 "p".to_string(),
    105                 "pubkey".to_string(),
    106                 RELAY_PRIMARY_WSS.to_string(),
    107             ],
    108             vec!["expiration".to_string(), "invalid".to_string()],
    109         ],
    110         "payload",
    111     )
    112     .unwrap_err();
    113     assert!(matches!(
    114         err,
    115         EventParseError::InvalidNumber("expiration", _)
    116     ));
    117 
    118     let err = gift_wrap_from_tags(
    119         KIND_GIFT_WRAP,
    120         &[vec!["p".to_string(), "pubkey".to_string(), " ".to_string()]],
    121         "payload",
    122     )
    123     .unwrap_err();
    124     assert!(matches!(err, EventParseError::InvalidTag("p")));
    125 }
    126 
    127 #[test]
    128 fn gift_wrap_metadata_and_index_from_event_roundtrip() {
    129     let gift_wrap = sample_gift_wrap();
    130     let parts = to_wire_parts(&gift_wrap).unwrap();
    131 
    132     let metadata = data_from_event(
    133         "id".to_string(),
    134         "author".to_string(),
    135         11,
    136         parts.kind,
    137         parts.content.clone(),
    138         parts.tags.clone(),
    139     )
    140     .unwrap();
    141     assert_eq!(metadata.id, "id");
    142     assert_eq!(metadata.author, "author");
    143     assert_eq!(metadata.published_at, 11);
    144     assert_eq!(
    145         metadata.data.recipient.public_key,
    146         gift_wrap.recipient.public_key
    147     );
    148     assert_eq!(
    149         metadata.data.recipient.relay_url,
    150         gift_wrap.recipient.relay_url
    151     );
    152     assert_eq!(metadata.data.content, gift_wrap.content);
    153     assert_eq!(metadata.data.expiration, gift_wrap.expiration);
    154 
    155     let index = parsed_from_event(
    156         "id".to_string(),
    157         "author".to_string(),
    158         11,
    159         parts.kind,
    160         parts.content,
    161         parts.tags,
    162         "sig".to_string(),
    163     )
    164     .unwrap();
    165     assert_eq!(index.event.kind, KIND_GIFT_WRAP);
    166     assert_eq!(index.event.sig, "sig");
    167     assert_eq!(index.data.data.recipient.public_key, "pubkey");
    168 }
    169 
    170 #[test]
    171 fn gift_wrap_build_tags_handles_optional_expiration_and_invalid_relay() {
    172     let mut gift_wrap = sample_gift_wrap();
    173     gift_wrap.expiration = None;
    174     let tags = gift_wrap_build_tags(&gift_wrap).unwrap();
    175     assert_eq!(
    176         tags,
    177         vec![vec![
    178             "p".to_string(),
    179             "pubkey".to_string(),
    180             RELAY_PRIMARY_WSS.to_string()
    181         ]]
    182     );
    183 
    184     let mut gift_wrap = sample_gift_wrap();
    185     gift_wrap.recipient.relay_url = Some(" ".to_string());
    186     let err = gift_wrap_build_tags(&gift_wrap).unwrap_err();
    187     assert!(matches!(
    188         err,
    189         EventEncodeError::EmptyRequiredField("recipient.relay_url")
    190     ));
    191 
    192     let mut gift_wrap = sample_gift_wrap();
    193     gift_wrap.recipient.relay_url = None;
    194     let tags = gift_wrap_build_tags(&gift_wrap).unwrap();
    195     assert_eq!(tags[0], vec!["p".to_string(), "pubkey".to_string()]);
    196 }
    197 
    198 #[test]
    199 fn gift_wrap_to_wire_parts_requires_content_and_accepts_default_kind() {
    200     let mut gift_wrap = sample_gift_wrap();
    201     gift_wrap.content = " ".to_string();
    202     let err = to_wire_parts(&gift_wrap).unwrap_err();
    203     assert!(matches!(
    204         err,
    205         EventEncodeError::EmptyRequiredField("content")
    206     ));
    207 
    208     let parts = to_wire_parts_with_kind(&sample_gift_wrap(), KIND_GIFT_WRAP).unwrap();
    209     assert_eq!(parts.kind, KIND_GIFT_WRAP);
    210     assert_eq!(parts.content, "encrypted");
    211 
    212     let mut gift_wrap = sample_gift_wrap();
    213     gift_wrap.recipient.public_key = " ".to_string();
    214     let err = to_wire_parts(&gift_wrap).unwrap_err();
    215     assert!(matches!(
    216         err,
    217         EventEncodeError::EmptyRequiredField("recipient.public_key")
    218     ));
    219 }
    220 
    221 #[test]
    222 fn gift_wrap_to_wire_parts_with_kind_rejects_wrong_kind() {
    223     let err = to_wire_parts_with_kind(&sample_gift_wrap(), KIND_MESSAGE).unwrap_err();
    224     assert!(matches!(err, EventEncodeError::InvalidKind(KIND_MESSAGE)));
    225 }
    226 
    227 #[test]
    228 fn gift_wrap_from_tags_handles_missing_expiration_and_rejects_empty_fields() {
    229     let parsed = gift_wrap_from_tags(
    230         KIND_GIFT_WRAP,
    231         &[vec!["p".to_string(), "pubkey".to_string()]],
    232         "payload",
    233     )
    234     .unwrap();
    235     assert_eq!(parsed.recipient.public_key, "pubkey");
    236     assert!(parsed.recipient.relay_url.is_none());
    237     assert!(parsed.expiration.is_none());
    238 
    239     let err = gift_wrap_from_tags(
    240         KIND_GIFT_WRAP,
    241         &[vec!["p".to_string(), " ".to_string()]],
    242         "payload",
    243     )
    244     .unwrap_err();
    245     assert!(matches!(err, EventParseError::InvalidTag("p")));
    246 
    247     let err = gift_wrap_from_tags(
    248         KIND_GIFT_WRAP,
    249         &[vec!["p".to_string(), "pubkey".to_string()]],
    250         " ",
    251     )
    252     .unwrap_err();
    253     assert!(matches!(err, EventParseError::InvalidTag("content")));
    254 }
    255 
    256 #[test]
    257 fn gift_wrap_metadata_and_index_propagate_parse_errors() {
    258     let tags = vec![vec!["p".to_string(), "pubkey".to_string()]];
    259     let err = data_from_event(
    260         "id".to_string(),
    261         "author".to_string(),
    262         11,
    263         KIND_GIFT_WRAP,
    264         " ".to_string(),
    265         tags.clone(),
    266     )
    267     .unwrap_err();
    268     assert!(matches!(err, EventParseError::InvalidTag("content")));
    269 
    270     let err = parsed_from_event(
    271         "id".to_string(),
    272         "author".to_string(),
    273         11,
    274         KIND_GIFT_WRAP,
    275         " ".to_string(),
    276         tags,
    277         "sig".to_string(),
    278     )
    279     .unwrap_err();
    280     assert!(matches!(err, EventParseError::InvalidTag("content")));
    281 }