Lock the input invariants with web_surface store regressions
Five PerTabSurface tests pin the input contract so future refactors can't silently regress it: - typed_text_enters_pending_input_after_clicked_viewport: typing reaches the sidecar once a click establishes keyboard focus. - scroll_delta_enters_pending_input_after_wheel: scroll deltas combine across multiple wheel events. - viewport_size_changes_after_stable_second_measurement: viewport resize is debounced behind a "same size twice" guard. - scroll_after_click_keeps_keyboard_focus_and_typed_text: the bug fixed last commit cycle — scroll drops the buffered click point but must keep keyboard_focus and buffered keystrokes. - typing_without_a_prior_click_is_rejected: typing without focus returns false, so a future refactor can't accept stray keystrokes. No instrumentation eprintln/log added in production paths (per CLAUDE.md NO LOGGING). cargo test ely_app --bin ely_app: 102 passed.
This commit is contained in:
@@ -49,6 +49,70 @@ fn viewport_size_changes_after_stable_second_measurement() -> Result<(), Box<dyn
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regression — a wheel scroll between focusing a field and typing
|
||||||
|
/// must not erase keyboard focus or buffered keystrokes.
|
||||||
|
///
|
||||||
|
/// The `record_scroll_delta` path drops `click_point` on purpose
|
||||||
|
/// (its viewport coordinates are stale once the page scrolls) but
|
||||||
|
/// must keep `keyboard_focus` and `typed_text`, so a focused input
|
||||||
|
/// keeps receiving the user's keystrokes after they wheel-scroll.
|
||||||
|
/// Locks the fix from commit fcac326-era input-loss work.
|
||||||
|
#[test]
|
||||||
|
fn scroll_after_click_keeps_keyboard_focus_and_typed_text() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut store = WebSurfaceStore::new();
|
||||||
|
let tab = web_tab("https://example.com/form")?;
|
||||||
|
let url = tab.url().as_str();
|
||||||
|
|
||||||
|
assert!(store.record_viewport_size(tab.id(), web_bounds()));
|
||||||
|
assert!(store.record_click_point(tab.id(), url, point(px(160.0), px(120.0))));
|
||||||
|
assert!(store.record_typed_text(tab.id(), url, "h"));
|
||||||
|
|
||||||
|
assert!(store.record_scroll_delta(tab.id(), url, point(px(0.0), px(140.0))));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
store.record_typed_text(tab.id(), url, "i"),
|
||||||
|
"scroll must not erase keyboard focus — typing after a scroll should still buffer",
|
||||||
|
);
|
||||||
|
|
||||||
|
let input = store.take_pending_input(tab.id(), url);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
input.scroll_delta.map(|delta| (delta.x(), delta.y())),
|
||||||
|
Some((0, 140)),
|
||||||
|
"scroll delta should reach the sidecar",
|
||||||
|
);
|
||||||
|
assert_eq!(input.scroll_offset.y(), 140);
|
||||||
|
assert!(
|
||||||
|
input.click_point.is_none(),
|
||||||
|
"post-scroll click coordinates would land on the wrong DOM node — they must be dropped",
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
input.typed_text.as_deref(),
|
||||||
|
Some("hi"),
|
||||||
|
"buffered keystrokes from before AND after the scroll must reach the sidecar",
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Locks the precondition that `record_typed_text` requires a prior
|
||||||
|
/// click to have established keyboard focus. Without this guard, a
|
||||||
|
/// future refactor could silently start buffering stray keystrokes
|
||||||
|
/// against an unfocused tab — and the user would see characters land
|
||||||
|
/// on whichever DOM node Servo last focused, with no visible cause.
|
||||||
|
#[test]
|
||||||
|
fn typing_without_a_prior_click_is_rejected() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut store = WebSurfaceStore::new();
|
||||||
|
let tab = web_tab("https://example.com/form")?;
|
||||||
|
let url = tab.url().as_str();
|
||||||
|
|
||||||
|
assert!(store.record_viewport_size(tab.id(), web_bounds()));
|
||||||
|
assert!(
|
||||||
|
!store.record_typed_text(tab.id(), url, "x"),
|
||||||
|
"typing must fail until a click establishes keyboard focus on this tab and url",
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn web_bounds() -> Bounds<gpui::Pixels> {
|
fn web_bounds() -> Bounds<gpui::Pixels> {
|
||||||
Bounds::new(point(px(0.0), px(0.0)), size(px(640.0), px(480.0)))
|
Bounds::new(point(px(0.0), px(0.0)), size(px(640.0), px(480.0)))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user