Skip to main content

mangadex_api/v5/custom_list/
get.rs

1//! Builder for the custom list view endpoint.
2//!
3//! <https://api.mangadex.org/swagger.html#/CustomList/get-list-id>
4//!
5//! # Examples
6//!
7//! ```rust
8//! use uuid::Uuid;
9//!
10//! use mangadex_api::v5::MangaDexClient;
11//!
12//! # async fn run() -> anyhow::Result<()> {
13//! let client = MangaDexClient::default();
14//!
15//! let list_id = Uuid::new_v4();
16//! let res = client
17//!     .custom_list()
18//!     .get()
19//!     .list_id(&list_id)
20//!     .build()?
21//!     .send()
22//!     .await?;
23//!
24//! println!("custom list: {:?}", res);
25//! # Ok(())
26//! # }
27//! ```
28
29use derive_builder::Builder;
30use serde::Serialize;
31use uuid::Uuid;
32
33use crate::HttpClientRef;
34use mangadex_api_schema::v5::CustomListResponse;
35
36#[derive(Debug, Serialize, Clone, Builder)]
37#[serde(rename_all = "camelCase")]
38#[builder(setter(into, strip_option), pattern = "owned")]
39pub struct GetCustomList<'a> {
40    /// This should never be set manually as this is only for internal use.
41    #[doc(hidden)]
42    #[serde(skip)]
43    #[builder(pattern = "immutable")]
44    pub(crate) http_client: HttpClientRef,
45
46    #[serde(skip)]
47    pub list_id: &'a Uuid,
48}
49
50endpoint! {
51    GET ("/list/{}", list_id),
52    #[query] GetCustomList<'_>,
53    #[flatten_result] CustomListResponse
54}
55
56#[cfg(test)]
57mod tests {
58    use fake::faker::name::en::Name;
59    use fake::Fake;
60    use serde_json::json;
61    use url::Url;
62    use uuid::Uuid;
63    use wiremock::matchers::{method, path_regex};
64    use wiremock::{Mock, MockServer, ResponseTemplate};
65
66    use crate::{HttpClient, MangaDexClient};
67    use mangadex_api_types::error::Error;
68    use mangadex_api_types::CustomListVisibility;
69
70    #[tokio::test]
71    async fn get_custom_list_fires_a_request_to_base_url() -> anyhow::Result<()> {
72        let mock_server = MockServer::start().await;
73        let http_client = HttpClient::builder()
74            .base_url(Url::parse(&mock_server.uri())?)
75            .build()?;
76        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
77
78        let list_id = Uuid::new_v4();
79        let list_name: String = Name().fake();
80        let response_body = json!({
81            "result": "ok",
82            "response": "entity",
83            "data": {
84                "id": list_id,
85                "type": "custom_list",
86                "attributes": {
87                    "name": list_name,
88                    "visibility": "private",
89                    "version": 1
90                },
91                "relationships": []
92            }
93        });
94
95        Mock::given(method("GET"))
96            .and(path_regex(r"/list/[0-9a-fA-F-]+"))
97            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
98            .expect(1)
99            .mount(&mock_server)
100            .await;
101
102        let res = mangadex_client
103            .custom_list()
104            .get()
105            .list_id(&list_id)
106            .build()?
107            .send()
108            .await?;
109
110        assert_eq!(res.data.id, list_id);
111        assert_eq!(res.data.attributes.name, list_name);
112        assert_eq!(
113            res.data.attributes.visibility,
114            CustomListVisibility::Private
115        );
116        assert_eq!(res.data.attributes.version, 1);
117
118        Ok(())
119    }
120
121    #[tokio::test]
122    async fn get_custom_list_handles_404() -> anyhow::Result<()> {
123        let mock_server = MockServer::start().await;
124        let http_client: HttpClient = HttpClient::builder()
125            .base_url(Url::parse(&mock_server.uri())?)
126            .build()?;
127        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
128
129        let list_id = Uuid::new_v4();
130        let error_id = Uuid::new_v4();
131
132        let response_body = json!({
133            "result": "error",
134            "errors": [{
135                "id": error_id.to_string(),
136                "status": 404,
137                "title": "Not found",
138                "detail": "CustomList could not be found"
139            }]
140        });
141
142        Mock::given(method("GET"))
143            .and(path_regex(r"/list/[0-9a-fA-F-]+"))
144            .respond_with(ResponseTemplate::new(404).set_body_json(response_body))
145            .expect(1)
146            .mount(&mock_server)
147            .await;
148
149        let res = mangadex_client
150            .custom_list()
151            .get()
152            .list_id(&list_id)
153            .build()?
154            .send()
155            .await
156            .expect_err("expected error");
157
158        if let Error::Api(errors) = res {
159            assert_eq!(errors.errors.len(), 1);
160
161            assert_eq!(errors.errors[0].id, error_id);
162            assert_eq!(errors.errors[0].status, 404);
163            assert_eq!(errors.errors[0].title, Some("Not found".to_string()));
164            assert_eq!(
165                errors.errors[0].detail,
166                Some("CustomList could not be found".to_string())
167            );
168        }
169
170        Ok(())
171    }
172}