Files
easy-nostr/src/bin/testall.rs
2026-01-31 16:27:12 +01:00

138 lines
4.6 KiB
Rust

use easy_nostr::EasyNostr;
use nostr_sdk::prelude::*;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("=== EasyNostr Production Test Suite ===");
// 1. Identity
let keys = Keys::generate();
let nsec = keys.secret_key().to_bech32()?;
let npub = keys.public_key().to_bech32()?;
println!("[INFO] Identity: {}", npub);
// 2. Init
let ez = EasyNostr::new(&nsec).await?;
// 3. Relays (More reliable set)
println!("\n[STEP 1] Connecting to Relays...");
let relays = vec![
"wss://relay.damus.io",
"wss://nos.lol",
"wss://relay.primal.net",
];
ez.add_relays(relays).await?;
// Give relays a moment to fully welcome us
sleep(Duration::from_secs(2)).await;
println!(" [OK] Connected.");
// 4. Follow Self (Critical for Timeline Test reliability)
println!("\n[STEP 2] Following Self (for robust timeline testing)...");
ez.create_contact(&npub, Some("Me Myself".to_string()))
.await?;
println!(" [OK] Followed self.");
// 5. Publish Post
println!("\n[STEP 3] Publishing Post...");
let secret_code = format!("Test Run {}", Timestamp::now().as_secs());
let event_id = ez
.post_text(&format!("Hello Nostr! {}", secret_code))
.await?;
println!(" [OK] Posted: {}", event_id.to_bech32()?);
// 6. Verify Timeline (with Retry)
println!("\n[STEP 4] verifying Timeline (expecting own post)...");
let mut found_post = false;
for i in 1..=5 {
sleep(Duration::from_secs(2)).await; // Wait for propagation
let posts = ez.get_timeline(vec![npub.clone()]).await?;
// Look for our specific post
if posts.iter().any(|p| p.content.contains(&secret_code)) {
println!(" [OK] Found our post in timeline after {}s!", i * 2);
found_post = true;
break;
} else {
println!(" ... attempt {}/5: Post not yet visible...", i);
}
}
if !found_post {
println!(" [ERR] Verified Failed: Post did not appear in timeline.");
}
// 7. DM Test (with Retry)
println!("\n[STEP 5] Testing Direct Messages...");
let dm_msg = format!("Secret DM {}", secret_code);
ez.send_private_message(&npub, &dm_msg).await?;
let mut found_dm = false;
for i in 1..=5 {
sleep(Duration::from_secs(2)).await;
let dms = ez.get_private_messages(&npub).await?;
if dms.iter().any(|m| m.content == dm_msg) {
println!(" [OK] Found DM after {}s!", i * 2);
found_dm = true;
break;
} else {
println!(" ... attempt {}/5: DM not yet visible...", i);
}
}
if !found_dm {
println!(" [ERR] DM propagation failed.");
// Non-fatal, DMs are slower
}
// 8. Global feed (Discovery)
println!("\n[STEP 6] testing Global Feed Discovery...");
let random_posts = ez.get_random_posts().await?;
if !random_posts.is_empty() {
println!(" [OK] Found {} random posts.", random_posts.len());
} else {
println!(" [WARN] No random posts found (depends on relay traffic).");
}
// 9. Hashtag search (NIP-12)
println!("\n[STEP 7] Testing Hashtag Search (NIP-12)...");
// We search for something common or wait for propagation of a tagged post.
// For a robust test, we could publish a tagged post, but for now we search for common tags.
let tags = vec!["nostr".to_string(), "bitcoin".to_string()];
let filtered_posts = ez.get_posts_by_hashtags(tags).await?;
if !filtered_posts.is_empty() {
println!(
" [OK] Found {} posts with hashtags.",
filtered_posts.len()
);
} else {
println!(" [WARN] No posts found for tags (depends on relay traffic).");
}
// 10. Metadata Update (Kind 0)
println!("\n[STEP 8] Testing Profile Metadata Update...");
let metadata_id = ez
.set_metadata(
Some("EasyNostr Test Bot".to_string()),
Some("EasyNostr".to_string()),
Some("Automated test for metadata updates".to_string()),
None, // NIP-05
None, // LUD-16
Some("https://github.com/Bytemalte/easy-nostr".to_string()),
Some(
"https://raw.githubusercontent.com/Bytemalte/easy-nostr/main/banner.png"
.to_string(),
),
Some(true), // bot
Some("2024-01-31".to_string()), // birthday
)
.await?;
println!(" [OK] Metadata updated: {}", metadata_id.to_bech32()?);
println!("\n=== Test Complete ===");
Ok(())
}