#![allow(missing_docs)] use std::collections::HashMap;
use std::sync::Arc;
use std::task::Poll;
use futures::future;
use http::StatusCode;
use tower::BoxError;
use tower::Service;
use crate::graphql::Request;
use crate::graphql::Response;
use crate::json_ext::Object;
use crate::services::SubgraphRequest;
use crate::services::SubgraphResponse;
type MockResponses = HashMap<Request, Response>;
#[derive(Clone, Default)]
pub struct MockSubgraph {
mocks: Arc<MockResponses>,
extensions: Option<Object>,
}
impl MockSubgraph {
pub fn new(mocks: MockResponses) -> Self {
Self {
mocks: Arc::new(mocks),
extensions: None,
}
}
pub fn builder() -> MockSubgraphBuilder {
MockSubgraphBuilder::default()
}
pub fn with_extensions(mut self, extensions: Object) -> Self {
self.extensions = Some(extensions);
self
}
}
#[derive(Clone, Default)]
pub struct MockSubgraphBuilder {
mocks: MockResponses,
extensions: Option<Object>,
}
impl MockSubgraphBuilder {
pub fn with_extensions(mut self, extensions: Object) -> Self {
self.extensions = Some(extensions);
self
}
pub fn with_json(mut self, request: serde_json::Value, response: serde_json::Value) -> Self {
self.mocks.insert(
serde_json::from_value(request).unwrap(),
serde_json::from_value(response).unwrap(),
);
self
}
pub fn build(self) -> MockSubgraph {
MockSubgraph {
mocks: Arc::new(self.mocks),
extensions: self.extensions,
}
}
}
impl Service<SubgraphRequest> for MockSubgraph {
type Response = SubgraphResponse;
type Error = BoxError;
type Future = future::Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: SubgraphRequest) -> Self::Future {
let response = if let Some(response) = self.mocks.get(req.subgraph_request.body()) {
let http_response = http::Response::builder()
.status(StatusCode::OK)
.body(response.clone())
.expect("Response is serializable; qed");
SubgraphResponse::new_from_response(http_response, req.context)
} else {
let error = crate::error::Error::builder()
.message(format!(
"couldn't find mock for query {}",
serde_json::to_string(&req.subgraph_request.body()).unwrap()
))
.extension_code("FETCH_ERROR".to_string())
.extensions(self.extensions.clone().unwrap_or_default())
.build();
SubgraphResponse::fake_builder()
.error(error)
.context(req.context)
.build()
};
future::ok(response)
}
}