use futures::future::BoxFuture;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use crate::coding::error::WebFetchError;
use crate::coding::tools::web_fetch::{HttpClient, HttpResponse};
#[derive(Debug, Clone, Default)]
pub struct FakeHttpClient {
responses: Arc<Mutex<HashMap<String, Result<HttpResponse, WebFetchError>>>>,
}
impl FakeHttpClient {
pub fn with_response(self, url: &str, response: HttpResponse) -> Self {
self.with_result(url, Ok(response))
}
pub fn with_html(self, url: &str, html: &str) -> Self {
self.with_response(
url,
HttpResponse {
final_url: url.to_string(),
status_code: 200,
body: html.to_string(),
content_type: Some("text/html".to_string()),
},
)
}
pub fn with_timeout(self, url: &str, timeout_ms: u64) -> Self {
self.with_result(url, Err(WebFetchError::Timeout(timeout_ms)))
}
pub fn with_request_failed(self, url: &str, message: &str) -> Self {
self.with_result(url, Err(WebFetchError::RequestFailed(message.to_string())))
}
fn with_result(self, url: &str, result: Result<HttpResponse, WebFetchError>) -> Self {
self.responses.lock().unwrap().insert(url.to_string(), result);
self
}
}
impl HttpClient for FakeHttpClient {
fn fetch<'a>(&'a self, url: &'a str, _timeout: Duration) -> BoxFuture<'a, Result<HttpResponse, WebFetchError>> {
let response = self.responses.lock().unwrap().get(url).cloned();
Box::pin(std::future::ready(response.unwrap_or_else(|| {
Err(WebFetchError::RequestFailed(format!("No fake response configured for URL: {url}")))
})))
}
}