1use 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 service::cloud_docs::sheets::v2::{
10 data_operation::{UpdateSheetDataResponse, ValueRangeRequest},
11 SpreadsheetSheetService,
12 },
13};
14
15#[derive(Serialize, Debug, Default)]
17pub struct PrependDataRequest {
18 #[serde(skip)]
19 api_request: ApiRequest,
20 #[serde(skip)]
21 spreadsheet_token: String,
22 #[serde(rename = "valueRange")]
24 value_range: ValueRangeRequest,
25}
26
27impl PrependDataRequest {
28 pub fn builder() -> PrependDataRequestBuilder {
29 PrependDataRequestBuilder::default()
30 }
31}
32
33#[derive(Default)]
34pub struct PrependDataRequestBuilder {
35 request: PrependDataRequest,
36}
37
38impl PrependDataRequestBuilder {
39 pub fn spreadsheet_token(mut self, spreadsheet_token: impl ToString) -> Self {
40 self.request.spreadsheet_token = spreadsheet_token.to_string();
41 self
42 }
43
44 pub fn range(mut self, range: impl ToString) -> Self {
47 self.request.value_range.range = range.to_string();
48 self
49 }
50
51 pub fn values(mut self, values: Value) -> Self {
53 self.request.value_range.values = values;
54 self
55 }
56
57 pub fn build(mut self) -> PrependDataRequest {
58 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
59 self.request
60 }
61}
62
63pub type PrependDataResponse = UpdateSheetDataResponse;
65
66impl SpreadsheetSheetService {
67 pub async fn prepend_data(
69 &self,
70 request: PrependDataRequest,
71 option: Option<RequestOption>,
72 ) -> SDKResult<BaseResponse<PrependDataResponse>> {
73 let mut api_req = request.api_request;
74 api_req.api_path =
75 SHEETS_V2_SPREADSHEET_VALUES_PREPEND.replace("{}", &request.spreadsheet_token);
76 api_req.http_method = reqwest::Method::POST;
77 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::App];
78
79 let api_resp =
80 crate::core::http::Transport::request(api_req, &self.config_arc, option).await?;
81
82 Ok(api_resp)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::core::{config::Config, constants::AppType};
90 use serde_json::{json, Value};
91
92 fn create_test_config() -> Config {
93 Config::builder()
94 .app_id("test_app_id")
95 .app_secret("test_app_secret")
96 .build()
97 }
98
99 fn create_test_service() -> SpreadsheetSheetService {
100 SpreadsheetSheetService::new(create_test_config())
101 }
102
103 #[test]
104 fn test_prepend_data_request_builder_creation() {
105 let builder = PrependDataRequest::builder();
106 let request = builder.build();
107
108 assert_eq!(request.spreadsheet_token, "");
109 assert_eq!(request.value_range.range, "");
110 assert_eq!(request.value_range.values, Value::Null);
111 }
112
113 #[test]
114 fn test_prepend_data_request_builder_with_spreadsheet_token() {
115 let request = PrependDataRequest::builder()
116 .spreadsheet_token("prepend_token_123")
117 .build();
118
119 assert_eq!(request.spreadsheet_token, "prepend_token_123");
120 }
121
122 #[test]
123 fn test_prepend_data_request_builder_with_range() {
124 let request = PrependDataRequest::builder().range("Sheet1!A1:D5").build();
125
126 assert_eq!(request.value_range.range, "Sheet1!A1:D5");
127 }
128
129 #[test]
130 fn test_prepend_data_request_builder_with_values() {
131 let test_values = json!([
132 ["Product", "Price", "Stock", "Category"],
133 ["Laptop", 999.99, 50, "Electronics"],
134 ["Mouse", 29.99, 200, "Accessories"]
135 ]);
136
137 let request = PrependDataRequest::builder()
138 .values(test_values.clone())
139 .build();
140
141 assert_eq!(request.value_range.values, test_values);
142 }
143
144 #[test]
145 fn test_prepend_data_request_builder_chaining() {
146 let test_values = json!([["Header1", "Header2"], ["Data1", "Data2"]]);
147
148 let request = PrependDataRequest::builder()
149 .spreadsheet_token("chain_token")
150 .range("Sheet2!B2:C3")
151 .values(test_values.clone())
152 .build();
153
154 assert_eq!(request.spreadsheet_token, "chain_token");
155 assert_eq!(request.value_range.range, "Sheet2!B2:C3");
156 assert_eq!(request.value_range.values, test_values);
157 }
158
159 #[test]
160 fn test_prepend_data_request_default() {
161 let request = PrependDataRequest::default();
162
163 assert_eq!(request.spreadsheet_token, "");
164 assert_eq!(request.value_range.range, "");
165 assert_eq!(request.value_range.values, Value::Null);
166 }
167
168 #[test]
169 fn test_prepend_data_request_builder_default() {
170 let builder = PrependDataRequestBuilder::default();
171 let request = builder.build();
172
173 assert_eq!(request.spreadsheet_token, "");
174 assert_eq!(request.value_range.range, "");
175 assert_eq!(request.value_range.values, Value::Null);
176 }
177
178 #[test]
179 fn test_prepend_data_request_serialization() {
180 let test_values = json!([["Col1", "Col2"], ["Val1", "Val2"]]);
181
182 let request = PrependDataRequest::builder()
183 .spreadsheet_token("serialize_token")
184 .range("Sheet1!A:B")
185 .values(test_values)
186 .build();
187
188 let serialized = serde_json::to_string(&request);
189 assert!(serialized.is_ok());
190
191 let json_str = serialized.unwrap();
192 assert!(json_str.contains("valueRange"));
193 assert!(!json_str.contains("spreadsheet_token")); }
195
196 #[test]
197 fn test_prepend_data_request_debug() {
198 let request = PrependDataRequest::builder()
199 .spreadsheet_token("debug_prepend_token")
200 .build();
201
202 let debug_str = format!("{:?}", request);
203 assert!(debug_str.contains("PrependDataRequest"));
204 assert!(debug_str.contains("debug_prepend_token"));
205 }
206
207 #[test]
208 fn test_prepend_data_request_with_empty_values() {
209 let request = PrependDataRequest::builder()
210 .spreadsheet_token("")
211 .range("")
212 .values(Value::Null)
213 .build();
214
215 assert_eq!(request.spreadsheet_token, "");
216 assert_eq!(request.value_range.range, "");
217 assert_eq!(request.value_range.values, Value::Null);
218 }
219
220 #[test]
221 fn test_prepend_data_request_with_special_characters() {
222 let request = PrependDataRequest::builder()
223 .spreadsheet_token("token_特殊字符_prepend_🎉")
224 .range("工作表!A1:Z999")
225 .build();
226
227 assert_eq!(request.spreadsheet_token, "token_特殊字符_prepend_🎉");
228 assert_eq!(request.value_range.range, "工作表!A1:Z999");
229 }
230
231 #[test]
232 fn test_prepend_data_request_with_unicode_data() {
233 let unicode_values = json!([
234 ["名称", "描述", "状态"],
235 ["测试项目", "这是一个测试项目", "活跃"],
236 ["实验数据", "包含中文和English混合", "完成"],
237 ["🚀项目", "包含emoji和特殊符号", "进行中"]
238 ]);
239
240 let request = PrependDataRequest::builder()
241 .values(unicode_values.clone())
242 .build();
243
244 assert_eq!(request.value_range.values, unicode_values);
245 }
246
247 #[test]
248 fn test_prepend_data_request_with_complex_json_structures() {
249 let complex_data = json!([
250 [
251 {"type": "formula", "value": "=SUM(A1:A10)"},
252 {"type": "link", "url": "https://example.com", "text": "Link"},
253 {"type": "mention", "user_id": "user123"}
254 ],
255 [
256 {"number": 42.5, "currency": "USD"},
257 {"date": "2023-12-25", "format": "yyyy-mm-dd"},
258 {"boolean": true, "confidence": 0.95}
259 ]
260 ]);
261
262 let request = PrependDataRequest::builder()
263 .values(complex_data.clone())
264 .build();
265
266 assert_eq!(request.value_range.values, complex_data);
267 }
268
269 #[test]
270 fn test_prepend_data_request_with_different_range_formats() {
271 let range_formats = vec![
272 "Sheet1!A1:B2",
273 "工作表名称!C:D",
274 "'Sheet with spaces'!E5:F10",
275 "Sheet2!A:A",
276 "数据表!1:5",
277 "Sheet!$A$1:$B$10",
278 ];
279
280 for range_format in range_formats {
281 let request = PrependDataRequest::builder().range(range_format).build();
282
283 assert_eq!(request.value_range.range, range_format);
284 }
285 }
286
287 #[test]
288 fn test_prepend_data_request_with_various_data_types() {
289 let mixed_types = vec![
290 json!("string_value"),
291 json!(123),
292 json!(45.67),
293 json!(true),
294 json!(false),
295 json!(null),
296 json!([1, 2, 3]),
297 json!({"key": "value", "nested": {"inner": "data"}}),
298 ];
299
300 for data_type in mixed_types {
301 let request = PrependDataRequest::builder()
302 .values(data_type.clone())
303 .build();
304
305 assert_eq!(request.value_range.values, data_type);
306 }
307 }
308
309 #[test]
310 fn test_prepend_data_request_api_body_serialization() {
311 let test_data = json!([["X", "Y"], ["1", "2"]]);
312
313 let request = PrependDataRequest::builder()
314 .spreadsheet_token("body_test")
315 .range("Sheet1!A:B")
316 .values(test_data)
317 .build();
318
319 assert!(!request.api_request.body.is_empty());
321
322 let body_str = String::from_utf8(request.api_request.body).unwrap();
324 let parsed: Value = serde_json::from_str(&body_str).unwrap();
325
326 assert!(parsed.get("valueRange").is_some());
327 assert!(parsed.get("spreadsheet_token").is_none()); }
329
330 #[test]
331 fn test_prepend_data_request_builder_overwrite_behavior() {
332 let mut builder = PrependDataRequest::builder();
333
334 builder = builder.spreadsheet_token("first_token");
336 builder = builder.spreadsheet_token("final_token");
337 builder = builder.range("first_range");
338 builder = builder.range("final_range");
339
340 let request = builder.build();
341
342 assert_eq!(request.spreadsheet_token, "final_token");
343 assert_eq!(request.value_range.range, "final_range");
344 }
345
346 #[test]
347 fn test_prepend_data_request_with_large_dataset() {
348 let large_data = json!((0..500)
349 .map(|i| vec![
350 format!("Item_{}", i),
351 format!("Category_{}", i % 10),
352 format!("Description for item number {}", i),
353 (i * 2).to_string(),
354 ])
355 .collect::<Vec<_>>());
356
357 let request = PrependDataRequest::builder()
358 .spreadsheet_token("large_dataset_token")
359 .range("BigSheet!A:D")
360 .values(large_data.clone())
361 .build();
362
363 assert_eq!(request.value_range.values, large_data);
364 assert_eq!(request.spreadsheet_token, "large_dataset_token");
365 }
366
367 #[test]
368 fn test_prepend_data_request_edge_cases() {
369 let very_long_token = "x".repeat(5000);
371 let request = PrependDataRequest::builder()
372 .spreadsheet_token(&very_long_token)
373 .build();
374 assert_eq!(request.spreadsheet_token, very_long_token);
375
376 let empty_array = json!([]);
378 let request = PrependDataRequest::builder()
379 .values(empty_array.clone())
380 .build();
381 assert_eq!(request.value_range.values, empty_array);
382
383 let nested_data = json!([[[[[["deep", "nesting"], ["test", "data"]]]]]]);
385 let request = PrependDataRequest::builder()
386 .values(nested_data.clone())
387 .build();
388 assert_eq!(request.value_range.values, nested_data);
389 }
390
391 #[test]
392 fn test_spreadsheet_sheet_service_creation() {
393 let service = create_test_service();
394 assert_eq!(service.config.app_id, "test_app_id");
395 assert_eq!(service.config.app_type, AppType::SelfBuild);
396 }
397
398 #[test]
399 fn test_prepend_data_response_type_alias() {
400 let _response: PrependDataResponse = UpdateSheetDataResponse {
402 spreed_sheet_token: "prepend_test".to_string(),
403 table_range: "A1:B5".to_string(),
404 revision: 2,
405 updates: crate::service::cloud_docs::sheets::v2::data_operation::SheetDataUpdates {
406 spreed_sheet_token: "prepend_test".to_string(),
407 updated_range: "A1:B5".to_string(),
408 updated_rows: 5,
409 updated_columns: 2,
410 updated_cells: 10,
411 revision: Some(2),
412 },
413 };
414 }
415
416 #[test]
417 fn test_prepend_data_request_memory_efficiency() {
418 let requests: Vec<PrependDataRequest> = (0..50)
420 .map(|i| {
421 PrependDataRequest::builder()
422 .spreadsheet_token(format!("efficient_token_{}", i))
423 .range(format!("Sheet{}!A:C", i + 1))
424 .values(json!([[
425 format!("Row{}", i),
426 i.to_string(),
427 format!("Data{}", i)
428 ]]))
429 .build()
430 })
431 .collect();
432
433 assert_eq!(requests.len(), 50);
434
435 for (i, request) in requests.iter().enumerate() {
437 assert_eq!(request.spreadsheet_token, format!("efficient_token_{}", i));
438 assert_eq!(request.value_range.range, format!("Sheet{}!A:C", i + 1));
439 }
440 }
441
442 #[test]
443 fn test_value_range_request_within_prepend_context() {
444 let value_range = ValueRangeRequest {
445 range: "PrependTest!A1:B2".to_string(),
446 values: json!([["Prepend1", "Prepend2"]]),
447 };
448
449 let request = PrependDataRequest {
450 api_request: ApiRequest::default(),
451 spreadsheet_token: "vr_test".to_string(),
452 value_range,
453 };
454
455 assert_eq!(request.value_range.range, "PrependTest!A1:B2");
456 assert_eq!(
457 request.value_range.values,
458 json!([["Prepend1", "Prepend2"]])
459 );
460 }
461
462 #[test]
463 fn test_prepend_data_request_json_serialization_completeness() {
464 let comprehensive_data = json!([
465 ["Text", "Number", "Boolean", "Null", "Array", "Object"],
466 ["Sample", 42, true, null, [1, 2, 3], {"nested": "value"}],
467 ["Unicode: 中文", 3.14286, false, null, [], {}]
468 ]);
469
470 let request = PrependDataRequest::builder()
471 .spreadsheet_token("comprehensive_test")
472 .range("Complete!A1:F3")
473 .values(comprehensive_data.clone())
474 .build();
475
476 let serialized = serde_json::to_string(&request).unwrap();
477 let parsed: Value = serde_json::from_str(&serialized).unwrap();
478
479 assert_eq!(parsed["valueRange"]["values"], comprehensive_data);
480 assert_eq!(parsed["valueRange"]["range"], "Complete!A1:F3");
481 }
482}