1use serde::{Deserialize, Serialize};
2
3use crate::{
4 core::{
5 api_req::ApiRequest,
6 api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
7 constants::AccessTokenType,
8 endpoints::cloud_docs::*,
9 req_option, SDKResult,
10 },
11 impl_executable_builder_owned,
12 service::cloud_docs::sheets::v2::{
13 spreadsheet_sheet::UpdateSheetProperty, SpreadsheetSheetService,
14 },
15};
16
17#[derive(Serialize, Deserialize, Debug, Default)]
18pub struct OperateSheetsRequest {
19 #[serde(skip)]
20 api_request: ApiRequest,
21 #[serde(skip)]
22 spreadsheet_token: String,
23 requests: Vec<OperateSheetsRequestElem>,
25}
26
27#[derive(Serialize, Deserialize, Debug)]
28pub enum OperateSheetsRequestElem {
32 #[serde(rename = "addSheet")]
34 AddSheet {
35 properties: AddSheetProperty,
37 },
38 #[serde(rename = "copySheet")]
40 CopySheet {
41 source: CopySheetSource,
43 destination: CopySheetDestination,
45 },
46 #[serde(rename = "updateSheet")]
48 UpdateSheet {
49 properties: UpdateSheetProperty,
51 },
52 #[serde(rename = "deleteSheet")]
54 DeleteSheet {
55 #[serde(rename = "sheetId")]
57 sheet_id: String,
58 },
59}
60
61#[derive(Serialize, Deserialize, Debug, Default)]
63pub struct AddSheetProperty {
64 pub title: String,
66 pub index: Option<i32>,
68}
69
70#[derive(Serialize, Deserialize, Debug, Default)]
72pub struct CopySheetSource {
73 #[serde(rename = "sheetId")]
75 sheet_id: String,
76}
77
78#[derive(Serialize, Deserialize, Debug, Default)]
80pub struct CopySheetDestination {
81 title: Option<String>,
83}
84
85impl OperateSheetsRequest {
86 pub fn builder() -> OperateSheetsRequestBuilder {
87 OperateSheetsRequestBuilder::default()
88 }
89}
90
91#[derive(Default)]
92pub struct OperateSheetsRequestBuilder {
93 request: OperateSheetsRequest,
94}
95
96impl OperateSheetsRequestBuilder {
97 pub fn spreadsheet_token(mut self, spreadsheet_token: impl ToString) -> Self {
98 self.request.spreadsheet_token = spreadsheet_token.to_string();
99 self
100 }
101
102 pub fn add_sheet(mut self, title: impl ToString, index: Option<i32>) -> Self {
104 self.request
105 .requests
106 .push(OperateSheetsRequestElem::AddSheet {
107 properties: AddSheetProperty {
108 title: title.to_string(),
109 index,
110 },
111 });
112 self
113 }
114
115 pub fn copy_sheet(mut self, source: impl ToString, destination: Option<String>) -> Self {
117 self.request
118 .requests
119 .push(OperateSheetsRequestElem::CopySheet {
120 source: CopySheetSource {
121 sheet_id: source.to_string(),
122 },
123 destination: CopySheetDestination { title: destination },
124 });
125 self
126 }
127
128 pub fn delete_sheet(mut self, sheet_id: impl ToString) -> Self {
130 self.request
131 .requests
132 .push(OperateSheetsRequestElem::DeleteSheet {
133 sheet_id: sheet_id.to_string(),
134 });
135 self
136 }
137
138 pub fn build(mut self) -> OperateSheetsRequest {
139 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
140 self.request
141 }
142}
143
144impl_executable_builder_owned!(
145 OperateSheetsRequestBuilder,
146 SpreadsheetSheetService,
147 OperateSheetsRequest,
148 BaseResponse<OperateSheetResponse>,
149 operate
150);
151
152impl SpreadsheetSheetService {
153 pub async fn operate(
156 &self,
157 request: OperateSheetsRequest,
158 option: Option<req_option::RequestOption>,
159 ) -> SDKResult<BaseResponse<OperateSheetResponse>> {
160 let mut api_req = request.api_request;
161 api_req.api_path =
162 SHEETS_V2_SPREADSHEET_SHEETS_BATCH_UPDATE.replace("{}", &request.spreadsheet_token);
163 api_req.http_method = reqwest::Method::POST;
164 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
165
166 let api_resp =
167 crate::core::http::Transport::request(api_req, &self.config_arc, option).await?;
168
169 Ok(api_resp)
170 }
171}
172
173#[derive(Deserialize, Debug)]
174pub struct OperateSheetResponse {
175 pub replies: Vec<OperateSheetReply>,
176}
177
178impl ApiResponseTrait for OperateSheetResponse {
179 fn data_format() -> ResponseFormat {
180 ResponseFormat::Data
181 }
182}
183
184#[derive(Deserialize, Debug)]
185pub enum OperateSheetReply {
189 #[serde(rename = "addSheet")]
191 AddSheet { properties: SheetResponse },
192 #[serde(rename = "copySheet")]
194 CopySheet { properties: SheetResponse },
195 #[serde(rename = "updateSheet")]
197 UpdateSheet { properties: UpdateSheetProperty },
198 #[serde(rename = "deleteSheet")]
200 DeleteSheet {
201 result: bool,
203 #[serde(rename = "sheetId")]
205 sheet_id: String,
206 },
207}
208
209#[derive(Deserialize, Debug)]
210pub struct SheetResponse {
212 #[serde(rename = "sheetId")]
214 pub sheet_id: String,
215 pub title: String,
217 pub index: Option<i32>,
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use crate::core::config::Config;
225 use rstest::rstest;
226
227 fn create_test_config() -> Config {
228 Config::builder()
229 .app_id("test_app_id")
230 .app_secret("test_app_secret")
231 .build()
232 }
233
234 fn create_test_service() -> SpreadsheetSheetService {
235 SpreadsheetSheetService::new(create_test_config())
236 }
237
238 #[test]
239 fn test_operate_sheets_request_builder_creation() {
240 let builder = OperateSheetsRequest::builder();
241 let request = builder.build();
242
243 assert_eq!(request.spreadsheet_token, "");
244 assert!(request.requests.is_empty());
245 }
246
247 #[test]
248 fn test_operate_sheets_request_builder_with_spreadsheet_token() {
249 let request = OperateSheetsRequest::builder()
250 .spreadsheet_token("test_spreadsheet_123")
251 .build();
252
253 assert_eq!(request.spreadsheet_token, "test_spreadsheet_123");
254 }
255
256 #[test]
257 fn test_operate_sheets_request_builder_with_add_sheet() {
258 let request = OperateSheetsRequest::builder()
259 .add_sheet("New Sheet", Some(2))
260 .build();
261
262 assert_eq!(request.requests.len(), 1);
263 match &request.requests[0] {
264 OperateSheetsRequestElem::AddSheet { properties } => {
265 assert_eq!(properties.title, "New Sheet");
266 assert_eq!(properties.index, Some(2));
267 }
268 _ => panic!("Expected AddSheet variant"),
269 }
270 }
271
272 #[test]
273 fn test_operate_sheets_request_builder_with_add_sheet_no_index() {
274 let request = OperateSheetsRequest::builder()
275 .add_sheet("Default Position Sheet", None)
276 .build();
277
278 assert_eq!(request.requests.len(), 1);
279 match &request.requests[0] {
280 OperateSheetsRequestElem::AddSheet { properties } => {
281 assert_eq!(properties.title, "Default Position Sheet");
282 assert!(properties.index.is_none());
283 }
284 _ => panic!("Expected AddSheet variant"),
285 }
286 }
287
288 #[test]
289 fn test_operate_sheets_request_builder_with_copy_sheet() {
290 let request = OperateSheetsRequest::builder()
291 .copy_sheet("source_sheet_123", Some("Copied Sheet".to_string()))
292 .build();
293
294 assert_eq!(request.requests.len(), 1);
295 match &request.requests[0] {
296 OperateSheetsRequestElem::CopySheet {
297 source,
298 destination,
299 } => {
300 assert_eq!(source.sheet_id, "source_sheet_123");
301 assert_eq!(destination.title, Some("Copied Sheet".to_string()));
302 }
303 _ => panic!("Expected CopySheet variant"),
304 }
305 }
306
307 #[test]
308 fn test_operate_sheets_request_builder_with_copy_sheet_no_title() {
309 let request = OperateSheetsRequest::builder()
310 .copy_sheet("source_sheet_456", None)
311 .build();
312
313 assert_eq!(request.requests.len(), 1);
314 match &request.requests[0] {
315 OperateSheetsRequestElem::CopySheet {
316 source,
317 destination,
318 } => {
319 assert_eq!(source.sheet_id, "source_sheet_456");
320 assert!(destination.title.is_none());
321 }
322 _ => panic!("Expected CopySheet variant"),
323 }
324 }
325
326 #[test]
327 fn test_operate_sheets_request_builder_with_delete_sheet() {
328 let request = OperateSheetsRequest::builder()
329 .delete_sheet("sheet_to_delete_789")
330 .build();
331
332 assert_eq!(request.requests.len(), 1);
333 match &request.requests[0] {
334 OperateSheetsRequestElem::DeleteSheet { sheet_id } => {
335 assert_eq!(sheet_id, "sheet_to_delete_789");
336 }
337 _ => panic!("Expected DeleteSheet variant"),
338 }
339 }
340
341 #[test]
342 fn test_operate_sheets_request_builder_chaining_multiple_operations() {
343 let request = OperateSheetsRequest::builder()
344 .spreadsheet_token("my_spreadsheet")
345 .add_sheet("Sheet 1", Some(0))
346 .add_sheet("Sheet 2", Some(1))
347 .copy_sheet("existing_sheet", Some("Copy of Existing".to_string()))
348 .delete_sheet("old_sheet")
349 .build();
350
351 assert_eq!(request.spreadsheet_token, "my_spreadsheet");
352 assert_eq!(request.requests.len(), 4);
353
354 match &request.requests[0] {
356 OperateSheetsRequestElem::AddSheet { properties } => {
357 assert_eq!(properties.title, "Sheet 1");
358 assert_eq!(properties.index, Some(0));
359 }
360 _ => panic!("Expected AddSheet variant"),
361 }
362
363 match &request.requests[1] {
364 OperateSheetsRequestElem::AddSheet { properties } => {
365 assert_eq!(properties.title, "Sheet 2");
366 assert_eq!(properties.index, Some(1));
367 }
368 _ => panic!("Expected AddSheet variant"),
369 }
370
371 match &request.requests[2] {
372 OperateSheetsRequestElem::CopySheet {
373 source,
374 destination,
375 } => {
376 assert_eq!(source.sheet_id, "existing_sheet");
377 assert_eq!(destination.title, Some("Copy of Existing".to_string()));
378 }
379 _ => panic!("Expected CopySheet variant"),
380 }
381
382 match &request.requests[3] {
383 OperateSheetsRequestElem::DeleteSheet { sheet_id } => {
384 assert_eq!(sheet_id, "old_sheet");
385 }
386 _ => panic!("Expected DeleteSheet variant"),
387 }
388 }
389
390 #[test]
391 fn test_operate_sheets_request_default() {
392 let request = OperateSheetsRequest::default();
393
394 assert_eq!(request.spreadsheet_token, "");
395 assert!(request.requests.is_empty());
396 }
397
398 #[test]
399 fn test_operate_sheets_request_builder_default() {
400 let builder = OperateSheetsRequestBuilder::default();
401 let request = builder.build();
402
403 assert_eq!(request.spreadsheet_token, "");
404 assert!(request.requests.is_empty());
405 }
406
407 #[test]
408 fn test_add_sheet_property_default() {
409 let props = AddSheetProperty::default();
410
411 assert_eq!(props.title, "");
412 assert!(props.index.is_none());
413 }
414
415 #[test]
416 fn test_copy_sheet_source_default() {
417 let source = CopySheetSource::default();
418
419 assert_eq!(source.sheet_id, "");
420 }
421
422 #[test]
423 fn test_copy_sheet_destination_default() {
424 let destination = CopySheetDestination::default();
425
426 assert!(destination.title.is_none());
427 }
428
429 #[test]
430 fn test_operate_sheets_request_serialization() {
431 let request = OperateSheetsRequest::builder()
432 .spreadsheet_token("token123")
433 .add_sheet("Test Sheet", Some(1))
434 .copy_sheet("source123", Some("Copy Title".to_string()))
435 .delete_sheet("delete456")
436 .build();
437
438 let serialized = serde_json::to_string(&request);
440 assert!(serialized.is_ok());
441
442 let json_str = serialized.unwrap();
443 assert!(json_str.contains("requests"));
444 assert!(json_str.contains("addSheet"));
445 assert!(json_str.contains("copySheet"));
446 assert!(json_str.contains("deleteSheet"));
447 assert!(json_str.contains("Test Sheet"));
448 assert!(json_str.contains("source123"));
449 assert!(json_str.contains("Copy Title"));
450 assert!(json_str.contains("delete456"));
451 }
452
453 #[test]
454 fn test_operate_sheets_request_serialization_empty() {
455 let request = OperateSheetsRequest::builder()
456 .spreadsheet_token("token123")
457 .build();
458
459 let serialized = serde_json::to_string(&request);
460 assert!(serialized.is_ok());
461
462 let json_str = serialized.unwrap();
463 assert!(json_str.contains("requests"));
464 assert!(json_str.contains("[]")); }
466
467 #[test]
468 fn test_operate_sheets_request_debug() {
469 let request = OperateSheetsRequest::builder()
470 .spreadsheet_token("debug_token")
471 .add_sheet("Debug Sheet", Some(0))
472 .build();
473
474 let debug_str = format!("{:?}", request);
475 assert!(debug_str.contains("OperateSheetsRequest"));
476 assert!(debug_str.contains("debug_token"));
477 assert!(debug_str.contains("Debug Sheet"));
478 }
479
480 #[test]
481 fn test_operate_sheets_request_with_empty_strings() {
482 let request = OperateSheetsRequest::builder()
483 .spreadsheet_token("")
484 .add_sheet("", None)
485 .copy_sheet("", None)
486 .delete_sheet("")
487 .build();
488
489 assert_eq!(request.spreadsheet_token, "");
490 assert_eq!(request.requests.len(), 3);
491 }
492
493 #[test]
494 fn test_operate_sheets_request_with_special_characters() {
495 let request = OperateSheetsRequest::builder()
496 .spreadsheet_token("token_with_特殊字符_🎯")
497 .add_sheet("工作表_📋_测试", Some(1))
498 .copy_sheet("源工作表_🔗", Some("副本_🎨".to_string()))
499 .delete_sheet("删除工作表_🗑️")
500 .build();
501
502 assert_eq!(request.spreadsheet_token, "token_with_特殊字符_🎯");
503
504 match &request.requests[0] {
505 OperateSheetsRequestElem::AddSheet { properties } => {
506 assert_eq!(properties.title, "工作表_📋_测试");
507 }
508 _ => panic!("Expected AddSheet variant"),
509 }
510
511 match &request.requests[1] {
512 OperateSheetsRequestElem::CopySheet {
513 source,
514 destination,
515 } => {
516 assert_eq!(source.sheet_id, "源工作表_🔗");
517 assert_eq!(destination.title, Some("副本_🎨".to_string()));
518 }
519 _ => panic!("Expected CopySheet variant"),
520 }
521
522 match &request.requests[2] {
523 OperateSheetsRequestElem::DeleteSheet { sheet_id } => {
524 assert_eq!(sheet_id, "删除工作表_🗑️");
525 }
526 _ => panic!("Expected DeleteSheet variant"),
527 }
528 }
529
530 #[rstest]
531 #[case(-1)] #[case(0)] #[case(1)] #[case(10)] #[case(1000)] fn test_operate_sheets_request_with_various_indices(#[case] index: i32) {
537 let request = OperateSheetsRequest::builder()
538 .add_sheet("Test Sheet", Some(index))
539 .build();
540
541 match &request.requests[0] {
542 OperateSheetsRequestElem::AddSheet { properties } => {
543 assert_eq!(properties.index, Some(index));
544 }
545 _ => panic!("Expected AddSheet variant"),
546 }
547 }
548
549 #[test]
550 fn test_operate_sheets_request_with_maximum_values() {
551 let request = OperateSheetsRequest::builder()
552 .add_sheet("Max Index Sheet", Some(i32::MAX))
553 .build();
554
555 match &request.requests[0] {
556 OperateSheetsRequestElem::AddSheet { properties } => {
557 assert_eq!(properties.index, Some(i32::MAX));
558 }
559 _ => panic!("Expected AddSheet variant"),
560 }
561 }
562
563 #[test]
564 fn test_operate_sheets_request_with_minimum_values() {
565 let request = OperateSheetsRequest::builder()
566 .add_sheet("Min Index Sheet", Some(i32::MIN))
567 .build();
568
569 match &request.requests[0] {
570 OperateSheetsRequestElem::AddSheet { properties } => {
571 assert_eq!(properties.index, Some(i32::MIN));
572 }
573 _ => panic!("Expected AddSheet variant"),
574 }
575 }
576
577 #[test]
578 fn test_operate_sheets_request_api_request_body_serialization() {
579 let request = OperateSheetsRequest::builder()
580 .spreadsheet_token("body_test_token")
581 .add_sheet("Body Test Sheet", Some(0))
582 .delete_sheet("delete_me")
583 .build();
584
585 assert!(!request.api_request.body.is_empty());
587
588 let body_str = String::from_utf8(request.api_request.body).unwrap();
590 let parsed: serde_json::Value = serde_json::from_str(&body_str).unwrap();
591
592 assert!(parsed.get("requests").is_some());
593 let requests = parsed.get("requests").unwrap().as_array().unwrap();
594 assert_eq!(requests.len(), 2);
595
596 assert!(requests[0].get("addSheet").is_some());
598 let add_sheet = requests[0].get("addSheet").unwrap();
599 assert!(add_sheet.get("properties").is_some());
600
601 assert!(requests[1].get("deleteSheet").is_some());
603 let delete_sheet = requests[1].get("deleteSheet").unwrap();
604 assert_eq!(delete_sheet.get("sheetId").unwrap(), "delete_me");
605 }
606
607 #[test]
608 fn test_operate_sheets_request_builder_multiple_calls() {
609 let mut builder = OperateSheetsRequest::builder();
610
611 builder = builder.spreadsheet_token("first_token");
613 builder = builder.spreadsheet_token("second_token");
614
615 builder = builder.add_sheet("Sheet 1", Some(0));
617 builder = builder.add_sheet("Sheet 2", Some(1));
618
619 let request = builder.build();
620
621 assert_eq!(request.spreadsheet_token, "second_token");
622 assert_eq!(request.requests.len(), 2);
623 }
624
625 #[test]
626 fn test_spreadsheet_sheet_service_creation() {
627 let service = create_test_service();
628
629 assert_eq!(service.config.app_id, "test_app_id");
631 }
632
633 #[test]
634 fn test_operate_sheet_response_data_format() {
635 assert_eq!(OperateSheetResponse::data_format(), ResponseFormat::Data);
636 }
637
638 #[test]
639 fn test_operate_sheet_reply_deserialization_add_sheet() {
640 let json_response = r#"{
641 "addSheet": {
642 "properties": {
643 "sheetId": "sheet123",
644 "title": "New Sheet",
645 "index": 1
646 }
647 }
648 }"#;
649
650 let reply: OperateSheetReply = serde_json::from_str(json_response).unwrap();
651
652 match reply {
653 OperateSheetReply::AddSheet { properties } => {
654 assert_eq!(properties.sheet_id, "sheet123");
655 assert_eq!(properties.title, "New Sheet");
656 assert_eq!(properties.index, Some(1));
657 }
658 _ => panic!("Expected AddSheet variant"),
659 }
660 }
661
662 #[test]
663 fn test_operate_sheet_reply_deserialization_copy_sheet() {
664 let json_response = r#"{
665 "copySheet": {
666 "properties": {
667 "sheetId": "copy456",
668 "title": "Copied Sheet",
669 "index": 2
670 }
671 }
672 }"#;
673
674 let reply: OperateSheetReply = serde_json::from_str(json_response).unwrap();
675
676 match reply {
677 OperateSheetReply::CopySheet { properties } => {
678 assert_eq!(properties.sheet_id, "copy456");
679 assert_eq!(properties.title, "Copied Sheet");
680 assert_eq!(properties.index, Some(2));
681 }
682 _ => panic!("Expected CopySheet variant"),
683 }
684 }
685
686 #[test]
687 fn test_operate_sheet_reply_deserialization_delete_sheet() {
688 let json_response = r#"{
689 "deleteSheet": {
690 "result": true,
691 "sheetId": "deleted789"
692 }
693 }"#;
694
695 let reply: OperateSheetReply = serde_json::from_str(json_response).unwrap();
696
697 match reply {
698 OperateSheetReply::DeleteSheet { result, sheet_id } => {
699 assert!(result);
700 assert_eq!(sheet_id, "deleted789");
701 }
702 _ => panic!("Expected DeleteSheet variant"),
703 }
704 }
705
706 #[test]
707 fn test_operate_sheet_response_deserialization() {
708 let json_response = r#"{
709 "replies": [
710 {
711 "addSheet": {
712 "properties": {
713 "sheetId": "new123",
714 "title": "Added Sheet",
715 "index": 0
716 }
717 }
718 },
719 {
720 "deleteSheet": {
721 "result": true,
722 "sheetId": "old456"
723 }
724 }
725 ]
726 }"#;
727
728 let response: OperateSheetResponse = serde_json::from_str(json_response).unwrap();
729
730 assert_eq!(response.replies.len(), 2);
731
732 match &response.replies[0] {
733 OperateSheetReply::AddSheet { properties } => {
734 assert_eq!(properties.sheet_id, "new123");
735 assert_eq!(properties.title, "Added Sheet");
736 assert_eq!(properties.index, Some(0));
737 }
738 _ => panic!("Expected AddSheet variant"),
739 }
740
741 match &response.replies[1] {
742 OperateSheetReply::DeleteSheet { result, sheet_id } => {
743 assert!(result);
744 assert_eq!(sheet_id, "old456");
745 }
746 _ => panic!("Expected DeleteSheet variant"),
747 }
748 }
749
750 #[test]
751 fn test_operate_sheets_request_edge_cases() {
752 let long_token = "a".repeat(10000);
754 let request = OperateSheetsRequest::builder()
755 .spreadsheet_token(&long_token)
756 .build();
757 assert_eq!(request.spreadsheet_token, long_token);
758
759 let long_title = "Sheet_".repeat(1000);
761 let request = OperateSheetsRequest::builder()
762 .add_sheet(&long_title, Some(0))
763 .build();
764
765 match &request.requests[0] {
766 OperateSheetsRequestElem::AddSheet { properties } => {
767 assert_eq!(properties.title, long_title);
768 }
769 _ => panic!("Expected AddSheet variant"),
770 }
771
772 let long_sheet_id = "sheet_id_".repeat(500);
774 let request = OperateSheetsRequest::builder()
775 .copy_sheet(&long_sheet_id, None)
776 .delete_sheet(&long_sheet_id)
777 .build();
778
779 match &request.requests[0] {
780 OperateSheetsRequestElem::CopySheet { source, .. } => {
781 assert_eq!(source.sheet_id, long_sheet_id);
782 }
783 _ => panic!("Expected CopySheet variant"),
784 }
785 }
786
787 #[test]
788 fn test_operate_sheets_request_memory_efficiency() {
789 let mut builder = OperateSheetsRequest::builder().spreadsheet_token("memory_test");
791
792 for i in 0..100 {
794 builder = builder.add_sheet(format!("Sheet_{}", i), Some(i));
795 builder = builder.copy_sheet(format!("source_{}", i), Some(format!("copy_{}", i)));
796 builder = builder.delete_sheet(format!("delete_{}", i));
797 }
798
799 let request = builder.build();
800
801 assert_eq!(request.requests.len(), 300); match &request.requests[0] {
805 OperateSheetsRequestElem::AddSheet { properties } => {
806 assert_eq!(properties.title, "Sheet_0");
807 assert_eq!(properties.index, Some(0));
808 }
809 _ => panic!("Expected AddSheet variant"),
810 }
811
812 match &request.requests[299] {
813 OperateSheetsRequestElem::DeleteSheet { sheet_id } => {
814 assert_eq!(sheet_id, "delete_99");
815 }
816 _ => panic!("Expected DeleteSheet variant"),
817 }
818 }
819
820 #[test]
821 fn test_sheet_response_debug() {
822 let response = SheetResponse {
823 sheet_id: "debug_sheet_123".to_string(),
824 title: "Debug Sheet".to_string(),
825 index: Some(5),
826 };
827
828 let debug_str = format!("{:?}", response);
829 assert!(debug_str.contains("SheetResponse"));
830 assert!(debug_str.contains("debug_sheet_123"));
831 assert!(debug_str.contains("Debug Sheet"));
832 assert!(debug_str.contains("Some(5)"));
833 }
834
835 #[test]
836 fn test_operate_sheets_request_unicode_handling() {
837 let request = OperateSheetsRequest::builder()
838 .spreadsheet_token("令牌_🔑_test")
839 .add_sheet("工作表_📋_name", Some(0))
840 .copy_sheet("源_🎯", Some("目标_🎪".to_string()))
841 .delete_sheet("删除_🗑️")
842 .build();
843
844 assert_eq!(request.spreadsheet_token, "令牌_🔑_test");
845
846 let serialized = serde_json::to_string(&request);
848 assert!(serialized.is_ok());
849
850 let json_str = serialized.unwrap();
851 assert!(json_str.contains("工作表_📋_name"));
852 assert!(json_str.contains("源_🎯"));
853 assert!(json_str.contains("目标_🎪"));
854 assert!(json_str.contains("删除_🗑️"));
855 }
856
857 #[test]
858 fn test_operate_sheets_request_builder_partial_configuration() {
859 let request1 = OperateSheetsRequest::builder()
861 .add_sheet("Only Add", Some(1))
862 .build();
863
864 assert_eq!(request1.requests.len(), 1);
865
866 let request2 = OperateSheetsRequest::builder()
867 .copy_sheet("source", None)
868 .delete_sheet("target")
869 .build();
870
871 assert_eq!(request2.requests.len(), 2);
872
873 let request3 = OperateSheetsRequest::builder()
874 .spreadsheet_token("test")
875 .build();
876
877 assert!(request3.requests.is_empty());
878 }
879}