Skip to main content

mangadex_api/v5/custom_list/
update.rs

1//! Builder for the CustomList update endpoint.
2//!
3//! <https://api.mangadex.org/swagger.html#/CustomList/put-list-id>
4//!
5//! # Examples
6//!
7//! ```rust
8//! use uuid::Uuid;
9//!
10//! use mangadex_api::v5::MangaDexClient;
11//! use mangadex_api::types::{Password, Username};
12//!
13//! # async fn run() -> anyhow::Result<()> {
14//! let client = MangaDexClient::default();
15//!
16//! let _login_res = client
17//!     .auth()
18//!     .login()
19//!     .username(Username::parse("myusername")?)
20//!     .password(Password::parse("hunter23")?)
21//!     .build()?
22//!     .send()
23//!     .await?;
24//!
25//! let list_id = Uuid::new_v4();
26//! let res = client
27//!     .custom_list()
28//!     .update()
29//!     .list_id(&list_id)
30//!     .name("Updated List Name")
31//!     .version(2u32)
32//!     .build()?
33//!     .send()
34//!     .await?;
35//!
36//! println!("update: {:?}", res);
37//! # Ok(())
38//! # }
39//! ```
40
41use derive_builder::Builder;
42use serde::Serialize;
43use uuid::Uuid;
44
45use crate::HttpClientRef;
46use mangadex_api_schema::v5::CustomListResponse;
47use mangadex_api_types::CustomListVisibility;
48
49#[derive(Debug, Serialize, Clone, Builder)]
50#[serde(rename_all = "camelCase")]
51#[builder(setter(into, strip_option), pattern = "owned")]
52#[non_exhaustive]
53pub struct UpdateCustomList<'a> {
54    /// This should never be set manually as this is only for internal use.
55    #[doc(hidden)]
56    #[serde(skip)]
57    #[builder(pattern = "immutable")]
58    pub(crate) http_client: HttpClientRef,
59
60    #[serde(skip)]
61    pub list_id: &'a Uuid,
62
63    #[serde(skip_serializing_if = "Option::is_none")]
64    #[builder(default)]
65    pub name: Option<&'a str>,
66
67    #[serde(skip_serializing_if = "Option::is_none")]
68    #[builder(default)]
69    pub visibility: Option<CustomListVisibility>,
70
71    #[serde(skip_serializing_if = "Vec::is_empty")]
72    #[builder(setter(each = "add_manga_id"), default)]
73    pub manga: Vec<Uuid>,
74
75    pub version: u32,
76}
77
78endpoint! {
79    PUT ("/list/{}", list_id),
80    #[body auth] UpdateCustomList<'_>,
81    #[flatten_result] CustomListResponse
82}
83
84#[cfg(test)]
85mod tests {
86    use fake::faker::name::en::Name;
87    use fake::Fake;
88    use serde_json::json;
89    use url::Url;
90    use uuid::Uuid;
91    use wiremock::matchers::{body_json, header, method, path_regex};
92    use wiremock::{Mock, MockServer, ResponseTemplate};
93
94    use crate::v5::AuthTokens;
95    use crate::{HttpClient, MangaDexClient};
96
97    #[tokio::test]
98    async fn update_custom_list_fires_a_request_to_base_url() -> anyhow::Result<()> {
99        let mock_server = MockServer::start().await;
100        let http_client = HttpClient::builder()
101            .base_url(Url::parse(&mock_server.uri())?)
102            .auth_tokens(AuthTokens {
103                session: "sessiontoken".to_string(),
104                refresh: "refreshtoken".to_string(),
105            })
106            .build()?;
107        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
108
109        let list_id = Uuid::new_v4();
110        let list_name: String = Name().fake();
111        let expected_body = json!({
112            "version": 2
113        });
114        let response_body = json!({
115            "result": "ok",
116            "response": "entity",
117            "data": {
118                "id": list_id,
119                "type": "custom_list",
120                "attributes": {
121                    "name": list_name,
122                    "visibility": "private",
123                    "version": 2
124                },
125                "relationships": []
126            }
127        });
128
129        Mock::given(method("PUT"))
130            .and(path_regex(r"/list/[0-9a-fA-F-]+"))
131            .and(header("Authorization", "Bearer sessiontoken"))
132            .and(header("Content-Type", "application/json"))
133            .and(body_json(expected_body))
134            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
135            .expect(1)
136            .mount(&mock_server)
137            .await;
138
139        let _ = mangadex_client
140            .custom_list()
141            .update()
142            .list_id(&list_id)
143            .version(2u32)
144            .build()?
145            .send()
146            .await?;
147
148        Ok(())
149    }
150}