mangadex_api/v5/custom_list/id/follow/
delete.rs

1//! Builder for the unfollow CustomList endpoint.
2//!
3//! <https://api.mangadex.org/docs/swagger.html#/CustomList/unfollow-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//! /*
17//!     
18//!     let _login_res = client
19//!         .auth()
20//!         .login()
21//!         .username(Username::parse("myusername")?)
22//!         .password(Password::parse("hunter23")?)
23//!         .send()
24//!         .await?;
25//!  */
26//!
27//!
28//! let list_id = Uuid::new_v4();
29//! let _ = client
30//!     .custom_list()
31//!     .id(list_id)
32//!     .follow()
33//!     .delete()
34//!     .build()?
35//!     .send()
36//!     .await?;
37//!
38//! # Ok(())
39//! # }
40//! ```
41
42use derive_builder::Builder;
43use mangadex_api_schema::NoData;
44use serde::Serialize;
45use uuid::Uuid;
46
47use crate::HttpClientRef;
48use mangadex_api_types::error::Result;
49
50#[cfg_attr(
51    feature = "deserializable-endpoint",
52    derive(serde::Deserialize, getset::Getters, getset::Setters)
53)]
54#[derive(Debug, Serialize, Clone, Builder)]
55#[serde(rename_all = "camelCase")]
56#[builder(
57    setter(into, strip_option),
58    build_fn(error = "mangadex_api_types::error::BuilderError")
59)]
60#[cfg_attr(feature = "non_exhaustive", non_exhaustive)]
61pub struct UnFollowCustomList {
62    /// This should never be set manually as this is only for internal use.
63    #[doc(hidden)]
64    #[serde(skip)]
65    #[builder(pattern = "immutable")]
66    #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
67    pub http_client: HttpClientRef,
68
69    /// CustomList ID.
70    #[serde(skip_serializing)]
71    pub list_id: Uuid,
72}
73
74endpoint! {
75    DELETE ("/list/{}/follow", list_id),
76    #[body auth] UnFollowCustomList,
77    #[discard_result] Result<NoData>,
78    UnFollowCustomListBuilder
79}
80
81#[cfg(test)]
82mod tests {
83    use serde_json::json;
84    use url::Url;
85    use uuid::Uuid;
86    use wiremock::matchers::{header, method, path_regex};
87    use wiremock::{Mock, MockServer, ResponseTemplate};
88
89    use crate::v5::AuthTokens;
90    use crate::{HttpClient, MangaDexClient};
91
92    #[tokio::test]
93    async fn follow_custom_list_fires_a_request_to_base_url() -> anyhow::Result<()> {
94        let mock_server = MockServer::start().await;
95        let http_client = HttpClient::builder()
96            .base_url(Url::parse(&mock_server.uri())?)
97            .auth_tokens(AuthTokens {
98                session: "sessiontoken".to_string(),
99                refresh: "refreshtoken".to_string(),
100            })
101            .build()?;
102        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
103
104        let custom_list_id = Uuid::new_v4();
105        let response_body = json!({
106            "result": "ok"
107        });
108
109        Mock::given(method("DELETE"))
110            .and(path_regex(r"/list/[0-9a-fA-F-]+/follow"))
111            .and(header("Authorization", "Bearer sessiontoken"))
112            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
113            .expect(1)
114            .mount(&mock_server)
115            .await;
116
117        mangadex_client
118            .custom_list()
119            .id(custom_list_id)
120            .follow()
121            .delete()
122            .build()?
123            .send()
124            .await?;
125
126        Ok(())
127    }
128}