open_lark/service/cloud_docs/sheets/v2/data_operation/
merge_cells.rs1use 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 service::cloud_docs::sheets::v2::SpreadsheetService,
12};
13
14#[derive(Serialize, Debug, Default)]
16pub struct MergeCellsRequest {
17 #[serde(skip)]
18 api_request: ApiRequest,
19 #[serde(skip)]
20 spreadsheet_token: String,
21 range: String,
23 #[serde(rename = "mergeType")]
26 merge_type: String,
27}
28
29impl MergeCellsRequest {
30 pub fn builder() -> MergeCellsRequestBuilder {
31 MergeCellsRequestBuilder::default()
32 }
33}
34
35#[derive(Default)]
36pub struct MergeCellsRequestBuilder {
37 request: MergeCellsRequest,
38}
39
40impl MergeCellsRequestBuilder {
41 pub fn spreadsheet_token(mut self, spreadsheet_token: impl ToString) -> Self {
42 self.request.spreadsheet_token = spreadsheet_token.to_string();
43 self
44 }
45
46 pub fn range(mut self, range: impl ToString) -> Self {
48 self.request.range = range.to_string();
49 self
50 }
51
52 pub fn merge_type(mut self, merge_type: impl ToString) -> Self {
55 self.request.merge_type = merge_type.to_string();
56 self
57 }
58
59 pub fn build(mut self) -> MergeCellsRequest {
60 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
61 self.request
62 }
63}
64
65#[derive(Deserialize, Debug)]
66pub struct MergeCellsResponse {
67 #[serde(rename = "spreadsheetToken")]
69 pub spread_sheet_token: String,
70}
71
72impl ApiResponseTrait for MergeCellsResponse {
73 fn data_format() -> ResponseFormat {
74 ResponseFormat::Data
75 }
76}
77
78impl SpreadsheetService {
79 pub async fn merge_cells(
81 &self,
82 request: MergeCellsRequest,
83 option: Option<req_option::RequestOption>,
84 ) -> SDKResult<BaseResponse<MergeCellsResponse>> {
85 let mut api_req = request.api_request;
86 api_req.api_path =
87 SHEETS_V2_SPREADSHEET_MERGE_CELLS.replace("{}", &request.spreadsheet_token);
88 api_req.http_method = reqwest::Method::POST;
89 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::App];
90
91 let api_resp = crate::core::http::Transport::request(api_req, &self.config, option).await?;
92
93 Ok(api_resp)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use crate::{
100 core::{config::Config, constants::AppType},
101 service::cloud_docs::sheets::v2::{
102 data_operation::{MergeCellsRequest, MergeCellsResponse},
103 SpreadsheetService,
104 },
105 };
106
107 fn create_service() -> SpreadsheetService {
108 let config = Config::builder()
109 .app_id("test_app_id")
110 .app_secret("test_app_secret")
111 .app_type(AppType::SelfBuild)
112 .build();
113 SpreadsheetService { config }
114 }
115
116 #[test]
117 fn test_merge_cells_builder_default() {
118 let request = MergeCellsRequest::builder().build();
119
120 assert_eq!(request.spreadsheet_token, "");
121 assert_eq!(request.range, "");
122 assert_eq!(request.merge_type, "");
123 }
124
125 #[test]
126 fn test_merge_cells_builder_basic() {
127 let request = MergeCellsRequest::builder()
128 .spreadsheet_token("test_token")
129 .range("Sheet1!A1:B2")
130 .merge_type("MERGE_ALL")
131 .build();
132
133 assert_eq!(request.spreadsheet_token, "test_token");
134 assert_eq!(request.range, "Sheet1!A1:B2");
135 assert_eq!(request.merge_type, "MERGE_ALL");
136 }
137
138 #[test]
139 fn test_merge_cells_builder_all_options() {
140 let request = MergeCellsRequest::builder()
141 .spreadsheet_token("spreadsheet_abc123")
142 .range("Data!C3:F6")
143 .merge_type("MERGE_ROWS")
144 .build();
145
146 assert_eq!(request.spreadsheet_token, "spreadsheet_abc123");
147 assert_eq!(request.range, "Data!C3:F6");
148 assert_eq!(request.merge_type, "MERGE_ROWS");
149 }
150
151 #[test]
152 fn test_merge_cells_builder_chaining() {
153 let request = MergeCellsRequest::builder()
154 .spreadsheet_token("chain_test")
155 .range("Summary!A1:D1")
156 .merge_type("MERGE_COLUMNS")
157 .build();
158
159 assert_eq!(request.spreadsheet_token, "chain_test");
160 assert_eq!(request.range, "Summary!A1:D1");
161 assert_eq!(request.merge_type, "MERGE_COLUMNS");
162 }
163
164 #[test]
165 fn test_merge_cells_merge_all_type() {
166 let request = MergeCellsRequest::builder()
167 .spreadsheet_token("merge_all_test")
168 .range("Sheet1!A1:C3")
169 .merge_type("MERGE_ALL")
170 .build();
171
172 assert_eq!(request.spreadsheet_token, "merge_all_test");
173 assert_eq!(request.range, "Sheet1!A1:C3");
174 assert_eq!(request.merge_type, "MERGE_ALL");
175 }
176
177 #[test]
178 fn test_merge_cells_merge_rows_type() {
179 let request = MergeCellsRequest::builder()
180 .spreadsheet_token("merge_rows_test")
181 .range("Report!B2:E5")
182 .merge_type("MERGE_ROWS")
183 .build();
184
185 assert_eq!(request.spreadsheet_token, "merge_rows_test");
186 assert_eq!(request.range, "Report!B2:E5");
187 assert_eq!(request.merge_type, "MERGE_ROWS");
188 }
189
190 #[test]
191 fn test_merge_cells_merge_columns_type() {
192 let request = MergeCellsRequest::builder()
193 .spreadsheet_token("merge_columns_test")
194 .range("Table!A1:A10")
195 .merge_type("MERGE_COLUMNS")
196 .build();
197
198 assert_eq!(request.spreadsheet_token, "merge_columns_test");
199 assert_eq!(request.range, "Table!A1:A10");
200 assert_eq!(request.merge_type, "MERGE_COLUMNS");
201 }
202
203 #[test]
204 fn test_merge_cells_with_unicode_ranges() {
205 let request = MergeCellsRequest::builder()
206 .spreadsheet_token("unicode_test")
207 .range("数据表!A1:D4")
208 .merge_type("MERGE_ALL")
209 .build();
210
211 assert_eq!(request.spreadsheet_token, "unicode_test");
212 assert_eq!(request.range, "数据表!A1:D4");
213 assert_eq!(request.merge_type, "MERGE_ALL");
214 }
215
216 #[test]
217 fn test_merge_cells_with_special_characters() {
218 let request = MergeCellsRequest::builder()
219 .spreadsheet_token("special_chars_test")
220 .range("'Sheet With Spaces'!A1:B5")
221 .merge_type("MERGE_ROWS")
222 .build();
223
224 assert_eq!(request.spreadsheet_token, "special_chars_test");
225 assert_eq!(request.range, "'Sheet With Spaces'!A1:B5");
226 assert_eq!(request.merge_type, "MERGE_ROWS");
227 }
228
229 #[test]
230 fn test_merge_cells_single_cell_range() {
231 let request = MergeCellsRequest::builder()
232 .spreadsheet_token("single_cell_test")
233 .range("Sheet1!A1:A1")
234 .merge_type("MERGE_ALL")
235 .build();
236
237 assert_eq!(request.spreadsheet_token, "single_cell_test");
238 assert_eq!(request.range, "Sheet1!A1:A1");
239 assert_eq!(request.merge_type, "MERGE_ALL");
240 }
241
242 #[test]
243 fn test_merge_cells_large_range() {
244 let request = MergeCellsRequest::builder()
245 .spreadsheet_token("large_range_test")
246 .range("Data!A1:Z100")
247 .merge_type("MERGE_ALL")
248 .build();
249
250 assert_eq!(request.spreadsheet_token, "large_range_test");
251 assert_eq!(request.range, "Data!A1:Z100");
252 assert_eq!(request.merge_type, "MERGE_ALL");
253 }
254
255 #[test]
256 fn test_merge_cells_row_range() {
257 let request = MergeCellsRequest::builder()
258 .spreadsheet_token("row_range_test")
259 .range("Sheet1!A1:Z1")
260 .merge_type("MERGE_ROWS")
261 .build();
262
263 assert_eq!(request.spreadsheet_token, "row_range_test");
264 assert_eq!(request.range, "Sheet1!A1:Z1");
265 assert_eq!(request.merge_type, "MERGE_ROWS");
266 }
267
268 #[test]
269 fn test_merge_cells_column_range() {
270 let request = MergeCellsRequest::builder()
271 .spreadsheet_token("column_range_test")
272 .range("Sheet1!A1:A50")
273 .merge_type("MERGE_COLUMNS")
274 .build();
275
276 assert_eq!(request.spreadsheet_token, "column_range_test");
277 assert_eq!(request.range, "Sheet1!A1:A50");
278 assert_eq!(request.merge_type, "MERGE_COLUMNS");
279 }
280
281 #[test]
282 fn test_merge_cells_different_sheets() {
283 let sheets_and_ranges = [
284 ("Sheet1", "A1:B2"),
285 ("Summary", "C1:F1"),
286 ("Data", "A5:D10"),
287 ("第一页", "B3:E8"),
288 ];
289
290 for (sheet, range) in sheets_and_ranges.iter() {
291 let full_range = format!("{}!{}", sheet, range);
292 let request = MergeCellsRequest::builder()
293 .spreadsheet_token("multi_sheet_test")
294 .range(&full_range)
295 .merge_type("MERGE_ALL")
296 .build();
297
298 assert_eq!(request.range, full_range);
299 assert_eq!(request.merge_type, "MERGE_ALL");
300 }
301 }
302
303 #[test]
304 fn test_merge_cells_serialization() {
305 let request = MergeCellsRequest::builder()
306 .spreadsheet_token("serialization_test")
307 .range("Sheet1!A1:C3")
308 .merge_type("MERGE_ALL")
309 .build();
310
311 let serialized = serde_json::to_string(&request);
312 assert!(serialized.is_ok());
313
314 let json_value: serde_json::Value = serde_json::from_str(&serialized.unwrap()).unwrap();
315 assert_eq!(json_value["range"], "Sheet1!A1:C3");
316 assert_eq!(json_value["mergeType"], "MERGE_ALL");
317 }
318
319 #[test]
320 fn test_merge_cells_response_deserialization() {
321 let response_json = serde_json::json!({
322 "spreadsheetToken": "test_token_123"
323 });
324
325 let response: MergeCellsResponse = serde_json::from_value(response_json).unwrap();
326
327 assert_eq!(response.spread_sheet_token, "test_token_123");
328 }
329
330 #[test]
331 fn test_merge_cells_complex_range_references() {
332 let complex_ranges = vec![
333 "Sheet1!A1:D5",
334 "'Data Sheet'!B2:F10",
335 "工作表!C3:G7",
336 "Sheet-Name_123!A10:E15",
337 "'Sheet (1)'!D1:H4",
338 ];
339
340 for range in complex_ranges {
341 let request = MergeCellsRequest::builder()
342 .spreadsheet_token("complex_ref_test")
343 .range(range)
344 .merge_type("MERGE_ALL")
345 .build();
346
347 assert_eq!(request.range, range);
348 }
349 }
350
351 #[test]
352 fn test_merge_cells_all_merge_types() {
353 let merge_types = vec!["MERGE_ALL", "MERGE_ROWS", "MERGE_COLUMNS"];
354
355 for merge_type in merge_types {
356 let request = MergeCellsRequest::builder()
357 .spreadsheet_token("all_types_test")
358 .range("Sheet1!A1:C3")
359 .merge_type(merge_type)
360 .build();
361
362 assert_eq!(request.merge_type, merge_type);
363 }
364 }
365
366 #[test]
367 fn test_merge_cells_service_creation() {
368 let service = create_service();
369 assert_eq!(service.config.app_id, "test_app_id");
370 assert_eq!(service.config.app_secret, "test_app_secret");
371 assert!(matches!(service.config.app_type, AppType::SelfBuild));
372 }
373
374 #[test]
375 fn test_merge_cells_builder_overwrites() {
376 let request = MergeCellsRequest::builder()
377 .spreadsheet_token("original_token")
378 .spreadsheet_token("final_token") .range("Sheet1!A1:B2")
380 .range("Sheet2!C3:D4") .merge_type("MERGE_ROWS")
382 .merge_type("MERGE_ALL") .build();
384
385 assert_eq!(request.spreadsheet_token, "final_token");
386 assert_eq!(request.range, "Sheet2!C3:D4");
387 assert_eq!(request.merge_type, "MERGE_ALL");
388 }
389
390 #[test]
391 fn test_merge_cells_case_sensitive_merge_types() {
392 let merge_types = vec![
394 "MERGE_ALL",
395 "merge_all", "Merge_All", "MERGE_ROWS",
398 "merge_rows",
399 "MERGE_COLUMNS",
400 "merge_columns",
401 ];
402
403 for merge_type in merge_types {
404 let request = MergeCellsRequest::builder()
405 .spreadsheet_token("case_test")
406 .range("Sheet1!A1:B2")
407 .merge_type(merge_type)
408 .build();
409
410 assert_eq!(request.merge_type, merge_type);
411 }
412 }
413
414 #[test]
415 fn test_merge_cells_very_long_token() {
416 let very_long_token = "a".repeat(1000);
417 let request = MergeCellsRequest::builder()
418 .spreadsheet_token(&very_long_token)
419 .range("Sheet1!A1:B2")
420 .merge_type("MERGE_ALL")
421 .build();
422
423 assert_eq!(request.spreadsheet_token, very_long_token);
424 assert_eq!(request.range, "Sheet1!A1:B2");
425 assert_eq!(request.merge_type, "MERGE_ALL");
426 }
427
428 #[test]
429 fn test_merge_cells_response_struct_debug() {
430 let response = MergeCellsResponse {
431 spread_sheet_token: "debug_test".to_string(),
432 };
433
434 let debug_str = format!("{:?}", response);
435 assert!(debug_str.contains("debug_test"));
436 assert!(debug_str.contains("MergeCellsResponse"));
437 }
438
439 #[test]
440 fn test_merge_cells_request_struct_debug() {
441 let request = MergeCellsRequest::builder()
442 .spreadsheet_token("debug_token")
443 .range("Sheet1!A1:B2")
444 .merge_type("MERGE_ALL")
445 .build();
446
447 let debug_str = format!("{:?}", request);
448 assert!(debug_str.contains("debug_token"));
449 assert!(debug_str.contains("Sheet1!A1:B2"));
450 assert!(debug_str.contains("MERGE_ALL"));
451 }
452
453 #[test]
454 fn test_merge_cells_empty_strings() {
455 let request = MergeCellsRequest::builder()
457 .spreadsheet_token("")
458 .range("")
459 .merge_type("")
460 .build();
461
462 assert_eq!(request.spreadsheet_token, "");
463 assert_eq!(request.range, "");
464 assert_eq!(request.merge_type, "");
465 }
466}