lib

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

profile.rs (6408B)


      1 #![cfg(feature = "serde_json")]
      2 
      3 use radroots_events::{
      4     kinds::{KIND_POST, KIND_PROFILE},
      5     profile::{
      6         RADROOTS_PROFILE_TYPE_TAG_ANY, RADROOTS_PROFILE_TYPE_TAG_COOP,
      7         RADROOTS_PROFILE_TYPE_TAG_FARM, RADROOTS_PROFILE_TYPE_TAG_KEY,
      8         RADROOTS_PROFILE_TYPE_TAG_RADROOTSD, RadrootsProfileType,
      9     },
     10 };
     11 use radroots_events_codec::error::EventParseError;
     12 use radroots_events_codec::profile::decode::{
     13     data_from_event, parsed_from_event, profile_from_content,
     14 };
     15 
     16 #[test]
     17 fn profile_from_content_parses_bot_boolean() {
     18     let content = r#"{"name":"alice","bot":true}"#;
     19     let profile = profile_from_content(content).unwrap();
     20 
     21     assert_eq!(profile.name, "alice");
     22     assert_eq!(profile.bot.as_deref(), Some("true"));
     23 }
     24 
     25 #[test]
     26 fn profile_from_content_parses_bot_string() {
     27     let content = r#"{"name":"alice","bot":"false"}"#;
     28     let profile = profile_from_content(content).unwrap();
     29 
     30     assert_eq!(profile.name, "alice");
     31     assert_eq!(profile.bot.as_deref(), Some("false"));
     32 }
     33 
     34 #[test]
     35 fn profile_from_content_parses_optional_metadata_and_ignores_invalid_scalars() {
     36     let content = r#"{"name":"alice","display_name":"Alice","nip05":"alice@example.test","about":"farm account","website":"https://farm.example.test","picture":"https://farm.example.test/pic.png","banner":"https://farm.example.test/banner.png","lud06":"lnurl1farm","lud16":"alice@example.test","bot":12}"#;
     37     let profile = profile_from_content(content).unwrap();
     38 
     39     assert_eq!(profile.name, "alice");
     40     assert_eq!(profile.display_name.as_deref(), Some("Alice"));
     41     assert_eq!(profile.nip05.as_deref(), Some("alice@example.test"));
     42     assert_eq!(profile.about.as_deref(), Some("farm account"));
     43     assert_eq!(
     44         profile.website.as_deref(),
     45         Some("https://farm.example.test")
     46     );
     47     assert_eq!(
     48         profile.picture.as_deref(),
     49         Some("https://farm.example.test/pic.png")
     50     );
     51     assert_eq!(
     52         profile.banner.as_deref(),
     53         Some("https://farm.example.test/banner.png")
     54     );
     55     assert_eq!(profile.lud06.as_deref(), Some("lnurl1farm"));
     56     assert_eq!(profile.lud16.as_deref(), Some("alice@example.test"));
     57     assert_eq!(profile.bot, None);
     58 }
     59 
     60 #[test]
     61 fn profile_from_content_rejects_missing_name() {
     62     let content = r#"{"display_name":"alice"}"#;
     63     let err = profile_from_content(content).unwrap_err();
     64     assert!(matches!(err, EventParseError::InvalidJson("name")));
     65 }
     66 
     67 #[test]
     68 fn profile_from_content_rejects_non_object_json() {
     69     let err = profile_from_content("[]").unwrap_err();
     70     assert!(matches!(err, EventParseError::InvalidJson("content")));
     71 }
     72 
     73 #[test]
     74 fn profile_from_content_rejects_invalid_json() {
     75     let err = profile_from_content("{").unwrap_err();
     76     assert!(matches!(err, EventParseError::InvalidJson("content")));
     77 }
     78 
     79 #[test]
     80 fn profile_metadata_rejects_wrong_kind() {
     81     let err = data_from_event(
     82         "id".to_string(),
     83         "author".to_string(),
     84         1,
     85         1,
     86         "{\"name\":\"alice\"}".to_string(),
     87         Vec::new(),
     88     )
     89     .unwrap_err();
     90 
     91     assert!(matches!(
     92         err,
     93         EventParseError::InvalidKind {
     94             expected: "0",
     95             got: KIND_POST
     96         }
     97     ));
     98 }
     99 
    100 #[test]
    101 fn profile_metadata_reads_profile_type_tag() {
    102     let metadata = data_from_event(
    103         "id".to_string(),
    104         "author".to_string(),
    105         1,
    106         0,
    107         "{\"name\":\"alice\"}".to_string(),
    108         vec![vec![
    109             RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    110             RADROOTS_PROFILE_TYPE_TAG_FARM.to_string(),
    111         ]],
    112     )
    113     .expect("metadata");
    114 
    115     assert_eq!(metadata.data.profile_type, Some(RadrootsProfileType::Farm));
    116 }
    117 
    118 #[test]
    119 fn profile_metadata_reads_profile_type_any_tag() {
    120     let metadata = data_from_event(
    121         "id".to_string(),
    122         "author".to_string(),
    123         1,
    124         0,
    125         "{\"name\":\"alice\"}".to_string(),
    126         vec![vec![
    127             RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    128             RADROOTS_PROFILE_TYPE_TAG_ANY.to_string(),
    129         ]],
    130     )
    131     .expect("metadata");
    132 
    133     assert_eq!(metadata.data.profile_type, Some(RadrootsProfileType::Any));
    134 }
    135 
    136 #[test]
    137 fn profile_metadata_reads_profile_type_radrootsd_tag() {
    138     let metadata = data_from_event(
    139         "id".to_string(),
    140         "author".to_string(),
    141         1,
    142         0,
    143         "{\"name\":\"alice\"}".to_string(),
    144         vec![vec![
    145             RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    146             RADROOTS_PROFILE_TYPE_TAG_RADROOTSD.to_string(),
    147         ]],
    148     )
    149     .expect("metadata");
    150 
    151     assert_eq!(
    152         metadata.data.profile_type,
    153         Some(RadrootsProfileType::Radrootsd)
    154     );
    155 }
    156 
    157 #[test]
    158 fn profile_metadata_ignores_short_unknown_and_unrelated_profile_type_tags() {
    159     let metadata = data_from_event(
    160         "id".to_string(),
    161         "author".to_string(),
    162         1,
    163         KIND_PROFILE,
    164         "{\"name\":\"alice\"}".to_string(),
    165         vec![
    166             vec![RADROOTS_PROFILE_TYPE_TAG_KEY.to_string()],
    167             vec![
    168                 RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    169                 "radroots:type:unknown".to_string(),
    170             ],
    171             vec!["x".to_string(), RADROOTS_PROFILE_TYPE_TAG_COOP.to_string()],
    172             vec![
    173                 RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    174                 RADROOTS_PROFILE_TYPE_TAG_COOP.to_string(),
    175             ],
    176         ],
    177     )
    178     .expect("metadata");
    179 
    180     assert_eq!(metadata.data.profile_type, Some(RadrootsProfileType::Coop));
    181 }
    182 
    183 #[test]
    184 fn profile_parsed_event_preserves_wire_event_and_decoded_data() {
    185     let parsed = parsed_from_event(
    186         "event-id".to_string(),
    187         "author-pubkey".to_string(),
    188         42,
    189         KIND_PROFILE,
    190         "{\"name\":\"alice\"}".to_string(),
    191         vec![vec![
    192             RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(),
    193             RADROOTS_PROFILE_TYPE_TAG_FARM.to_string(),
    194         ]],
    195         "event-sig".to_string(),
    196     )
    197     .expect("parsed profile");
    198 
    199     assert_eq!(parsed.event.id, "event-id");
    200     assert_eq!(parsed.event.author, "author-pubkey");
    201     assert_eq!(parsed.event.created_at, 42);
    202     assert_eq!(parsed.event.kind, KIND_PROFILE);
    203     assert_eq!(parsed.event.content, "{\"name\":\"alice\"}");
    204     assert_eq!(parsed.event.sig, "event-sig");
    205     assert_eq!(parsed.data.data.profile.name, "alice");
    206     assert_eq!(
    207         parsed.data.data.profile_type,
    208         Some(RadrootsProfileType::Farm)
    209     );
    210 }