open_lark/core/
req_option.rs

1#![allow(dead_code)]
2
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Default)]
6pub struct RequestOption {
7    pub(crate) tenant_key: String,
8    pub(crate) user_access_token: String,
9    pub(crate) app_access_token: String,
10    pub(crate) tenant_access_token: String,
11    pub(crate) need_helpdesk_auth: bool,
12    pub(crate) request_id: String,
13    pub(crate) app_ticket: String,
14    pub(crate) file_upload: bool,
15    pub(crate) file_download: bool,
16    pub(crate) header: HashMap<String, String>,
17}
18
19impl RequestOption {
20    pub fn builder() -> RequestOptionBuilder {
21        RequestOptionBuilder::default()
22    }
23}
24
25#[derive(Default)]
26pub struct RequestOptionBuilder {
27    option: RequestOption,
28}
29
30impl RequestOptionBuilder {
31    pub fn tenant_key(mut self, tenant_key: impl ToString) -> Self {
32        self.option.tenant_key = tenant_key.to_string();
33        self
34    }
35
36    pub fn user_access_token(mut self, user_access_token: impl ToString) -> Self {
37        self.option.user_access_token = user_access_token.to_string();
38        self
39    }
40
41    pub fn app_access_token(mut self, app_access_token: impl ToString) -> Self {
42        self.option.app_access_token = app_access_token.to_string();
43        self
44    }
45
46    pub fn tenant_access_token(mut self, tenant_access_token: impl ToString) -> Self {
47        self.option.tenant_access_token = tenant_access_token.to_string();
48        self
49    }
50
51    pub fn need_helpdesk_auth(mut self, need_helpdesk_auth: bool) -> Self {
52        self.option.need_helpdesk_auth = need_helpdesk_auth;
53        self
54    }
55
56    pub fn request_id(mut self, request_id: impl ToString) -> Self {
57        self.option.request_id = request_id.to_string();
58        self
59    }
60
61    pub fn app_ticket(mut self, app_ticket: impl ToString) -> Self {
62        self.option.app_ticket = app_ticket.to_string();
63        self
64    }
65
66    pub fn file_upload(mut self, file_upload: bool) -> Self {
67        self.option.file_upload = file_upload;
68        self
69    }
70
71    pub fn file_download(mut self, file_download: bool) -> Self {
72        self.option.file_download = file_download;
73        self
74    }
75
76    pub fn header(mut self, header: HashMap<String, String>) -> Self {
77        self.option.header = header;
78        self
79    }
80
81    /// 添加请求头
82    pub fn add_header(mut self, key: impl ToString, value: impl ToString) -> Self {
83        self.option
84            .header
85            .insert(key.to_string(), value.to_string());
86        self
87    }
88
89    pub fn build(self) -> RequestOption {
90        self.option
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use std::collections::HashMap;
98
99    #[test]
100    fn test_request_option_default() {
101        let option = RequestOption::default();
102        assert_eq!(option.tenant_key, "");
103        assert_eq!(option.user_access_token, "");
104        assert_eq!(option.app_access_token, "");
105        assert_eq!(option.tenant_access_token, "");
106        assert!(!option.need_helpdesk_auth);
107        assert_eq!(option.request_id, "");
108        assert_eq!(option.app_ticket, "");
109        assert!(!option.file_upload);
110        assert!(!option.file_download);
111        assert!(option.header.is_empty());
112    }
113
114    #[test]
115    fn test_request_option_builder_creation() {
116        let builder = RequestOption::builder();
117        let option = builder.build();
118
119        // Should be same as default
120        assert_eq!(option.tenant_key, "");
121        assert_eq!(option.user_access_token, "");
122        assert_eq!(option.app_access_token, "");
123        assert_eq!(option.tenant_access_token, "");
124        assert!(!option.need_helpdesk_auth);
125        assert_eq!(option.request_id, "");
126        assert_eq!(option.app_ticket, "");
127        assert!(!option.file_upload);
128        assert!(!option.file_download);
129        assert!(option.header.is_empty());
130    }
131
132    #[test]
133    fn test_request_option_builder_tenant_key() {
134        let option = RequestOption::builder().tenant_key("test_tenant").build();
135
136        assert_eq!(option.tenant_key, "test_tenant");
137
138        // Test with String
139        let option = RequestOption::builder()
140            .tenant_key("another_tenant".to_string())
141            .build();
142
143        assert_eq!(option.tenant_key, "another_tenant");
144    }
145
146    #[test]
147    fn test_request_option_builder_user_access_token() {
148        let option = RequestOption::builder()
149            .user_access_token("user_token_123")
150            .build();
151
152        assert_eq!(option.user_access_token, "user_token_123");
153
154        // Test with String
155        let option = RequestOption::builder()
156            .user_access_token("user_token_456".to_string())
157            .build();
158
159        assert_eq!(option.user_access_token, "user_token_456");
160    }
161
162    #[test]
163    fn test_request_option_builder_app_access_token() {
164        let option = RequestOption::builder()
165            .app_access_token("app_token_789")
166            .build();
167
168        assert_eq!(option.app_access_token, "app_token_789");
169
170        // Test with String
171        let option = RequestOption::builder()
172            .app_access_token("app_token_012".to_string())
173            .build();
174
175        assert_eq!(option.app_access_token, "app_token_012");
176    }
177
178    #[test]
179    fn test_request_option_builder_tenant_access_token() {
180        let option = RequestOption::builder()
181            .tenant_access_token("tenant_token_345")
182            .build();
183
184        assert_eq!(option.tenant_access_token, "tenant_token_345");
185
186        // Test with String
187        let option = RequestOption::builder()
188            .tenant_access_token("tenant_token_678".to_string())
189            .build();
190
191        assert_eq!(option.tenant_access_token, "tenant_token_678");
192    }
193
194    #[test]
195    fn test_request_option_builder_need_helpdesk_auth() {
196        let option = RequestOption::builder().need_helpdesk_auth(true).build();
197
198        assert!(option.need_helpdesk_auth);
199
200        let option = RequestOption::builder().need_helpdesk_auth(false).build();
201
202        assert!(!option.need_helpdesk_auth);
203    }
204
205    #[test]
206    fn test_request_option_builder_request_id() {
207        let option = RequestOption::builder().request_id("req_12345").build();
208
209        assert_eq!(option.request_id, "req_12345");
210
211        // Test with String
212        let option = RequestOption::builder()
213            .request_id("req_67890".to_string())
214            .build();
215
216        assert_eq!(option.request_id, "req_67890");
217    }
218
219    #[test]
220    fn test_request_option_builder_app_ticket() {
221        let option = RequestOption::builder().app_ticket("ticket_abc").build();
222
223        assert_eq!(option.app_ticket, "ticket_abc");
224
225        // Test with String
226        let option = RequestOption::builder()
227            .app_ticket("ticket_def".to_string())
228            .build();
229
230        assert_eq!(option.app_ticket, "ticket_def");
231    }
232
233    #[test]
234    fn test_request_option_builder_file_upload() {
235        let option = RequestOption::builder().file_upload(true).build();
236
237        assert!(option.file_upload);
238
239        let option = RequestOption::builder().file_upload(false).build();
240
241        assert!(!option.file_upload);
242    }
243
244    #[test]
245    fn test_request_option_builder_file_download() {
246        let option = RequestOption::builder().file_download(true).build();
247
248        assert!(option.file_download);
249
250        let option = RequestOption::builder().file_download(false).build();
251
252        assert!(!option.file_download);
253    }
254
255    #[test]
256    fn test_request_option_builder_header() {
257        let mut headers = HashMap::new();
258        headers.insert("Content-Type".to_string(), "application/json".to_string());
259        headers.insert("Authorization".to_string(), "Bearer token".to_string());
260
261        let option = RequestOption::builder().header(headers.clone()).build();
262
263        assert_eq!(option.header.len(), 2);
264        assert_eq!(
265            option.header.get("Content-Type"),
266            Some(&"application/json".to_string())
267        );
268        assert_eq!(
269            option.header.get("Authorization"),
270            Some(&"Bearer token".to_string())
271        );
272    }
273
274    #[test]
275    fn test_request_option_builder_add_header() {
276        let option = RequestOption::builder()
277            .add_header("X-Custom-Header", "custom_value")
278            .add_header("X-Another-Header", "another_value")
279            .build();
280
281        assert_eq!(option.header.len(), 2);
282        assert_eq!(
283            option.header.get("X-Custom-Header"),
284            Some(&"custom_value".to_string())
285        );
286        assert_eq!(
287            option.header.get("X-Another-Header"),
288            Some(&"another_value".to_string())
289        );
290
291        // Test with String types
292        let option = RequestOption::builder()
293            .add_header("X-String-Header".to_string(), "string_value".to_string())
294            .build();
295
296        assert_eq!(option.header.len(), 1);
297        assert_eq!(
298            option.header.get("X-String-Header"),
299            Some(&"string_value".to_string())
300        );
301    }
302
303    #[test]
304    fn test_request_option_builder_add_header_multiple() {
305        let option = RequestOption::builder()
306            .add_header("Header1", "value1")
307            .add_header("Header2", "value2")
308            .add_header("Header3", "value3")
309            .build();
310
311        assert_eq!(option.header.len(), 3);
312        assert_eq!(option.header.get("Header1"), Some(&"value1".to_string()));
313        assert_eq!(option.header.get("Header2"), Some(&"value2".to_string()));
314        assert_eq!(option.header.get("Header3"), Some(&"value3".to_string()));
315    }
316
317    #[test]
318    fn test_request_option_builder_header_and_add_header() {
319        let mut initial_headers = HashMap::new();
320        initial_headers.insert("Initial-Header".to_string(), "initial_value".to_string());
321
322        let option = RequestOption::builder()
323            .header(initial_headers)
324            .add_header("Added-Header", "added_value")
325            .build();
326
327        assert_eq!(option.header.len(), 2);
328        assert_eq!(
329            option.header.get("Initial-Header"),
330            Some(&"initial_value".to_string())
331        );
332        assert_eq!(
333            option.header.get("Added-Header"),
334            Some(&"added_value".to_string())
335        );
336    }
337
338    #[test]
339    fn test_request_option_builder_chaining() {
340        let option = RequestOption::builder()
341            .tenant_key("test_tenant")
342            .user_access_token("user_token")
343            .app_access_token("app_token")
344            .tenant_access_token("tenant_token")
345            .need_helpdesk_auth(true)
346            .request_id("req_123")
347            .app_ticket("ticket_456")
348            .file_upload(true)
349            .file_download(false)
350            .add_header("X-Test", "test_value")
351            .build();
352
353        assert_eq!(option.tenant_key, "test_tenant");
354        assert_eq!(option.user_access_token, "user_token");
355        assert_eq!(option.app_access_token, "app_token");
356        assert_eq!(option.tenant_access_token, "tenant_token");
357        assert!(option.need_helpdesk_auth);
358        assert_eq!(option.request_id, "req_123");
359        assert_eq!(option.app_ticket, "ticket_456");
360        assert!(option.file_upload);
361        assert!(!option.file_download);
362        assert_eq!(option.header.len(), 1);
363        assert_eq!(option.header.get("X-Test"), Some(&"test_value".to_string()));
364    }
365
366    #[test]
367    fn test_request_option_builder_empty_strings() {
368        let option = RequestOption::builder()
369            .tenant_key("")
370            .user_access_token("")
371            .app_access_token("")
372            .tenant_access_token("")
373            .request_id("")
374            .app_ticket("")
375            .build();
376
377        assert_eq!(option.tenant_key, "");
378        assert_eq!(option.user_access_token, "");
379        assert_eq!(option.app_access_token, "");
380        assert_eq!(option.tenant_access_token, "");
381        assert_eq!(option.request_id, "");
382        assert_eq!(option.app_ticket, "");
383    }
384
385    #[test]
386    fn test_request_option_builder_special_characters() {
387        let option = RequestOption::builder()
388            .tenant_key("tenant@#$%^&*()")
389            .user_access_token("token_with_symbols!@#")
390            .request_id("req_with_unicode_测试")
391            .add_header("X-Special-Chars", "value@#$%")
392            .build();
393
394        assert_eq!(option.tenant_key, "tenant@#$%^&*()");
395        assert_eq!(option.user_access_token, "token_with_symbols!@#");
396        assert_eq!(option.request_id, "req_with_unicode_测试");
397        assert_eq!(
398            option.header.get("X-Special-Chars"),
399            Some(&"value@#$%".to_string())
400        );
401    }
402
403    #[test]
404    fn test_request_option_builder_overwrite_header() {
405        let mut initial_headers = HashMap::new();
406        initial_headers.insert("Test-Header".to_string(), "initial_value".to_string());
407
408        let option = RequestOption::builder()
409            .header(initial_headers)
410            .add_header("Test-Header", "overwritten_value")
411            .build();
412
413        assert_eq!(option.header.len(), 1);
414        assert_eq!(
415            option.header.get("Test-Header"),
416            Some(&"overwritten_value".to_string())
417        );
418    }
419
420    #[test]
421    fn test_request_option_builder_empty_header_map() {
422        let empty_headers = HashMap::new();
423
424        let option = RequestOption::builder().header(empty_headers).build();
425
426        assert!(option.header.is_empty());
427    }
428
429    #[test]
430    fn test_request_option_debug_clone() {
431        let option = RequestOption::builder()
432            .tenant_key("test")
433            .need_helpdesk_auth(true)
434            .build();
435
436        // Test Debug trait
437        let debug_str = format!("{:?}", option);
438        assert!(debug_str.contains("RequestOption"));
439
440        // Test Clone trait
441        let cloned_option = option.clone();
442        assert_eq!(option.tenant_key, cloned_option.tenant_key);
443        assert_eq!(option.need_helpdesk_auth, cloned_option.need_helpdesk_auth);
444    }
445
446    #[test]
447    fn test_request_option_builder_default() {
448        let builder = RequestOptionBuilder::default();
449        let option = builder.build();
450
451        // Should be equivalent to RequestOption::default()
452        let default_option = RequestOption::default();
453
454        assert_eq!(option.tenant_key, default_option.tenant_key);
455        assert_eq!(option.user_access_token, default_option.user_access_token);
456        assert_eq!(option.app_access_token, default_option.app_access_token);
457        assert_eq!(
458            option.tenant_access_token,
459            default_option.tenant_access_token
460        );
461        assert_eq!(option.need_helpdesk_auth, default_option.need_helpdesk_auth);
462        assert_eq!(option.request_id, default_option.request_id);
463        assert_eq!(option.app_ticket, default_option.app_ticket);
464        assert_eq!(option.file_upload, default_option.file_upload);
465        assert_eq!(option.file_download, default_option.file_download);
466        assert_eq!(option.header.len(), default_option.header.len());
467    }
468}