improvise-7mro: red lockstep matrix, keys sent before a scroll is answered

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-23 19:11:18 -07:00
parent 6942e53e5e
commit 32f6067423
@@ -2662,3 +2662,140 @@ fn renaming_a_formula_from_the_panel_lands_the_same_document_as_the_host() {
assert_eq!(client.view.status_msg, "Formula updated");
assert_eq!(app.view_state.status_msg, "Renamed Tax to Levy");
}
/// One scroll-then-edit case: the window, where the cursor starts, and the keys.
type Pipelined = (
&'static str,
(usize, usize),
((usize, usize), usize, usize),
&'static [&'static str],
);
/// `wrapping_host`'s cells that differ from how it was built, as `Month/Measure`.
fn written_cells(app: &App) -> Vec<String> {
let model = &app.model_state.workbook.model;
let mut written = Vec::new();
for month in ["Jan", "Feb"] {
for (measure, built) in [("Revenue", Some(10.0)), ("Profit", None), ("Cost", Some(4.0))] {
let key = improvise_command::model::cell::CellKey::new(vec![
("Month".to_string(), month.to_string()),
("_Measure".to_string(), measure.to_string()),
]);
let now = model.get_cell(&key).cloned();
if now != built.map(improvise_protocol::CellValue::Number) {
written.push(format!("{month}/{measure}"));
}
}
}
written
}
/// One key on the client, its frame sent to the host; the reply comes back
/// for the caller to deliver or hold. An upstream key reaches a host that answers nothing.
fn sent(
host: &mut improvise_command::ui::host::Host,
session: improvise_command::ui::project::SessionId,
client: &mut ClientState,
key: &str,
) -> Vec<improvise_command::ui::host::Addressed> {
match resolve(client, BrowserKey::new(key).to_key_event().unwrap()) {
KeyOutcome::Local(cmds) => {
client.fold_outgoing(&cmds);
host.handle(session, ClientFrame::Commands(cmds))
}
_ => Vec::new(),
}
}
/// improvise-7mro: the offset-aliasing matrix, replies delivered and replies
/// held. See `context/test-evidence/clients.md`.
#[test]
fn keys_sent_before_a_scroll_is_answered_agree_with_the_tui() {
let cases: [Pipelined; 5] = [
("wrap", (2, 6), ((2, 0), 1, 0), &["i", "Enter", "8", "Enter"]),
("horizontal wrap", (2, 1), ((2, 0), 1, 0), &["i", "Enter", "8", "Enter"]),
("G", (2, 6), ((0, 0), 0, 0), &["G", "i", "7", "Enter"]),
("$", (2, 1), ((0, 0), 0, 0), &["$", "i", "7", "Enter"]),
("gg", (2, 6), ((2, 0), 1, 0), &["g", "g", "i", "7", "Enter"]),
];
for (name, window, (at, row_offset, col_offset), keys) in cases {
let mut tui = wrapping_host();
tui.cursor_mut().selected = at;
for &k in keys {
reduce_key(&mut tui, BrowserKey::new(k).to_key_event().unwrap());
}
assert_eq!(written_cells(&tui).len(), 1, "setup: {name}: the TUI wrote one cell");
for held in [false, true] {
let what = format!("{name} ({keys:?}, replies held: {held})");
let mut host = improvise_command::ui::host::Host::new(wrapping_host());
let (session, welcome) = host.connect(window.0, window.1);
let mut client = ClientState {
window,
..ClientState::default()
};
deliver(vec![welcome], session, &mut client);
let placed = vec![
improvise_protocol::Command::SetSelected {
row: at.0,
col: at.1,
},
improvise_protocol::Command::SetRowOffset(row_offset),
improvise_protocol::Command::SetColOffset(col_offset),
];
client.fold_outgoing(&placed);
deliver(
host.handle(session, ClientFrame::Commands(placed)),
session,
&mut client,
);
let mut replies = Vec::new();
for &k in keys {
let reply = sent(&mut host, session, &mut client, k);
match held {
true => replies.extend(reply),
false => deliver(reply, session, &mut client),
}
}
if held {
assert_eq!(
written_cells(host.app()),
Vec::<String>::new(),
"{what}: a write was composed before its target was projected"
);
assert!(
client.view.mode.is_editing() && !client.view.status_msg.is_empty(),
"{what}: Enter must wait out loud with the editor open: {:?}, {:?}",
client.view.mode,
client.view.status_msg
);
deliver(replies, session, &mut client);
let reply = sent(&mut host, session, &mut client, "Enter");
deliver(reply, session, &mut client);
}
assert_eq!(
written_cells(host.app()),
written_cells(&tui),
"{what}: the browser wrote a different cell from the TUI"
);
if !held {
assert_eq!(document_text(host.app()), document_text(&tui), "{what}");
}
assert_eq!(
client.view.cursor().selected,
tui.view_state.cursor().selected,
"{what}: the cursor"
);
assert_eq!(
format!("{:?}", client.view.mode),
format!("{:?}", tui.view_state.mode),
"{what}: the mode; browser status {:?}",
client.view.status_msg
);
assert_eq!(
client.view.buffers.get("edit"),
tui.view_state.buffers.get("edit"),
"{what}: the editor's buffer"
);
}
}
}