let url: Url = "gemini://gemini.circumlunar.space".parse().unwrap();
let response = "20 \r\nsome text\r\n";
let body = "some text\r\n";
let mut fui = FakeUi::new();
let mut net = FakeNet::new(FakeConn::new(response.into()));
crate::core::run_url(&mut net, &mut fui, url.clone());
let net_sink = Rc::try_unwrap(net.conn.0).unwrap().into_inner().sink;
let net_sink = String::from_utf8(net_sink).unwrap();
assert_eq!(net_sink, format!("{}\r\n", url));
let ui_sink = fui.sink;
assert_eq!(ui_sink.as_ref(), [FUIEvent::Show]);
}
/// User interface that records method calls and returns canned inputs
#[derive(Default)]
struct FakeUi {
source: Vec<String>,
sink: Vec<FUIEvent>,
}
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
enum FUIEvent {
//TODO figure out how to solve lifetime issues
// and store Media in this variant
// Or just convert it to a string? idk
Show,
Warn(String),
Read(String),
ReadSecret(String),
}
impl FakeUi {
pub fn new() -> Self {
Default::default()
}
}
impl Ui for FakeUi {
fn show(&mut self, content: media::Media) {
self.sink.push(FUIEvent::Show)
}
fn warn<D: Display>(&mut self, warning: D) {
self.sink.push(FUIEvent::Warn(warning.to_string()))
}
fn read(&mut self, prompt: impl Display) -> Option<String> {
self.sink.push(FUIEvent::Read(prompt.to_string()));
self.source.pop()
}
fn read_secret(&mut self, prompt: impl Display) -> Option<String> {
self.sink.push(FUIEvent::ReadSecret(prompt.to_string()));
self.source.pop()
}
}
#[derive(Debug)]
struct FakeNet {
conn: SharedFakeConn,
}
impl FakeNet {
fn new(conn: FakeConn) -> Self {
Self {
conn: SharedFakeConn(Rc::new(RefCell::new(conn))),
}
}
}
#[derive(Clone, Debug)]
struct SharedFakeConn(Rc<RefCell<FakeConn>>);
#[derive(Debug)]
struct FakeConn {
sink: Vec<u8>,
source: Vec<u8>,
}
impl FakeConn {
fn new(source: String) -> Self {
Self {
sink: Vec::new(),
source: source.into_bytes(),
}
}
}
impl Read for SharedFakeConn {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.borrow_mut().read(buf)
}
}
impl Write for SharedFakeConn {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.borrow_mut().write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.0.borrow_mut().flush()
}
}
impl Read for FakeConn {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
(&*self.source).read(buf)
}
}
impl Write for FakeConn {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.sink.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.sink.flush()
}
}
impl Network for FakeNet {
type Error = &'static str;
type Connection = SharedFakeConn;
fn connect(&mut self, _: &Url) -> Result<Self::Connection, Self::Error> {
Ok(self.conn.clone())
}