mangadex_api/v5/custom_list/
post.rs1use 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#[cfg_attr(
50 feature = "deserializable-endpoint",
51 derive(serde::Deserialize, getset::Getters, getset::Setters)
52)]
53#[derive(Debug, Serialize, Clone, Builder)]
54#[serde(rename_all = "camelCase")]
55#[builder(
56 setter(into, strip_option),
57 build_fn(error = "mangadex_api_types::error::BuilderError")
58)]
59#[cfg_attr(feature = "non_exhaustive", non_exhaustive)]
60pub struct CreateCustomList {
61 #[doc(hidden)]
63 #[serde(skip)]
64 #[builder(pattern = "immutable")]
65 #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
66 pub http_client: HttpClientRef,
67
68 pub name: String,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 #[builder(default)]
71 pub visibility: Option<CustomListVisibility>,
72 #[serde(skip_serializing_if = "Vec::is_empty")]
73 #[builder(setter(each = "add_manga_id"), default)]
74 pub manga: Vec<Uuid>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 #[builder(default)]
77 pub version: Option<u32>,
78}
79
80endpoint! {
81 POST ("/list"),
82 #[body auth] CreateCustomList,
83 #[flatten_result] CustomListResponse,
84 CreateCustomListBuilder
85}
86
87#[cfg(test)]
88mod tests {
89 use fake::faker::name::en::Name;
90 use fake::Fake;
91 use serde_json::json;
92 use url::Url;
93 use uuid::Uuid;
94 use wiremock::matchers::{body_json, header, method, path};
95 use wiremock::{Mock, MockServer, ResponseTemplate};
96
97 use crate::v5::AuthTokens;
98 use crate::{HttpClient, MangaDexClient};
99
100 #[tokio::test]
101 async fn create_custom_list_fires_a_request_to_base_url() -> anyhow::Result<()> {
102 let mock_server = MockServer::start().await;
103 let http_client = HttpClient::builder()
104 .base_url(Url::parse(&mock_server.uri())?)
105 .auth_tokens(AuthTokens {
106 session: "sessiontoken".to_string(),
107 refresh: "refreshtoken".to_string(),
108 })
109 .build()?;
110 let mangadex_client = MangaDexClient::new_with_http_client(http_client);
111
112 let custom_list_id = Uuid::new_v4();
113 let custom_list_name: String = Name().fake();
114 let expected_body = json!({
115 "name": custom_list_name,
116 "version": 1
117 });
118 let response_body = json!({
119 "result": "ok",
120 "response": "entity",
121 "data": {
122 "id": custom_list_id,
123 "type": "custom_list",
124 "attributes": {
125 "name": custom_list_name,
126 "visibility": "private",
127 "version": 1
128 },
129 "relationships": []
130 }
131 });
132
133 Mock::given(method("POST"))
134 .and(path(r"/list"))
135 .and(header("Authorization", "Bearer sessiontoken"))
136 .and(header("Content-Type", "application/json"))
137 .and(body_json(expected_body))
138 .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
139 .expect(1)
140 .mount(&mock_server)
141 .await;
142
143 let _ = mangadex_client
144 .custom_list()
145 .post()
146 .name(custom_list_name.as_str())
147 .version(1u32)
148 .send()
149 .await?;
150
151 Ok(())
152 }
153}