open_lark/service/cloud_docs/sheets/v2/data_operation/
append_data.rs1use serde::Serialize;
2use serde_json::Value;
3
4use crate::{
5 core::{
6 api_req::ApiRequest, api_resp::BaseResponse, constants::AccessTokenType,
7 endpoints::cloud_docs::*, req_option::RequestOption, SDKResult,
8 },
9 impl_executable_builder_owned,
10 service::cloud_docs::sheets::v2::{
11 data_operation::{UpdateSheetDataResponse, ValueRangeRequest},
12 SpreadsheetSheetService,
13 },
14};
15
16#[derive(Serialize, Debug, Default)]
18pub struct AppendDataRequest {
19 #[serde(skip)]
20 api_request: ApiRequest,
21 #[serde(skip)]
22 spreadsheet_token: String,
23 #[serde(rename = "insertDataOption")]
26 insert_data_option: String,
27 #[serde(rename = "valueRange")]
29 value_range: ValueRangeRequest,
30}
31
32impl AppendDataRequest {
33 pub fn builder() -> AppendDataRequestBuilder {
34 AppendDataRequestBuilder::default()
35 }
36}
37
38#[derive(Default)]
39pub struct AppendDataRequestBuilder {
40 request: AppendDataRequest,
41}
42
43impl AppendDataRequestBuilder {
44 pub fn spreadsheet_token(mut self, spreadsheet_token: impl ToString) -> Self {
45 self.request.spreadsheet_token = spreadsheet_token.to_string();
46 self
47 }
48
49 pub fn range(mut self, range: impl ToString) -> Self {
52 self.request.value_range.range = range.to_string();
53 self
54 }
55
56 pub fn values(mut self, values: Value) -> Self {
58 self.request.value_range.values = values;
59 self
60 }
61
62 pub fn build(mut self) -> AppendDataRequest {
63 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
64 self.request
65 }
66}
67
68pub type AppendDataResponse = UpdateSheetDataResponse;
69
70impl_executable_builder_owned!(
72 AppendDataRequestBuilder,
73 SpreadsheetSheetService,
74 AppendDataRequest,
75 BaseResponse<AppendDataResponse>,
76 append_data
77);
78
79impl SpreadsheetSheetService {
80 pub async fn append_data(
82 &self,
83 request: AppendDataRequest,
84 option: Option<RequestOption>,
85 ) -> SDKResult<BaseResponse<AppendDataResponse>> {
86 let mut api_req = request.api_request;
87 api_req.api_path =
88 SHEETS_V2_SPREADSHEET_VALUES_APPEND.replace("{}", &request.spreadsheet_token);
89 api_req.http_method = reqwest::Method::POST;
90 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::App];
91
92 let api_resp =
93 crate::core::http::Transport::request(api_req, &self.config_arc, option).await?;
94
95 Ok(api_resp)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use crate::core::config::Config;
103 use serde_json::{json, Value};
104
105 fn create_test_config() -> Config {
106 Config::builder()
107 .app_id("test_app_id")
108 .app_secret("test_app_secret")
109 .build()
110 }
111
112 fn create_test_service() -> SpreadsheetSheetService {
113 SpreadsheetSheetService::new(create_test_config())
114 }
115
116 #[test]
117 fn test_append_data_request_builder_creation() {
118 let builder = AppendDataRequest::builder();
119 let request = builder.build();
120
121 assert_eq!(request.spreadsheet_token, "");
122 assert_eq!(request.value_range.range, "");
123 assert_eq!(request.value_range.values, Value::Null);
124 assert_eq!(request.insert_data_option, "");
125 }
126
127 #[test]
128 fn test_append_data_request_builder_with_spreadsheet_token() {
129 let request = AppendDataRequest::builder()
130 .spreadsheet_token("test_token_123")
131 .build();
132
133 assert_eq!(request.spreadsheet_token, "test_token_123");
134 }
135
136 #[test]
137 fn test_append_data_request_builder_with_range() {
138 let request = AppendDataRequest::builder().range("Sheet1!A1:C10").build();
139
140 assert_eq!(request.value_range.range, "Sheet1!A1:C10");
141 }
142
143 #[test]
144 fn test_append_data_request_builder_with_values() {
145 let test_values = json!([
146 ["Name", "Age", "City"],
147 ["John", 25, "NYC"],
148 ["Jane", 30, "LA"]
149 ]);
150
151 let request = AppendDataRequest::builder()
152 .values(test_values.clone())
153 .build();
154
155 assert_eq!(request.value_range.values, test_values);
156 }
157
158 #[test]
159 fn test_append_data_request_builder_chaining() {
160 let test_values = json!([["A", "B"], ["1", "2"]]);
161
162 let request = AppendDataRequest::builder()
163 .spreadsheet_token("my_sheet_token")
164 .range("Sheet1!A1:B2")
165 .values(test_values.clone())
166 .build();
167
168 assert_eq!(request.spreadsheet_token, "my_sheet_token");
169 assert_eq!(request.value_range.range, "Sheet1!A1:B2");
170 assert_eq!(request.value_range.values, test_values);
171 }
172
173 #[test]
174 fn test_append_data_request_default() {
175 let request = AppendDataRequest::default();
176
177 assert_eq!(request.spreadsheet_token, "");
178 assert_eq!(request.value_range.range, "");
179 assert_eq!(request.value_range.values, Value::Null);
180 assert_eq!(request.insert_data_option, "");
181 }
182
183 #[test]
184 fn test_append_data_request_builder_default() {
185 let builder = AppendDataRequestBuilder::default();
186 let request = builder.build();
187
188 assert_eq!(request.spreadsheet_token, "");
189 assert_eq!(request.value_range.range, "");
190 assert_eq!(request.value_range.values, Value::Null);
191 }
192
193 #[test]
194 fn test_append_data_request_serialization() {
195 let test_values = json!([["Header1", "Header2"], ["Value1", "Value2"]]);
196
197 let request = AppendDataRequest::builder()
198 .spreadsheet_token("token123")
199 .range("Sheet1!A:B")
200 .values(test_values)
201 .build();
202
203 let serialized = serde_json::to_string(&request);
205 assert!(serialized.is_ok());
206
207 let json_str = serialized.unwrap();
208 assert!(json_str.contains("insertDataOption"));
209 assert!(json_str.contains("valueRange"));
210 }
211
212 #[test]
213 fn test_append_data_request_debug() {
214 let request = AppendDataRequest::builder()
215 .spreadsheet_token("debug_token")
216 .build();
217
218 let debug_str = format!("{:?}", request);
219 assert!(debug_str.contains("AppendDataRequest"));
220 assert!(debug_str.contains("debug_token"));
221 }
222
223 #[test]
224 fn test_append_data_request_with_empty_strings() {
225 let request = AppendDataRequest::builder()
226 .spreadsheet_token("")
227 .range("")
228 .values(Value::Null)
229 .build();
230
231 assert_eq!(request.spreadsheet_token, "");
232 assert_eq!(request.value_range.range, "");
233 assert_eq!(request.value_range.values, Value::Null);
234 }
235
236 #[test]
237 fn test_append_data_request_with_special_characters() {
238 let request = AppendDataRequest::builder()
239 .spreadsheet_token("token_with_特殊字符_🎯")
240 .range("Sheet名称!A1:Z100")
241 .build();
242
243 assert_eq!(request.spreadsheet_token, "token_with_特殊字符_🎯");
244 assert_eq!(request.value_range.range, "Sheet名称!A1:Z100");
245 }
246
247 #[test]
248 fn test_append_data_request_with_unicode_values() {
249 let test_values = json!([
250 ["姓名", "年龄", "城市"],
251 ["张三", 25, "北京"],
252 ["李四", 30, "上海"],
253 ["王五", 35, "深圳"]
254 ]);
255
256 let request = AppendDataRequest::builder()
257 .values(test_values.clone())
258 .build();
259
260 assert_eq!(request.value_range.values, test_values);
261 }
262
263 #[test]
264 fn test_append_data_request_with_complex_json() {
265 let complex_values = json!([
266 [{"text": "Complex"}, {"formula": "=A1+B1"}, {"link": "https://example.com"}],
267 [123.45, true, null],
268 [{"nested": {"deep": "value"}}, [1, 2, 3], "simple_string"]
269 ]);
270
271 let request = AppendDataRequest::builder()
272 .values(complex_values.clone())
273 .build();
274
275 assert_eq!(request.value_range.values, complex_values);
276 }
277
278 #[test]
279 fn test_append_data_request_with_large_data() {
280 let large_values = json!((0..1000)
281 .map(|i| vec![
282 format!("Name_{}", i),
283 i.to_string(),
284 format!("Description for item {}", i)
285 ])
286 .collect::<Vec<_>>());
287
288 let request = AppendDataRequest::builder()
289 .spreadsheet_token("large_data_token")
290 .range("Sheet1!A:C")
291 .values(large_values.clone())
292 .build();
293
294 assert_eq!(request.value_range.values, large_values);
295 assert_eq!(request.spreadsheet_token, "large_data_token");
296 }
297
298 #[test]
299 fn test_append_data_request_with_different_range_formats() {
300 let ranges = vec![
301 "Sheet1!A1:B2",
302 "工作表1!C:D",
303 "'My Sheet'!E5:G10",
304 "Sheet2!A:A",
305 "Sheet3!1:3",
306 ];
307
308 for range in ranges {
309 let request = AppendDataRequest::builder().range(range).build();
310
311 assert_eq!(request.value_range.range, range);
312 }
313 }
314
315 #[test]
316 fn test_append_data_request_with_different_value_types() {
317 let different_types = vec![
318 json!("string"),
319 json!(42),
320 json!(3.14286),
321 json!(true),
322 json!(null),
323 json!([1, 2, 3]),
324 json!({"key": "value"}),
325 ];
326
327 for value in different_types {
328 let request = AppendDataRequest::builder().values(value.clone()).build();
329
330 assert_eq!(request.value_range.values, value);
331 }
332 }
333
334 #[test]
335 fn test_append_data_request_api_request_body_serialization() {
336 let test_values = json!([["A", "B"], ["1", "2"]]);
337
338 let request = AppendDataRequest::builder()
339 .spreadsheet_token("body_test_token")
340 .range("Sheet1!A:B")
341 .values(test_values)
342 .build();
343
344 assert!(!request.api_request.body.is_empty());
346
347 let body_str = String::from_utf8(request.api_request.body).unwrap();
349 let parsed: Value = serde_json::from_str(&body_str).unwrap();
350
351 assert!(parsed.get("valueRange").is_some());
352 assert!(parsed.get("insertDataOption").is_some());
353 }
354
355 #[test]
356 fn test_append_data_request_builder_multiple_calls() {
357 let mut builder = AppendDataRequest::builder();
358
359 builder = builder.spreadsheet_token("first_token");
361 builder = builder.spreadsheet_token("second_token");
362 builder = builder.range("first_range");
363 builder = builder.range("second_range");
364
365 let request = builder.build();
366
367 assert_eq!(request.spreadsheet_token, "second_token");
368 assert_eq!(request.value_range.range, "second_range");
369 }
370
371 #[test]
372 fn test_spreadsheet_sheet_service_creation() {
373 let service = create_test_service();
374
375 assert_eq!(service.config.app_id, "test_app_id");
377 }
378
379 #[test]
380 fn test_append_data_response_type_alias() {
381 let _response: AppendDataResponse = UpdateSheetDataResponse {
383 spreed_sheet_token: "test".to_string(),
384 table_range: "A1:B2".to_string(),
385 revision: 1,
386 updates: crate::service::cloud_docs::sheets::v2::data_operation::SheetDataUpdates {
387 spreed_sheet_token: "test".to_string(),
388 updated_range: "A1:B2".to_string(),
389 updated_rows: 2,
390 updated_columns: 2,
391 updated_cells: 4,
392 revision: Some(1),
393 },
394 };
395 }
396
397 #[test]
398 fn test_append_data_request_edge_cases() {
399 let long_token = "a".repeat(10000);
401 let request = AppendDataRequest::builder()
402 .spreadsheet_token(&long_token)
403 .build();
404 assert_eq!(request.spreadsheet_token, long_token);
405
406 let empty_array = json!([]);
408 let request = AppendDataRequest::builder()
409 .values(empty_array.clone())
410 .build();
411 assert_eq!(request.value_range.values, empty_array);
412
413 let nested_array = json!([[[["deeply", "nested"], ["values", "here"]]]]);
415 let request = AppendDataRequest::builder()
416 .values(nested_array.clone())
417 .build();
418 assert_eq!(request.value_range.values, nested_array);
419 }
420
421 #[test]
422 fn test_value_range_request_default() {
423 let value_range = ValueRangeRequest::default();
424 assert_eq!(value_range.range, "");
425 assert_eq!(value_range.values, Value::Null);
426 }
427
428 #[test]
429 fn test_value_range_request_serialization() {
430 let value_range = ValueRangeRequest {
431 range: "A1:B2".to_string(),
432 values: json!([["1", "2"]]),
433 };
434
435 let serialized = serde_json::to_string(&value_range);
436 assert!(serialized.is_ok());
437
438 let json_str = serialized.unwrap();
439 assert!(json_str.contains("range"));
440 assert!(json_str.contains("values"));
441 assert!(json_str.contains("A1:B2"));
442 }
443
444 #[test]
445 fn test_append_data_request_memory_efficiency() {
446 let requests: Vec<AppendDataRequest> = (0..100)
448 .map(|i| {
449 AppendDataRequest::builder()
450 .spreadsheet_token(format!("token_{}", i))
451 .range(format!("Sheet{}!A:B", i))
452 .values(json!([[i.to_string(), (i + 1).to_string()]]))
453 .build()
454 })
455 .collect();
456
457 assert_eq!(requests.len(), 100);
458
459 for (i, request) in requests.iter().enumerate() {
461 assert_eq!(request.spreadsheet_token, format!("token_{}", i));
462 assert_eq!(request.value_range.range, format!("Sheet{}!A:B", i));
463 }
464 }
465}