mangadex_api/v5/custom_list/id/
get.rs1use derive_builder::Builder;
29use mangadex_api_types::ReferenceExpansionResource;
30use serde::Serialize;
31use uuid::Uuid;
32
33use crate::HttpClientRef;
34use mangadex_api_schema::v5::CustomListResponse;
35
36#[cfg_attr(
37 feature = "deserializable-endpoint",
38 derive(serde::Deserialize, getset::Getters, getset::Setters)
39)]
40#[derive(Debug, Serialize, Clone, Builder)]
41#[serde(rename_all = "camelCase")]
42#[builder(
43 setter(into, strip_option),
44 build_fn(error = "mangadex_api_types::error::BuilderError")
45)]
46pub struct GetCustomList {
47 #[doc(hidden)]
49 #[serde(skip)]
50 #[builder(pattern = "immutable")]
51 #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
52 pub http_client: HttpClientRef,
53
54 #[serde(skip_serializing)]
55 pub list_id: Uuid,
56
57 #[builder(setter(each = "include"), default)]
58 pub includes: Vec<ReferenceExpansionResource>,
59}
60
61endpoint! {
62 GET ("/list/{}", list_id),
63 #[query] GetCustomList,
64 #[flatten_result] CustomListResponse,
65 GetCustomListBuilder
66}
67
68#[cfg(test)]
69mod tests {
70 use fake::faker::name::en::Name;
71 use fake::Fake;
72 use serde_json::json;
73 use url::Url;
74 use uuid::Uuid;
75 use wiremock::matchers::{method, path_regex};
76 use wiremock::{Mock, MockServer, ResponseTemplate};
77
78 use crate::{HttpClient, MangaDexClient};
79 use mangadex_api_types::error::Error;
80 use mangadex_api_types::CustomListVisibility;
81
82 #[tokio::test]
83 async fn get_custom_list_fires_a_request_to_base_url() -> anyhow::Result<()> {
84 let mock_server = MockServer::start().await;
85 let http_client = HttpClient::builder()
86 .base_url(Url::parse(&mock_server.uri())?)
87 .build()?;
88 let mangadex_client = MangaDexClient::new_with_http_client(http_client);
89
90 let list_id = Uuid::new_v4();
91 let list_name: String = Name().fake();
92 let response_body = json!({
93 "result": "ok",
94 "response": "entity",
95 "data": {
96 "id": list_id,
97 "type": "custom_list",
98 "attributes": {
99 "name": list_name,
100 "visibility": "private",
101 "version": 1
102 },
103 "relationships": []
104 }
105 });
106
107 Mock::given(method("GET"))
108 .and(path_regex(r"/list/[0-9a-fA-F-]+"))
109 .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
110 .expect(1)
111 .mount(&mock_server)
112 .await;
113
114 let res = mangadex_client
115 .custom_list()
116 .id(list_id)
117 .get()
118 .send()
119 .await?;
120
121 assert_eq!(res.data.id, list_id);
122 assert_eq!(res.data.attributes.name, list_name);
123 assert_eq!(
124 res.data.attributes.visibility,
125 CustomListVisibility::Private
126 );
127 assert_eq!(res.data.attributes.version, 1);
128
129 Ok(())
130 }
131
132 #[tokio::test]
133 async fn get_custom_list_handles_404() -> anyhow::Result<()> {
134 let mock_server = MockServer::start().await;
135 let http_client: HttpClient = HttpClient::builder()
136 .base_url(Url::parse(&mock_server.uri())?)
137 .build()?;
138 let mangadex_client = MangaDexClient::new_with_http_client(http_client);
139
140 let list_id = Uuid::new_v4();
141 let error_id = Uuid::new_v4();
142
143 let response_body = json!({
144 "result": "error",
145 "errors": [{
146 "id": error_id.to_string(),
147 "status": 404,
148 "title": "Not found",
149 "detail": "CustomList could not be found"
150 }]
151 });
152
153 Mock::given(method("GET"))
154 .and(path_regex(r"/list/[0-9a-fA-F-]+"))
155 .respond_with(ResponseTemplate::new(404).set_body_json(response_body))
156 .expect(1)
157 .mount(&mock_server)
158 .await;
159
160 let res = mangadex_client
161 .custom_list()
162 .id(list_id)
163 .get()
164 .send()
165 .await
166 .expect_err("expected error");
167
168 if let Error::Api(errors) = res {
169 assert_eq!(errors.errors.len(), 1);
170
171 assert_eq!(errors.errors[0].id, error_id);
172 assert_eq!(errors.errors[0].status, 404);
173 assert_eq!(errors.errors[0].title, Some("Not found".to_string()));
174 assert_eq!(
175 errors.errors[0].detail,
176 Some("CustomList could not be found".to_string())
177 );
178 }
179
180 Ok(())
181 }
182}