From 000901c0cbca8464b5a89bcc93c5474f6564bafd Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Sun, 1 Oct 2023 00:00:00 +0100 Subject: feat(prs-create) send to multiple relays add tests but these currently don't work when run together --- test_utils/src/relay.rs | 196 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 test_utils/src/relay.rs (limited to 'test_utils/src/relay.rs') diff --git a/test_utils/src/relay.rs b/test_utils/src/relay.rs new file mode 100644 index 0000000..6de3618 --- /dev/null +++ b/test_utils/src/relay.rs @@ -0,0 +1,196 @@ +use std::collections::HashMap; + +use anyhow::{bail, Result}; +use nostr::{ClientMessage, RelayMessage}; + +use crate::CliTester; + +type ListenerFunc<'a> = &'a dyn Fn(&mut Relay, u64, nostr::Event) -> Result<()>; + +pub struct Relay<'a> { + port: u16, + event_hub: simple_websockets::EventHub, + clients: HashMap, + pub events: Vec, + event_listener: Option>, +} + +impl<'a> Relay<'a> { + pub fn new(port: u16, event_listener: Option>) -> Self { + let event_hub = simple_websockets::launch(port) + .unwrap_or_else(|_| panic!("failed to listen on port {port}")); + Self { + port, + events: vec![], + event_hub, + clients: HashMap::new(), + event_listener, + } + } + pub fn respond_ok( + &self, + client_id: u64, + event: nostr::Event, + error: Option<&str>, + ) -> Result { + let responder = self.clients.get(&client_id).unwrap(); + + let ok_json = RelayMessage::Ok { + event_id: event.id, + status: error.is_none(), + message: error.unwrap_or("").to_string(), + } + .as_json(); + // bail!(format!("{}", &ok_json)); + Ok(responder.send(simple_websockets::Message::Text(ok_json))) + } + /// listen, collect events and responds with event_listener to events or + /// Ok(eventid) if event_listner is None + pub async fn listen_until_close(&mut self) -> Result<()> { + loop { + println!("polling"); + match self.event_hub.poll_async().await { + simple_websockets::Event::Connect(client_id, responder) => { + // add their Responder to our `clients` map: + self.clients.insert(client_id, responder); + } + simple_websockets::Event::Disconnect(client_id) => { + // remove the disconnected client from the clients map: + println!("{} disconnected", self.port); + self.clients.remove(&client_id); + break; + } + simple_websockets::Event::Message(client_id, message) => { + println!( + "Received a message from client #{}: {:?}", + client_id, message + ); + + if let Ok(event) = get_nevent(message) { + self.events.push(event.clone()); + if let Some(listner) = self.event_listener { + listner(self, client_id, event)?; + } else { + self.respond_ok(client_id, event, None)?; + } + } + } + } + } + println!("stop polling"); + println!("we may not be polling but the tcplistner is still listening"); + Ok(()) + } +} + +fn get_nevent(message: simple_websockets::Message) -> Result { + if let simple_websockets::Message::Text(s) = message.clone() { + let cm_result = ClientMessage::from_json(s); + if let Ok(ClientMessage::Event(event)) = cm_result { + let e = *event; + return Ok(e.clone()); + } + } + bail!("not nostr event") +} + +pub enum Message { + Event, + // Request, +} + +/// leaves trailing whitespace and only compatible with --no-cli-spinners flag +/// relays tuple: (title,successful,message) +pub fn expect_send_with_progress( + p: &mut CliTester, + relays: Vec<(&str, bool, &str)>, + event_count: u16, +) -> Result<()> { + p.expect(format!( + " - {} -------------------- 0/{event_count}", + &relays[0].0 + ))?; + for relay in &relays { + // if successful + if relay.1 { + p.expect_eventually(format!(" y {}", relay.0))?; + } else { + p.expect_eventually(format!(" x {} {}", relay.0, relay.2))?; + } + // could check that before only contains titles: + // - # y x n/n and whitespace + // let before = p.expect_eventually(format!(" â {title}"))?; + // assert_eq!("", before.trim()); + } + Ok(()) +} + +pub fn expect_send_with_progress_exact_interaction( + p: &mut CliTester, + titles: Vec<&str>, + count: u16, +) -> Result<()> { + let whitespace_mid = " \r\n"; + let whitespace_end = " \r\r\r"; + + p.expect(format!( + " - {} -------------------- 0/{count} \r", + titles[0] + ))?; + p.expect(format!( + " - {} -------------------- 0/{count}{whitespace_mid}", + titles[0] + ))?; + p.expect(format!( + " - {} -------------------- 0/{count} \r\r", + titles[1] + ))?; + + let generate_text = |title: &str, num: u16, confirmed_complete: bool| -> String { + let symbol = if confirmed_complete && num.eq(&count) { + "â" + } else { + "-" + }; + let bar = match (num, count) { + (0, _) => "--------------------", + (1, 2) => "###########---------", + (x, y) => { + if x.eq(&y) { + "####################" + } else { + "--unknown--" + } + } + }; + format!( + " {symbol} {title} {bar} {num}/{count}{}", + if (&title).eq(titles.last().unwrap()) { + whitespace_end + } else { + whitespace_mid + } + ) + }; + let mut nums: HashMap<&str, u16> = HashMap::new(); + for title in &titles { + nums.insert(title, 0); + p.expect(generate_text(title, 0, false))?; + } + loop { + for selected_title in &titles { + for title in &titles { + if title.eq(selected_title) { + let new_num = nums.get(title).unwrap() + 1; + if new_num.gt(&count) { + return Ok(()); + } + nums.insert(title, new_num); + p.expect(generate_text(title, *nums.get(title).unwrap(), false))?; + } else { + p.expect(generate_text(title, *nums.get(title).unwrap(), true))?; + } + } + } + } +} -- cgit v1.2.3