test(incremental): hidden members under every aggregation, evidence and the step 4 reasoning (improvise-u2le)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Claude (dbsp-backend)
2026-10-10 14:42:43 -07:00
committed by Edward Langley
parent a18a092186
commit c6fbce0ca1
5 changed files with 264 additions and 2 deletions
@@ -9,8 +9,8 @@ use improvise_core::model::cell::CellValue;
use improvise_core::view::View;
use improvise_incremental::{Edit, Incremental, differential_in};
use support::{
corpus, edits_for, grouped_model, hand_model, hidden_workbook, none_of, ratio_workbook,
wide_workbook,
corpus, edits_for, grouped_model, hand_model, hidden_counted_workbook, hidden_workbook,
none_of, ratio_workbook, wide_workbook,
};
fn run(model: &Model, views: &[View], none: &[String], edits: &[Edit]) -> Result<(), String> {
@@ -77,6 +77,27 @@ fn incremental_matches_eager_on_hidden_items_and_collapsed_groups() {
run(&wb.model, &views, &none, &edits).unwrap();
}
#[test]
fn incremental_matches_eager_on_a_collapsed_group_with_a_hidden_member_under_every_aggregation() {
let wb = hidden_counted_workbook();
let views: Vec<View> = wb.views.values().cloned().collect();
let none = none_of(&wb);
let mut edits = agg_edits("Revenue");
edits.push(Edit::SetCell(
support::key("Inland", "A", "Revenue"),
CellValue::Number(f64::NAN),
));
edits.extend(agg_edits("Revenue"));
run(&wb.model, &views, &none, &edits).unwrap();
}
#[test]
fn incremental_matches_eager_on_a_formula_read_under_every_aggregation() {
let model = hand_model();
let none = vec!["Region".to_string()];
run(&model, &[], &none, &agg_edits("Profit")).unwrap();
}
#[test]
fn incremental_matches_eager_on_a_group_read_without_a_view() {
let model = grouped_model();
@@ -181,3 +181,18 @@ fn occupancy_with_a_hidden_item_reads_the_groups_it_subtracts() {
"the line, less p3 under it"
);
}
#[test]
fn a_group_whose_cells_are_all_cleared_is_no_longer_read() {
let mut backend = Incremental::new(table(2, AggFunc::Count), vec![]);
let one = cell(1, 1, 1);
assert_eq!(backend.raw_fold(&one), Some(CellValue::Number(1.0)));
backend.apply(&Edit::ClearCell(cell(1, 1, 1)));
let before = backend.meter();
assert_eq!(backend.raw_fold(&one), None, "nothing is left under it");
assert_eq!(
since(before, backend.meter()).reads,
0,
"and no empty group stands in for it"
);
}
@@ -223,3 +223,13 @@ pub fn ratio_workbook() -> improvise_core::workbook::Workbook {
view.set_axis("Product", Axis::None);
wb
}
/// [`hidden_workbook`] drawn with the measure on the columns and Product folded: its cells
/// carry a measure, so the measure's aggregation reaches every row, total and collapsed group.
pub fn hidden_counted_workbook() -> improvise_core::workbook::Workbook {
let mut wb = hidden_workbook();
let view = wb.active_view_mut();
view.set_axis("Product", Axis::None);
view.set_axis("_Measure", Axis::Column);
wb
}