y1av: seat the at-cursor tests off index 0

delete-formula-at-cursor, switch-view-at-cursor and delete-view-at-cursor
were asserted with the cursor at 0 of a one-element list, where the item
under the cursor and the first item are one item. A DeleteFormulaAtCursor
hard-wired to index 0 passed the whole workspace. Now each cursor sits at
index 1 of a longer list; the index-0 rivals fail.

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:28:58 -07:00
parent fbe7459cc6
commit 4277cf6f84
2 changed files with 72 additions and 19 deletions
+25 -4
View File
@@ -4721,17 +4721,38 @@ are now named, so moving the right cursor on the wrong panel fails.
### delete_formula_at_cursor_with_formulas
Asserts the `RemoveFormula` names `Profit` in `Type` — the formula the cursor is
on — rather than merely that a formula was removed.
Asserts the `RemoveFormula` names the formula the cursor is on, rather than merely
that a formula was removed. PR #148 named the field, but its fixture was **one**
formula with the cursor at **0**, where "the formula under the cursor" and "the
first formula" are the same formula (improvise-y1av). The rival it could not see —
`DeleteFormulaAtCursor` reading index `0` instead of `ctx.formula_cursor` — passed
the **whole workspace**, so `d` in the formula panel deleting the wrong formula had
no guard anywhere. Now two formulas, cursor at **1**: it must remove `Tax` and must
not name `Profit`. Rival `let cursor = 0usize.min(..)` injected, full suite run:
this is the only test that fails.
### switch_view_at_cursor_with_valid_cursor
Names `Default`, the view under the cursor.
Names the view under the cursor. Same fixture defect as above (improvise-y1av):
`two_cat_model` has one view, so the cursor at 0 named `Default` whether or not
the command read it. Now `Default, Other` with the cursor at **1**, asserting
`Other`. Rival `get(cursor).and(first())` — in bounds only, so the out-of-bounds
arm is unchanged and `switch_view_at_cursor_out_of_bounds_returns_empty` cannot be
what catches it — injected and run: fails here, in
`delete_view_at_cursor_deletes_the_view_under_a_nonzero_cursor`, and in the two
`wasm-client/tests/lockstep.rs` tests that were previously the only guard.
### delete_view_at_cursor_deletes_the_view_under_a_nonzero_cursor
improvise-y1av. `Default, Other, Third` with the cursor at **1**: deletes `Other`
and steps the panel cursor back to 0. The same rival as above fails it.
### delete_view_at_cursor_zero_does_not_adjust_cursor
Names `Default` too. Its existing negative half — no `SetPanelCursor` at
position 0 — is unchanged.
position 0 — is unchanged. Position 0 is this test's subject, so it cannot
separate "the view under the cursor" from "the first view" and does not try to;
the test above does.
### commit_category_add_with_name_produces_add_effect
@@ -395,39 +395,50 @@ mod tests {
assert!(effects.is_empty());
}
/// Evidence: `context/test-evidence/command.md`.
#[test]
fn delete_formula_at_cursor_with_formulas() {
let mut m = two_cat_model();
m.model.add_formula(crate::formula::ast::Formula {
raw: "Profit = Revenue - Cost".to_string(),
target: "Profit".to_string(),
target_category: "Type".to_string(),
expr: crate::formula::ast::Expr::Number(0.0),
filter: None,
format: None,
});
for (target, raw) in [("Profit", "Profit = 1"), ("Tax", "Tax = 2")] {
m.model.add_formula(crate::formula::ast::Formula {
raw: raw.to_string(),
target: target.to_string(),
target_category: "Type".to_string(),
expr: crate::formula::ast::Expr::Number(0.0),
filter: None,
format: None,
});
}
let layout = make_layout(&m);
let reg = make_registry();
let ctx = make_ctx(&m, &layout, &reg);
let mut ctx = make_ctx(&m, &layout, &reg);
ctx.formula_cursor = 1;
let effects = DeleteFormulaAtCursor.execute(&ctx);
let dbg = effects_debug(&effects);
assert!(
dbg.contains("RemoveFormula { target: \"Profit\", target_category: \"Type\" }"),
"must remove the formula AT THE CURSOR, got: {dbg}"
dbg.contains("RemoveFormula { target: \"Tax\", target_category: \"Type\" }"),
"must remove the formula AT THE CURSOR (Tax, index 1), got: {dbg}"
);
assert!(
!dbg.contains("\"Profit\""),
"removed the first formula, not the one under the cursor: {dbg}"
);
}
/// Evidence: `context/test-evidence/command.md`.
#[test]
fn switch_view_at_cursor_with_valid_cursor() {
let m = two_cat_model();
let mut m = two_cat_model();
m.create_view("Other");
let layout = make_layout(&m);
let reg = make_registry();
let ctx = make_ctx(&m, &layout, &reg);
let mut ctx = make_ctx(&m, &layout, &reg);
ctx.view_panel_cursor = 1;
let effects = SwitchViewAtCursor.execute(&ctx);
let dbg = effects_debug(&effects);
assert!(
dbg.contains("SwitchView(\"Default\")"),
"must switch to the view UNDER THE CURSOR, got: {dbg}"
dbg.contains("SwitchView(\"Other\")"),
"must switch to the view UNDER THE CURSOR (Other, index 1), got: {dbg}"
);
assert!(dbg.contains("Normal"), "Expected Normal mode, got: {dbg}");
}
@@ -504,6 +515,27 @@ mod tests {
);
}
/// Evidence: `context/test-evidence/command.md`.
#[test]
fn delete_view_at_cursor_deletes_the_view_under_a_nonzero_cursor() {
let mut m = two_cat_model();
m.create_view("Other");
m.create_view("Third");
let layout = make_layout(&m);
let reg = make_registry();
let mut ctx = make_ctx(&m, &layout, &reg);
ctx.view_panel_cursor = 1;
let dbg = effects_debug(&DeleteViewAtCursor.execute(&ctx));
assert!(
dbg.contains("DeleteView(\"Other\")"),
"must delete the view UNDER THE CURSOR (Other, index 1), got: {dbg}"
);
assert!(
dbg.contains("SetPanelCursor { panel: View, cursor: 0 }"),
"a delete off position 0 steps the cursor back, got: {dbg}"
);
}
#[test]
fn delete_view_at_cursor_zero_does_not_adjust_cursor() {
let m = two_cat_model();