lib

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

commit a8c83655b40f5a85265c27fb12f4c5165632cda2
parent 30cb226d21a1709252b2cfd1914ce3c42640dcd0
Author: triesap <tyson@radroots.org>
Date:   Sun, 21 Jun 2026 20:30:13 +0000

events-codec: expand profile decode coverage

- Cover optional profile metadata extraction, invalid scalar bot handling, and non-object JSON rejection.

- Exercise profile type tag selection across short, unrelated, unknown, and later valid tags.

- Assert parsed profile events preserve wire event fields and decoded profile data.

- Validate focused profile tests, full radroots_events_codec tests, crate check, diff check, and refreshed coverage run.

Diffstat:
Mcrates/events_codec/tests/profile.rs | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 98 insertions(+), 8 deletions(-)

diff --git a/crates/events_codec/tests/profile.rs b/crates/events_codec/tests/profile.rs @@ -1,14 +1,17 @@ #![cfg(feature = "serde_json")] use radroots_events::{ - kinds::KIND_POST, + kinds::{KIND_POST, KIND_PROFILE}, profile::{ - RADROOTS_PROFILE_TYPE_TAG_ANY, RADROOTS_PROFILE_TYPE_TAG_FARM, - RADROOTS_PROFILE_TYPE_TAG_KEY, RADROOTS_PROFILE_TYPE_TAG_RADROOTSD, RadrootsProfileType, + RADROOTS_PROFILE_TYPE_TAG_ANY, RADROOTS_PROFILE_TYPE_TAG_COOP, + RADROOTS_PROFILE_TYPE_TAG_FARM, RADROOTS_PROFILE_TYPE_TAG_KEY, + RADROOTS_PROFILE_TYPE_TAG_RADROOTSD, RadrootsProfileType, }, }; use radroots_events_codec::error::EventParseError; -use radroots_events_codec::profile::decode::profile_from_content; +use radroots_events_codec::profile::decode::{ + data_from_event, parsed_from_event, profile_from_content, +}; #[test] fn profile_from_content_parses_bot_boolean() { @@ -29,6 +32,32 @@ fn profile_from_content_parses_bot_string() { } #[test] +fn profile_from_content_parses_optional_metadata_and_ignores_invalid_scalars() { + 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}"#; + let profile = profile_from_content(content).unwrap(); + + assert_eq!(profile.name, "alice"); + assert_eq!(profile.display_name.as_deref(), Some("Alice")); + assert_eq!(profile.nip05.as_deref(), Some("alice@example.test")); + assert_eq!(profile.about.as_deref(), Some("farm account")); + assert_eq!( + profile.website.as_deref(), + Some("https://farm.example.test") + ); + assert_eq!( + profile.picture.as_deref(), + Some("https://farm.example.test/pic.png") + ); + assert_eq!( + profile.banner.as_deref(), + Some("https://farm.example.test/banner.png") + ); + assert_eq!(profile.lud06.as_deref(), Some("lnurl1farm")); + assert_eq!(profile.lud16.as_deref(), Some("alice@example.test")); + assert_eq!(profile.bot, None); +} + +#[test] fn profile_from_content_rejects_missing_name() { let content = r#"{"display_name":"alice"}"#; let err = profile_from_content(content).unwrap_err(); @@ -36,6 +65,12 @@ fn profile_from_content_rejects_missing_name() { } #[test] +fn profile_from_content_rejects_non_object_json() { + let err = profile_from_content("[]").unwrap_err(); + assert!(matches!(err, EventParseError::InvalidJson("content"))); +} + +#[test] fn profile_from_content_rejects_invalid_json() { let err = profile_from_content("{").unwrap_err(); assert!(matches!(err, EventParseError::InvalidJson("content"))); @@ -43,7 +78,7 @@ fn profile_from_content_rejects_invalid_json() { #[test] fn profile_metadata_rejects_wrong_kind() { - let err = radroots_events_codec::profile::decode::data_from_event( + let err = data_from_event( "id".to_string(), "author".to_string(), 1, @@ -64,7 +99,7 @@ fn profile_metadata_rejects_wrong_kind() { #[test] fn profile_metadata_reads_profile_type_tag() { - let metadata = radroots_events_codec::profile::decode::data_from_event( + let metadata = data_from_event( "id".to_string(), "author".to_string(), 1, @@ -82,7 +117,7 @@ fn profile_metadata_reads_profile_type_tag() { #[test] fn profile_metadata_reads_profile_type_any_tag() { - let metadata = radroots_events_codec::profile::decode::data_from_event( + let metadata = data_from_event( "id".to_string(), "author".to_string(), 1, @@ -100,7 +135,7 @@ fn profile_metadata_reads_profile_type_any_tag() { #[test] fn profile_metadata_reads_profile_type_radrootsd_tag() { - let metadata = radroots_events_codec::profile::decode::data_from_event( + let metadata = data_from_event( "id".to_string(), "author".to_string(), 1, @@ -118,3 +153,58 @@ fn profile_metadata_reads_profile_type_radrootsd_tag() { Some(RadrootsProfileType::Radrootsd) ); } + +#[test] +fn profile_metadata_ignores_short_unknown_and_unrelated_profile_type_tags() { + let metadata = data_from_event( + "id".to_string(), + "author".to_string(), + 1, + KIND_PROFILE, + "{\"name\":\"alice\"}".to_string(), + vec![ + vec![RADROOTS_PROFILE_TYPE_TAG_KEY.to_string()], + vec![ + RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(), + "radroots:type:unknown".to_string(), + ], + vec!["x".to_string(), RADROOTS_PROFILE_TYPE_TAG_COOP.to_string()], + vec![ + RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(), + RADROOTS_PROFILE_TYPE_TAG_COOP.to_string(), + ], + ], + ) + .expect("metadata"); + + assert_eq!(metadata.data.profile_type, Some(RadrootsProfileType::Coop)); +} + +#[test] +fn profile_parsed_event_preserves_wire_event_and_decoded_data() { + let parsed = parsed_from_event( + "event-id".to_string(), + "author-pubkey".to_string(), + 42, + KIND_PROFILE, + "{\"name\":\"alice\"}".to_string(), + vec![vec![ + RADROOTS_PROFILE_TYPE_TAG_KEY.to_string(), + RADROOTS_PROFILE_TYPE_TAG_FARM.to_string(), + ]], + "event-sig".to_string(), + ) + .expect("parsed profile"); + + assert_eq!(parsed.event.id, "event-id"); + assert_eq!(parsed.event.author, "author-pubkey"); + assert_eq!(parsed.event.created_at, 42); + assert_eq!(parsed.event.kind, KIND_PROFILE); + assert_eq!(parsed.event.content, "{\"name\":\"alice\"}"); + assert_eq!(parsed.event.sig, "event-sig"); + assert_eq!(parsed.data.data.profile.name, "alice"); + assert_eq!( + parsed.data.data.profile_type, + Some(RadrootsProfileType::Farm) + ); +}