vertigo 0.11.3

Reactive Real-DOM library with SSR for Rust
Documentation
use std::rc::Rc;
use vertigo_macro::store;

use super::{CallbackStore, api_browser_command};
#[cfg(test)]
use crate::dev::ValueMut;
use crate::dev::{CallbackId, FutureBox, SsrFetchRequest, SsrFetchResponse};

#[store]
pub fn api_fetch() -> Rc<ApiFetch> {
    ApiFetch::new()
}

#[cfg(test)]
type MockFetchHandler =
    crate::dev::ValueMut<Option<Rc<dyn Fn(SsrFetchRequest) -> SsrFetchResponse>>>;

pub struct ApiFetch {
    #[cfg(test)]
    mock_handler: MockFetchHandler,
    store: CallbackStore<SsrFetchResponse, ()>,
}

impl ApiFetch {
    fn new() -> Rc<ApiFetch> {
        Rc::new(ApiFetch {
            #[cfg(test)]
            mock_handler: ValueMut::new(None),
            store: CallbackStore::new(),
        })
    }

    #[cfg(test)]
    pub fn set_mock_handler(
        &self,
        handler: impl Fn(SsrFetchRequest) -> SsrFetchResponse + 'static,
    ) {
        self.mock_handler.set(Some(Rc::new(handler)));
    }

    pub async fn fetch(&self, request: SsrFetchRequest) -> SsrFetchResponse {
        #[cfg(test)]
        if let Some(handler) = self.mock_handler.get() {
            return handler(request);
        }

        let (sender, receiver) = FutureBox::<SsrFetchResponse>::new();

        let callback = self.store.register_once(move |response| {
            sender.publish(response);
        });

        api_browser_command().fetch_exec(request, callback);

        receiver.await
    }

    pub fn callback(&self, callback: CallbackId, response: SsrFetchResponse) {
        self.store.call(callback, response);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::FetchMethod;
    use crate::dev::{SsrFetchRequestBody, SsrFetchResponseContent};
    use std::collections::BTreeMap;

    #[tokio::test]
    async fn test_mock_fetch() {
        let api = api_fetch();

        api.set_mock_handler(|request| {
            assert_eq!(request.url, "https://test.com");
            SsrFetchResponse::Ok {
                status: 200,
                response: SsrFetchResponseContent::Text("mocked response".to_string()),
            }
        });

        let request = SsrFetchRequest {
            method: FetchMethod::GET,
            url: "https://test.com".to_string(),
            headers: BTreeMap::new(),
            body: SsrFetchRequestBody::None,
        };

        let response = api.fetch(request).await;

        match response {
            SsrFetchResponse::Ok { status, response } => {
                assert_eq!(status, 200);
                match response {
                    SsrFetchResponseContent::Text(text) => {
                        assert_eq!(text, "mocked response");
                    }
                    _ => panic!("Expected text response"),
                }
            }
            _ => panic!("Expected Ok response"),
        }
    }
}