improvise-umi4: WIP failing tests — an untouched edit must store the identical value

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Edward Langley
2026-09-22 21:43:38 -07:00
parent 1c184a5cc2
commit c246dc1df6
2 changed files with 186 additions and 0 deletions
@@ -473,6 +473,123 @@ mod tests {
"bulk entry lands at the start of the new row"
);
}
/// Values whose `Display` (four decimals) and value disagree, plus text.
fn values_display_rounds() -> Vec<crate::model::cell::CellValue> {
use crate::model::cell::CellValue::{Number, Text};
vec![
Number(1.23456789),
Number(0.1 + 0.2),
Number(98765.4321987),
Number(123456789012345.67),
Number(-0.00001234),
Text("0.1 + 0.2".into()),
]
}
/// Two regions, two measures, with `value` at (West, Revenue): never index 0.
fn grid_holding(value: crate::model::cell::CellValue, records: bool) -> crate::ui::app::App {
use crate::model::cell::{CellKey, CellValue};
use crate::ui::app::App;
use crate::view::Axis;
let mut wb = Workbook::new("Seed");
wb.add_category("Region").unwrap();
for region in ["North", "West"] {
wb.add_item("Region", region).unwrap();
}
for measure in ["Cost", "Revenue"] {
wb.add_item("_Measure", measure).unwrap();
}
let key = |r: &str, m: &str| {
CellKey::new(vec![
("Region".into(), r.into()),
("_Measure".into(), m.into()),
])
};
wb.model.set_cell(key("North", "Cost"), CellValue::Number(1.0));
wb.model.set_cell(key("North", "Revenue"), CellValue::Number(2.0));
wb.model.set_cell(key("West", "Cost"), CellValue::Number(3.0));
wb.model.set_cell(key("West", "Revenue"), value);
{
let v = wb.active_view_mut();
match records {
true => {
v.set_axis("_Index", Axis::Row);
v.set_axis("_Dim", Axis::Column);
v.set_axis("Region", Axis::None);
v.set_axis("_Measure", Axis::None);
}
false => {
v.set_axis("Region", Axis::Row);
v.set_axis("_Measure", Axis::Column);
}
}
}
let mut app = App::new(wb, None);
app.rebuild_layout();
assert_eq!(app.layout.is_records_mode(), records, "wrong fixture mode");
app
}
/// Open the editor on (West, Revenue) and commit it untouched; the stored value.
fn no_op_commit(records: bool, value: crate::model::cell::CellValue) {
use crate::model::cell::CellKey;
use improvise_protocol::key::KeyCode;
let mut app = grid_holding(value.clone(), records);
let target = CellKey::new(vec![
("Region".into(), "West".into()),
("_Measure".into(), "Revenue".into()),
]);
let at = match records {
true => (1, 3),
false => (1, 1),
};
app.cursor_mut().selected = at;
if records {
app.view_state.mode = AppMode::RecordsNormal;
assert_eq!(
app.layout.record_col(at.1),
Some(&RecordCol::Measure("Revenue".into())),
"the cursor is not on the Revenue column"
);
}
assert_eq!(
app.model_state.workbook.model.get_cell(&target),
Some(&value),
"the fixture does not hold the value under test"
);
press(&mut app, KeyCode::Char('i'));
assert!(app.view_state.mode.is_editing(), "`i` did not open an editor");
press(&mut app, KeyCode::Enter);
let stored = app.model_state.workbook.model.get_cell(&target).cloned();
let same = match (&stored, &value) {
(Some(CellValue::Number(a)), CellValue::Number(b)) => a.to_bits() == b.to_bits(),
(stored, value) => stored.as_ref() == Some(value),
};
assert!(
same,
"{} mode: i then Enter on {value:?} stored {stored:?}",
if records { "records" } else { "pivot" }
);
}
/// BUG (improvise-umi4) — see `context/test-evidence/command.md`.
#[test]
fn an_untouched_pivot_edit_stores_the_identical_value() {
for value in values_display_rounds() {
no_op_commit(false, value);
}
}
/// BUG (improvise-umi4) — see `context/test-evidence/command.md`.
#[test]
fn an_untouched_records_edit_stores_the_identical_value() {
for value in values_display_rounds() {
no_op_commit(true, value);
}
}
}
// ── Commit commands (mode-specific buffer consumers) ────────────────────────
@@ -1755,3 +1755,72 @@ fn yy_over_an_aggregate_copies_the_sum_the_host_copies() {
"client and host yanked different values over an aggregate"
);
}
/// Two regions by two measures, `value` at (South, Revenue): row 1, column 1,
/// so "the cell under the cursor" is not "the first cell".
fn precise_host(value: improvise_protocol::CellValue) -> App {
let mut wb = Workbook::new("Test");
wb.add_category("Region").unwrap();
wb.add_item("Region", "North").unwrap();
wb.add_item("Region", "South").unwrap();
wb.add_item("_Measure", "Cost").unwrap();
wb.add_item("_Measure", "Revenue").unwrap();
wb.active_view_mut().set_axis("Region", Axis::Row);
wb.active_view_mut().set_axis("_Measure", Axis::Column);
for (region, measure, v) in [
("North", "Cost", improvise_protocol::CellValue::Number(1.0)),
("North", "Revenue", improvise_protocol::CellValue::Number(2.0)),
("South", "Cost", improvise_protocol::CellValue::Number(3.0)),
("South", "Revenue", value),
] {
wb.model.set_cell(region_measure(region, measure), v);
}
let mut app = App::new(wb, None);
app.term_height = 2 + 8;
app.rebuild_layout();
app.cursor_mut().selected = (1, 1);
app
}
/// BUG (improvise-umi4) — see `context/test-evidence/clients.md`.
#[test]
fn an_untouched_browser_edit_stores_the_identical_value() {
use improvise_protocol::CellValue::{Number, Text};
let window = (2, 2);
for value in [
Number(1.23456789),
Number(0.1 + 0.2),
Number(98765.4321987),
Number(123456789012345.67),
Number(-0.00001234),
Text("0.1 + 0.2".into()),
] {
let mut host = precise_host(value.clone());
let mut client = client_ready_to_edit(&host, window);
for key in ["i", "Enter"] {
let event = BrowserKey::new(key).to_key_event().unwrap();
let KeyOutcome::Local(cmds) = resolve(&client, event) else {
panic!("{key}: the client must answer this key locally");
};
for cmd in &cmds {
client.fold(cmd);
}
apply_on(&mut host, &cmds);
}
assert!(
!client.view.mode.is_editing(),
"Enter did not commit, so nothing was written and this proves nothing"
);
let stored = host
.model_state
.workbook
.model
.get_cell(&region_measure("South", "Revenue"))
.cloned();
let same = match (&stored, &value) {
(Some(Number(a)), Number(b)) => a.to_bits() == b.to_bits(),
(stored, value) => stored.as_ref() == Some(value),
};
assert!(same, "i then Enter on {value:?} stored {stored:?}");
}
}