-
Notifications
You must be signed in to change notification settings - Fork 957
fix(sheets): report error for invalid --json-values instead of silent empty append #463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@googleworkspace/cli": patch | ||
| --- | ||
|
|
||
| Report validation error for invalid --json-values instead of silent empty append |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,7 +102,7 @@ TIPS: | |
| ) -> Pin<Box<dyn Future<Output = Result<bool, GwsError>> + Send + 'a>> { | ||
| Box::pin(async move { | ||
| if let Some(matches) = matches.subcommand_matches("+append") { | ||
| let config = parse_append_args(matches); | ||
| let config = parse_append_args(matches)?; | ||
| let (params_str, body_str, scopes) = build_append_request(&config, doc)?; | ||
|
|
||
| let scope_strs: Vec<&str> = scopes.iter().map(|s| s.as_str()).collect(); | ||
|
|
@@ -257,6 +257,7 @@ fn build_read_request( | |
| /// Configuration for appending values to a spreadsheet. | ||
| /// | ||
| /// Holds the parsed arguments for the `+append` subcommand. | ||
| #[derive(Debug)] | ||
| pub struct AppendConfig { | ||
| /// The ID of the spreadsheet to append to. | ||
| pub spreadsheet_id: String, | ||
|
|
@@ -267,7 +268,8 @@ pub struct AppendConfig { | |
| /// Parses arguments for the `+append` command. | ||
| /// | ||
| /// Supports both `--values` (single row) and `--json-values` (single or multi-row). | ||
| pub fn parse_append_args(matches: &ArgMatches) -> AppendConfig { | ||
| /// Returns a validation error if `--json-values` contains invalid JSON. | ||
| pub fn parse_append_args(matches: &ArgMatches) -> Result<AppendConfig, GwsError> { | ||
| let values = if let Some(json_str) = matches.get_one::<String>("json-values") { | ||
| // Try parsing as array-of-arrays (multi-row) first | ||
| if let Ok(parsed) = serde_json::from_str::<Vec<Vec<String>>>(json_str) { | ||
|
|
@@ -276,21 +278,20 @@ pub fn parse_append_args(matches: &ArgMatches) -> AppendConfig { | |
| // Single flat array — treat as one row | ||
| vec![parsed] | ||
| } else { | ||
| eprintln!( | ||
| "Warning: --json-values is not valid JSON; expected an array or array-of-arrays" | ||
| ); | ||
| Vec::new() | ||
| return Err(GwsError::Validation(format!( | ||
| "--json-values is not valid JSON: expected an array like '[\"a\",\"b\"]' or array-of-arrays like '[[\"a\",\"b\"],[\"c\",\"d\"]]'." | ||
| ))); | ||
| } | ||
|
Comment on lines
280
to
284
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current error message for invalid } else {
// Check if it's a JSON syntax error or just a type mismatch.
let err_msg = if let Err(e) = serde_json::from_str::<serde_json::Value>(json_str) {
format!("--json-values is not valid JSON: {e}")
} else {
"--json-values has an incorrect structure".to_string()
};
return Err(GwsError::Validation(format!(
"{err_msg}. Expected an array like '[\"a\",\"b\"]' or array-of-arrays like '[[\"a\",\"b\"],[\"c\",\"d\"]]'."
)));
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're right, updated the error to first check if it's valid JSON at all vs valid JSON but wrong structure, so the message is more accurate |
||
| } else if let Some(values_str) = matches.get_one::<String>("values") { | ||
| vec![values_str.split(',').map(|s| s.to_string()).collect()] | ||
| } else { | ||
| Vec::new() | ||
| }; | ||
anshul-garg27 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| AppendConfig { | ||
| Ok(AppendConfig { | ||
| spreadsheet_id: matches.get_one::<String>("spreadsheet").unwrap().clone(), | ||
| values, | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| /// Configuration for reading values from a spreadsheet. | ||
|
|
@@ -395,7 +396,7 @@ mod tests { | |
| #[test] | ||
| fn test_parse_append_args_values() { | ||
| let matches = make_matches_append(&["test", "--spreadsheet", "123", "--values", "a,b,c"]); | ||
| let config = parse_append_args(&matches); | ||
| let config = parse_append_args(&matches).unwrap(); | ||
| assert_eq!(config.spreadsheet_id, "123"); | ||
| assert_eq!(config.values, vec![vec!["a", "b", "c"]]); | ||
| } | ||
|
|
@@ -409,7 +410,7 @@ mod tests { | |
| "--json-values", | ||
| r#"["a","b","c"]"#, | ||
| ]); | ||
| let config = parse_append_args(&matches); | ||
| let config = parse_append_args(&matches).unwrap(); | ||
| assert_eq!(config.values, vec![vec!["a", "b", "c"]]); | ||
| } | ||
|
|
||
|
|
@@ -422,7 +423,7 @@ mod tests { | |
| "--json-values", | ||
| r#"[["Alice","100"],["Bob","200"]]"#, | ||
| ]); | ||
| let config = parse_append_args(&matches); | ||
| let config = parse_append_args(&matches).unwrap(); | ||
| assert_eq!( | ||
| config.values, | ||
| vec![vec!["Alice", "100"], vec!["Bob", "200"]] | ||
|
|
@@ -447,6 +448,36 @@ mod tests { | |
| assert_eq!(values[1], json!(["Bob", "200"])); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_parse_append_args_json_valid() { | ||
| let matches = make_matches_append(&[ | ||
| "test", | ||
| "--spreadsheet", | ||
| "123", | ||
| "--json-values", | ||
| r#"["a","b","c"]"#, | ||
| ]); | ||
| let config = parse_append_args(&matches).unwrap(); | ||
| assert_eq!(config.values, vec![vec!["a", "b", "c"]]); | ||
| } | ||
|
Comment on lines
+451
to
+462
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, removed the duplicate test |
||
|
|
||
| #[test] | ||
| fn test_parse_append_args_json_invalid_returns_error() { | ||
| let matches = make_matches_append(&[ | ||
| "test", | ||
| "--spreadsheet", | ||
| "123", | ||
| "--json-values", | ||
| "not valid json", | ||
| ]); | ||
| let err = parse_append_args(&matches).unwrap_err(); | ||
| let msg = err.to_string(); | ||
| assert!( | ||
| msg.contains("--json-values is not valid JSON"), | ||
| "expected JSON error message, got: {msg}" | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_parse_read_args() { | ||
| let matches = make_matches_read(&["test", "--spreadsheet", "123", "--range", "A1:B2"]); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description mentions including error details (
<details>) for invalid JSON, but the current implementation provides a generic error message. To improve the user experience and align with the PR's goal, consider including the specific parsing error fromserde_json. This will help users debug their input more effectively.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, added the serde_json error details to the message so users can see exactly what went wrong