Skip to main content

mangadex_api/v5/api_client/id/
get.rs

1//! Builder for getting client by its id.
2//!
3//! <https://api.mangadex.org/docs/swagger.html#/ApiClient/get-apiclient>
4//!
5//! # Examples
6//!
7//! ```rust
8//! use mangadex_api::v5::MangaDexClient;
9//! use uuid::Uuid;
10//!
11//! # async fn run() -> anyhow::Result<()> {
12//! let client = MangaDexClient::default();
13//!
14//! let client_res = client
15//!     .client()
16//!     .id(Uuid::new_v4())
17//!     .get()
18//!     .send()
19//!     .await?;
20//!
21//! println!("client: {:?}", client_res);
22//! # Ok(())
23//! # }
24//! ```
25//!
26use derive_builder::Builder;
27use serde::Serialize;
28use uuid::Uuid;
29
30use crate::HttpClientRef;
31use mangadex_api_types::ReferenceExpansionResource;
32
33type ApiClientResponse = crate::Result<mangadex_api_schema::v5::ApiClientData>;
34
35#[cfg_attr(
36    feature = "deserializable-endpoint",
37    derive(serde::Deserialize, getset::Getters, getset::Setters)
38)]
39#[derive(Debug, Serialize, Clone, Builder)]
40#[serde(rename_all = "camelCase")]
41#[builder(
42    setter(into, strip_option),
43    build_fn(error = "crate::error::BuilderError")
44)]
45#[non_exhaustive]
46pub struct GetClient {
47    /// This should never be set manually as this is only for internal use.
48    #[doc(hidden)]
49    #[serde(skip)]
50    #[builder(pattern = "immutable")]
51    #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
52    pub http_client: HttpClientRef,
53
54    #[serde(skip_serializing)]
55    pub client_id: Uuid,
56
57    #[builder(setter(each = "include"), default)]
58    #[serde(skip_serializing_if = "Vec::is_empty")]
59    pub includes: Vec<ReferenceExpansionResource>,
60}
61
62endpoint! {
63    GET ("/client/{}", client_id),
64    #[query auth] GetClient,
65    #[flatten_result] ApiClientResponse,
66    GetClientBuilder
67}
68
69#[cfg(test)]
70mod tests {
71    use serde_json::json;
72    use url::Url;
73    use uuid::Uuid;
74    use wiremock::matchers::{header, method, path_regex};
75    use wiremock::{Mock, MockServer, ResponseTemplate};
76
77    use crate::{HttpClient, MangaDexClient};
78    use mangadex_api_schema::v5::{AuthTokens, RelatedAttributes};
79    use mangadex_api_types::{ReferenceExpansionResource, RelationshipType};
80
81    #[tokio::test]
82    async fn get_client_fires_a_request_to_base_url() -> anyhow::Result<()> {
83        let mock_server = MockServer::start().await;
84        let http_client = HttpClient::builder()
85            .base_url(Url::parse(&mock_server.uri())?)
86            .auth_tokens(non_exhaustive::non_exhaustive!(AuthTokens {
87                session: "myToken".to_string(),
88                refresh: "myRefreshToken".to_string(),
89            }))
90            .build()?;
91        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
92
93        let client_id = Uuid::parse_str("eec486de-24f0-4e68-8459-34f26a62ceaa").unwrap();
94
95        let response_body = json!({
96          "result": "ok",
97          "response": "entity",
98          "data": {
99            "id": client_id,
100            "type": "api_client",
101            "attributes": {
102              "name": "Mangadex-API-Auth",
103              "description": "This is a API Client used for the [mangadex-api](https://github.com/tonymushah/mangadex-api) tests.",
104              "profile": "personal",
105              "externalClientId": null,
106              "isActive": false,
107              "state": "requested",
108              "createdAt": "2023-10-28T12:37:22+00:00",
109              "updatedAt": "2023-10-28T12:37:22+00:00",
110              "version": 1
111            },
112            "relationships": [
113              {
114                "id": "554149c7-f28f-4a30-b5fa-9db9b1e11353",
115                "type": "creator"
116              }
117            ]
118          }
119        });
120
121        Mock::given(method("GET"))
122            .and(path_regex(r"/client/[0-9a-fA-F-]+"))
123            .and(header("Authorization", "Bearer myToken"))
124            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
125            .expect(1)
126            .mount(&mock_server)
127            .await;
128
129        let res = mangadex_client.client().id(client_id).get().send().await?;
130
131        assert_eq!(res.data.type_, RelationshipType::ApiClient);
132
133        Ok(())
134    }
135
136    #[tokio::test]
137    async fn get_client_handles_reference_expansion() -> anyhow::Result<()> {
138        let mock_server = MockServer::start().await;
139        let http_client = HttpClient::builder()
140            .base_url(Url::parse(&mock_server.uri())?)
141            .auth_tokens(non_exhaustive::non_exhaustive!(AuthTokens {
142                session: "myToken".to_string(),
143                refresh: "myRefreshToken".to_string(),
144            }))
145            .build()?;
146        let mangadex_client = MangaDexClient::new_with_http_client(http_client);
147
148        let client_id = Uuid::parse_str("eec486de-24f0-4e68-8459-34f26a62ceaa").unwrap();
149
150        let response_body = json!({
151          "result": "ok",
152          "response": "entity",
153          "data": {
154            "id": client_id,
155            "type": "api_client",
156            "attributes": {
157              "name": "Mangadex-API-Auth",
158              "description": "This is a API Client used for the [mangadex-api](https://github.com/tonymushah/mangadex-api) tests.",
159              "profile": "personal",
160              "externalClientId": null,
161              "isActive": false,
162              "state": "requested",
163              "createdAt": "2023-10-28T12:37:22+00:00",
164              "updatedAt": "2023-10-28T12:37:22+00:00",
165              "version": 1
166            },
167            "relationships": [
168              {
169                "id": "554149c7-f28f-4a30-b5fa-9db9b1e11353",
170                "type": "creator",
171                "attributes": {
172                  "username": "Tony_Mushah",
173                  "roles": [
174                    "ROLE_USER"
175                  ],
176                  "version": 175
177                }
178              }
179            ]
180          }
181        });
182
183        Mock::given(method("GET"))
184            .and(path_regex(r"/client/[0-9a-fA-F-]+"))
185            .and(header("Authorization", "Bearer myToken"))
186            .respond_with(ResponseTemplate::new(200).set_body_json(response_body))
187            .expect(1)
188            .mount(&mock_server)
189            .await;
190
191        let res = mangadex_client
192            .client()
193            .id(client_id)
194            .get()
195            .include(&ReferenceExpansionResource::Creator)
196            .send()
197            .await?;
198
199        assert_eq!(res.data.relationships[0].type_, RelationshipType::Creator);
200        assert!(res.data.relationships[0].related.is_none());
201        if let RelatedAttributes::User(user) =
202            res.data.relationships[0].attributes.as_ref().unwrap()
203        {
204            assert_eq!(user.username, "Tony_Mushah".to_string());
205        } else {
206            panic!("Expected user RelatedAttributes");
207        }
208
209        Ok(())
210    }
211}