mithril_aggregator_client/query/get/
get_certificate.rs1use async_trait::async_trait;
2use reqwest::StatusCode;
3
4use mithril_common::messages::CertificateMessage;
5
6use crate::AggregatorHttpClientResult;
7use crate::query::{AggregatorQuery, QueryContext, QueryMethod, ResponseExt};
8
9pub struct GetCertificateQuery {
11 hash: String,
12}
13
14impl GetCertificateQuery {
15 pub fn by_hash<H: Into<String>>(hash: H) -> Self {
17 Self { hash: hash.into() }
18 }
19
20 pub fn latest_genesis() -> Self {
22 Self {
23 hash: "genesis".to_string(),
24 }
25 }
26}
27
28#[cfg_attr(target_family = "wasm", async_trait(?Send))]
29#[cfg_attr(not(target_family = "wasm"), async_trait)]
30impl AggregatorQuery for GetCertificateQuery {
31 type Response = Option<CertificateMessage>;
32 type Body = ();
33
34 fn method() -> QueryMethod {
35 QueryMethod::Get
36 }
37
38 fn route(&self) -> String {
39 format!("certificate/{}", self.hash)
40 }
41
42 async fn handle_response(
43 &self,
44 context: QueryContext,
45 ) -> AggregatorHttpClientResult<Self::Response> {
46 match context.response.status() {
47 StatusCode::OK => context.response.parse_json_option().await,
48 StatusCode::NOT_FOUND => Ok(None),
49 _ => Err(context.unhandled_status_code().await),
50 }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use serde_json::json;
57
58 use mithril_common::test::double::Dummy;
59
60 use crate::AggregatorHttpClientError;
61 use crate::test::{assert_error_matches, setup_server_and_client};
62
63 use super::*;
64
65 #[tokio::test]
66 async fn test_certificates_details_ok_200() {
67 let (server, client) = setup_server_and_client();
68 let expected_message = CertificateMessage::dummy();
69 let _server_mock = server.mock(|when, then| {
70 when.path(format!("/certificate/{}", expected_message.hash));
71 then.status(200).body(json!(expected_message).to_string());
72 });
73
74 let fetched_message = client
75 .send(GetCertificateQuery::by_hash(&expected_message.hash))
76 .await
77 .unwrap();
78
79 assert_eq!(Some(expected_message), fetched_message);
80 }
81
82 #[tokio::test]
83 async fn test_certificates_details_ok_404() {
84 let (server, client) = setup_server_and_client();
85 let _server_mock = server.mock(|when, then| {
86 when.any_request();
87 then.status(404);
88 });
89
90 let fetched_message = client.send(GetCertificateQuery::by_hash("whatever")).await.unwrap();
91
92 assert_eq!(None, fetched_message);
93 }
94
95 #[tokio::test]
96 async fn test_certificates_details_ko_500() {
97 let (server, client) = setup_server_and_client();
98 let _server_mock = server.mock(|when, then| {
99 when.any_request();
100 then.status(500).body("an error occurred");
101 });
102
103 let error = client
104 .send(GetCertificateQuery::by_hash("whatever"))
105 .await
106 .unwrap_err();
107
108 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
109 }
110
111 #[tokio::test]
112 async fn test_latest_genesis_ok_200() {
113 let (server, client) = setup_server_and_client();
114 let genesis_message = CertificateMessage::dummy();
115 let _server_mock = server.mock(|when, then| {
116 when.path("/certificate/genesis");
117 then.status(200).body(json!(genesis_message).to_string());
118 });
119
120 let fetched = client.send(GetCertificateQuery::latest_genesis()).await.unwrap();
121
122 assert_eq!(Some(genesis_message), fetched);
123 }
124
125 #[tokio::test]
126 async fn test_latest_genesis_ok_404() {
127 let (server, client) = setup_server_and_client();
128 let _server_mock = server.mock(|when, then| {
129 when.any_request();
130 then.status(404);
131 });
132
133 let fetched = client.send(GetCertificateQuery::latest_genesis()).await.unwrap();
134
135 assert_eq!(None, fetched);
136 }
137
138 #[tokio::test]
139 async fn test_latest_genesis_ko_500() {
140 let (server, client) = setup_server_and_client();
141 let _server_mock = server.mock(|when, then| {
142 when.any_request();
143 then.status(500).body("an error occurred");
144 });
145
146 let error = client.send(GetCertificateQuery::latest_genesis()).await.unwrap_err();
147
148 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
149 }
150}