mangadex_api/v5/api_client/id/
get.rs1use 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 #[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}