mangadex_api/v5/upload/begin/chapter_id/
post.rs1use derive_builder::Builder;
44use mangadex_api_schema::v5::UploadSessionData;
45use serde::Serialize;
46use uuid::Uuid;
47
48use crate::HttpClientRef;
49
50#[cfg_attr(
56 feature = "deserializable-endpoint",
57 derive(serde::Deserialize, getset::Getters, getset::Setters)
58)]
59#[derive(Debug, Builder, Serialize, Clone)]
60#[serde(rename_all = "camelCase")]
61#[builder(
62 setter(into, strip_option),
63 build_fn(error = "crate::error::BuilderError")
64)]
65#[non_exhaustive]
66pub struct StartEditChapterSession {
67 #[doc(hidden)]
69 #[serde(skip)]
70 #[builder(pattern = "immutable")]
71 #[cfg_attr(feature = "deserializable-endpoint", getset(set = "pub", get = "pub"))]
72 pub http_client: HttpClientRef,
73
74 #[serde(skip_serializing)]
75 pub chapter_id: Uuid,
76
77 pub version: u32,
78}
79
80endpoint! {
81 POST ("/upload/begin/{}", chapter_id),
82 #[body auth] StartEditChapterSession,
83 #[rate_limited] UploadSessionData,
84 StartEditChapterSessionBuilder
85}
86
87#[cfg(test)]
88mod tests {
89 use serde_json::json;
90 use time::OffsetDateTime;
91 use url::Url;
92 use uuid::Uuid;
93 use wiremock::matchers::{body_json, header, method, path_regex};
94 use wiremock::{Mock, MockServer, ResponseTemplate};
95
96 use crate::v5::AuthTokens;
97 use crate::{HttpClient, MangaDexClient};
98 use mangadex_api_types::{MangaDexDateTime, RelationshipType};
99
100 #[tokio::test]
101 async fn start_edit_chapter_session_fires_a_request_to_base_url() -> anyhow::Result<()> {
102 let mock_server = MockServer::start().await;
103 let http_client: HttpClient = HttpClient::builder()
104 .base_url(Url::parse(&mock_server.uri())?)
105 .auth_tokens(non_exhaustive::non_exhaustive!(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 chapter_id = Uuid::new_v4();
113 let session_id = Uuid::new_v4();
114
115 let datetime = MangaDexDateTime::new(&OffsetDateTime::now_utc());
116
117 let expected_body = json!({
118 "version": 2,
119 });
120 let response_body = json!({
121 "result": "ok",
122 "response": "entity",
123 "data" : {
124 "id": session_id,
125 "type": "upload_session",
126 "attributes": {
127 "isCommitted": false,
128 "isProcessed": false,
129 "isDeleted": false,
130 "version": 2,
131 "createdAt": datetime.to_string(),
132 "updatedAt": datetime.to_string(),
133 },
134 "relationships": []
135 }
136 });
137
138 Mock::given(method("POST"))
139 .and(path_regex("/upload/begin/[0-9a-fA-F-]+"))
140 .and(header("Authorization", "Bearer sessiontoken"))
141 .and(header("Content-Type", "application/json"))
142 .and(body_json(expected_body))
143 .respond_with(
144 ResponseTemplate::new(200)
145 .insert_header("x-ratelimit-retry-after", "1698723860")
146 .insert_header("x-ratelimit-limit", "40")
147 .insert_header("x-ratelimit-remaining", "39")
148 .set_body_json(response_body),
149 )
150 .expect(1)
151 .mount(&mock_server)
152 .await;
153
154 let res = mangadex_client
155 .upload()
156 .begin()
157 .chapter_id(chapter_id)
158 .post()
159 .version(2_u32)
160 .send()
161 .await?;
162
163 let res = &res.data;
164
165 assert_eq!(res.id, session_id);
166 assert_eq!(res.type_, RelationshipType::UploadSession);
167 assert!(!res.attributes.is_committed);
168 assert!(!res.attributes.is_processed);
169 assert!(!res.attributes.is_deleted);
170 assert_eq!(res.attributes.version, 2);
171 assert_eq!(res.attributes.created_at.to_string(), datetime.to_string());
172 assert_eq!(res.attributes.updated_at.to_string(), datetime.to_string());
173
174 Ok(())
175 }
176}