mangadex_api/v5/user/id/list/
get.rs

1//! Builder for fetching a user's custom lists endpoint.
2//!
3//! <https://api.mangadex.org/docs/swagger.html#/User/get-user-id-list>
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 user_id = Uuid::new_v4();
16//!
17//! let res = client
18//!     .user()
19//!     .id(user_id)
20//!     .list()
21//!     .get()
22//!     .limit(1_u32)
23//!     .send()
24//!     .await?;
25//!
26//! println!("custom lists: {:?}", res);
27//! # Ok(())
28//! # }
29//! ```
30
31use derive_builder::Builder;
32use serde::Serialize;
33use uuid::Uuid;
34
35use crate::HttpClientRef;
36use mangadex_api_schema::v5::CustomListListResponse;
37
38#[cfg_attr(
39    feature = "deserializable-endpoint",
40    derive(serde::Deserialize, getset::Getters, getset::Setters)
41)]
42#[derive(Debug, Serialize, Clone, Builder)]
43#[serde(rename_all = "camelCase")]
44#[builder(
45    setter(into, strip_option),
46    build_fn(error = "mangadex_api_types::error::BuilderError")
47)]
48pub struct UserCustomLists {
49    /// This should never be set manually as this is only for internal use.
50    #[doc(hidden)]
51    #[serde(skip)]
52    #[builder(pattern = "immutable")]
53    #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
54    pub http_client: HttpClientRef,
55
56    #[serde(skip_serializing)]
57    pub user_id: Uuid,
58
59    #[serde(skip_serializing_if = "Option::is_none")]
60    #[builder(default)]
61    limit: Option<u32>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    #[builder(default)]
64    offset: Option<u32>,
65}
66
67endpoint! {
68    GET ("/user/{}/list", user_id),
69    #[query] UserCustomLists,
70    #[flatten_result] CustomListListResponse,
71    UserCustomListsBuilder
72}
73
74#[cfg(test)]
75mod tests {
76    use fake::faker::name::en::Name;
77    use fake::Fake;
78    use serde_json::json;
79    use url::Url;
80    use uuid::Uuid;
81    use wiremock::matchers::{method, path_regex};
82    use wiremock::{Mock, MockServer, ResponseTemplate};
83
84    use crate::{HttpClient, MangaDexClient};
85
86    #[tokio::test]
87    async fn get_user_custom_lists_fires_a_request_to_base_url() -> anyhow::Result<()> {
88        let mock_server = MockServer::start().await;
89        let http_client = HttpClient::builder()
90            .base_url(Url::parse(&mock_server.uri())?)
91            .build()?;
92        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
93
94        let user_id = Uuid::new_v4();
95        let list_id = Uuid::new_v4();
96        let list_name: String = Name().fake();
97        let response_body = json!({
98            "result": "ok",
99            "response": "collection",
100            "data": [
101                {
102                    "id": list_id,
103                    "type": "custom_list",
104                    "attributes": {
105                        "name": list_name,
106                        "visibility": "public",
107                        "version": 1
108                    },
109                    "relationships": []
110                }
111            ],
112            "limit": 1,
113            "offset": 0,
114            "total": 1
115        });
116
117        Mock::given(method("GET"))
118            .and(path_regex(r"/user/[0-9a-fA-F-]+/list"))
119            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
120            .expect(1)
121            .mount(&mock_server)
122            .await;
123
124        let _ = mangadex_client
125            .user()
126            .id(user_id)
127            .list()
128            .get()
129            .limit(1_u32)
130            .send()
131            .await?;
132
133        Ok(())
134    }
135}