diff --git a/crates/engine/src/cmd/pivot.rs b/crates/engine/src/cmd/pivot.rs index 8a441fa1b..06050f7e8 100644 --- a/crates/engine/src/cmd/pivot.rs +++ b/crates/engine/src/cmd/pivot.rs @@ -675,7 +675,13 @@ fn insert_pivot(s: &mut Session, p: &Json) -> Result { Json::String(n) => add_to_area("insert.pivotTable", pt, &src, n, area, None, None, None)?, Json::Object(_) => { let n = str_param(f, "field").ok_or_else(|| bad("insert.pivotTable", "a field object needs `field`"))?; - add_to_area("insert.pivotTable", pt, &src, n, area, func_param(str_param(f, "func")), str_param(f, "name"), None)?; + let func = match str_param(f, "func") { + Some(fname) => { + Some(func_param(Some(fname)).ok_or_else(|| bad("insert.pivotTable", format!("unknown function `{fname}`")))?) + } + None => None, + }; + add_to_area("insert.pivotTable", pt, &src, n, area, func, str_param(f, "name"), None)?; let by = group_param(str_param(f, "group")); if let Some(by) = by.filter(|b| *b != PivotDateGroup::None) && matches!(area, "rows" | "columns") diff --git a/crates/engine/tests/pivot_unknown_func.rs b/crates/engine/tests/pivot_unknown_func.rs new file mode 100644 index 000000000..f4d2427f0 --- /dev/null +++ b/crates/engine/tests/pivot_unknown_func.rs @@ -0,0 +1,33 @@ +use gridcraft_engine::Session; +use serde_json::json; + +fn session() -> Session { + let mut s = Session::new(); + s.new_workbook(); + s.execute("range.setValues", json!({"range":"A1", "values":[["Region", "Sales"], ["East", "10"], ["East", "2"], ["West", "4"]]})).unwrap(); + s +} + +#[test] +fn insert_pivot_table_rejects_unknown_func() { + for func in ["stdev", "sumx"] { + let mut s = session(); + let r = s.execute( + "insert.pivotTable", + json!({"source":"Sheet1!A1:B4", "destination":"Sheet1!F1", "rows":["Region"], "values":[{"field":"Sales", "func":func}]}), + ); + assert!(r.is_err(), "unknown func `{func}` accepted silently"); + assert!(s.doc().unwrap().wb.active().unwrap().pivots.is_empty()); + } +} + +#[test] +fn insert_pivot_table_accepts_known_func() { + let mut s = session(); + s.execute( + "insert.pivotTable", + json!({"source":"Sheet1!A1:B4", "destination":"Sheet1!F1", "rows":["Region"], "values":[{"field":"Sales", "func":"stddev"}]}), + ) + .unwrap(); + assert_eq!(s.doc().unwrap().wb.active().unwrap().pivots.len(), 1); +}