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:
@@ -4721,17 +4721,38 @@ are now named, so moving the right cursor on the wrong panel fails.
|
|||||||
|
|
||||||
### delete_formula_at_cursor_with_formulas
|
### delete_formula_at_cursor_with_formulas
|
||||||
|
|
||||||
Asserts the `RemoveFormula` names `Profit` in `Type` — the formula the cursor is
|
Asserts the `RemoveFormula` names the formula the cursor is on, rather than merely
|
||||||
on — rather than merely that a formula was removed.
|
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
|
### 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
|
### delete_view_at_cursor_zero_does_not_adjust_cursor
|
||||||
|
|
||||||
Names `Default` too. Its existing negative half — no `SetPanelCursor` at
|
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
|
### commit_category_add_with_name_produces_add_effect
|
||||||
|
|
||||||
|
|||||||
@@ -395,39 +395,50 @@ mod tests {
|
|||||||
assert!(effects.is_empty());
|
assert!(effects.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evidence: `context/test-evidence/command.md`.
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_formula_at_cursor_with_formulas() {
|
fn delete_formula_at_cursor_with_formulas() {
|
||||||
let mut m = two_cat_model();
|
let mut m = two_cat_model();
|
||||||
m.model.add_formula(crate::formula::ast::Formula {
|
for (target, raw) in [("Profit", "Profit = 1"), ("Tax", "Tax = 2")] {
|
||||||
raw: "Profit = Revenue - Cost".to_string(),
|
m.model.add_formula(crate::formula::ast::Formula {
|
||||||
target: "Profit".to_string(),
|
raw: raw.to_string(),
|
||||||
target_category: "Type".to_string(),
|
target: target.to_string(),
|
||||||
expr: crate::formula::ast::Expr::Number(0.0),
|
target_category: "Type".to_string(),
|
||||||
filter: None,
|
expr: crate::formula::ast::Expr::Number(0.0),
|
||||||
format: None,
|
filter: None,
|
||||||
});
|
format: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
let layout = make_layout(&m);
|
let layout = make_layout(&m);
|
||||||
let reg = make_registry();
|
let reg = make_registry();
|
||||||
let ctx = make_ctx(&m, &layout, ®);
|
let mut ctx = make_ctx(&m, &layout, ®);
|
||||||
|
ctx.formula_cursor = 1;
|
||||||
let effects = DeleteFormulaAtCursor.execute(&ctx);
|
let effects = DeleteFormulaAtCursor.execute(&ctx);
|
||||||
let dbg = effects_debug(&effects);
|
let dbg = effects_debug(&effects);
|
||||||
assert!(
|
assert!(
|
||||||
dbg.contains("RemoveFormula { target: \"Profit\", target_category: \"Type\" }"),
|
dbg.contains("RemoveFormula { target: \"Tax\", target_category: \"Type\" }"),
|
||||||
"must remove the formula AT THE CURSOR, got: {dbg}"
|
"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]
|
#[test]
|
||||||
fn switch_view_at_cursor_with_valid_cursor() {
|
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 layout = make_layout(&m);
|
||||||
let reg = make_registry();
|
let reg = make_registry();
|
||||||
let ctx = make_ctx(&m, &layout, ®);
|
let mut ctx = make_ctx(&m, &layout, ®);
|
||||||
|
ctx.view_panel_cursor = 1;
|
||||||
let effects = SwitchViewAtCursor.execute(&ctx);
|
let effects = SwitchViewAtCursor.execute(&ctx);
|
||||||
let dbg = effects_debug(&effects);
|
let dbg = effects_debug(&effects);
|
||||||
assert!(
|
assert!(
|
||||||
dbg.contains("SwitchView(\"Default\")"),
|
dbg.contains("SwitchView(\"Other\")"),
|
||||||
"must switch to the view UNDER THE CURSOR, got: {dbg}"
|
"must switch to the view UNDER THE CURSOR (Other, index 1), got: {dbg}"
|
||||||
);
|
);
|
||||||
assert!(dbg.contains("Normal"), "Expected Normal mode, 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, ®);
|
||||||
|
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]
|
#[test]
|
||||||
fn delete_view_at_cursor_zero_does_not_adjust_cursor() {
|
fn delete_view_at_cursor_zero_does_not_adjust_cursor() {
|
||||||
let m = two_cat_model();
|
let m = two_cat_model();
|
||||||
|
|||||||
Reference in New Issue
Block a user