diff --git a/crates/engine/src/cmd/data.rs b/crates/engine/src/cmd/data.rs index a33c39166..102115f00 100644 --- a/crates/engine/src/cmd/data.rs +++ b/crates/engine/src/cmd/data.rs @@ -955,6 +955,9 @@ fn validation(s: &mut Session, p: &Json) -> Result { // An unknown type used to give an "any value" rule, saved as `type="none"`: no validation. other => return Err(bad("data.validation", format!("unknown type `{other}` (any, whole, decimal, list, date, time, textLength, custom)"))), }; + if kind == ValidationKind::List && str_param(p, "formula1").is_none_or(|f| f.trim().trim_start_matches('=').is_empty()) { + return Err(bad("data.validation", "a list validation needs `formula1`")); + } const OPERATORS: [&str; 12] = [ "between", "notBetween", @@ -1402,6 +1405,17 @@ mod tests { } } + #[test] + fn list_validation_without_formula1_is_an_error() { + let mut s = Session::new(); + s.new_workbook(); + assert!(s.execute("data.validation", json!({"range": "A1:A3", "type": "list", "source": "\"a,b,c\""})).is_err()); + assert!(s.execute("data.validation", json!({"range": "A1:A3", "type": "list"})).is_err()); + assert!(s.doc().unwrap().wb.active().unwrap().validations.is_empty()); + s.execute("data.validation", json!({"range": "A1:A3", "type": "list", "formula1": "\"a,b,c\""})).unwrap(); + assert_eq!(s.execute("data.validate", json!({"cell": "A1", "input": "a"})).unwrap()["ok"], json!(true)); + } + #[test] fn partial_validation_edits_keep_the_rest_of_the_old_rule() { let mut s = Session::new();