139 lines
4.4 KiB
Rust
139 lines
4.4 KiB
Rust
use gpui::{
|
|
Entity, Modifiers, ParentElement as _, Render, Styled as _, TestAppContext,
|
|
VisualTestContext, Window, div, point, px,
|
|
};
|
|
use gpui_native_core::input::{Input, InputState};
|
|
use gpui_native_theme::Theme;
|
|
|
|
struct Harness {
|
|
state: Entity<InputState>,
|
|
disabled: bool,
|
|
}
|
|
|
|
impl Render for Harness {
|
|
fn render(
|
|
&mut self,
|
|
_window: &mut Window,
|
|
_cx: &mut gpui::Context<Self>,
|
|
) -> impl gpui::IntoElement {
|
|
div().size_full().child(
|
|
Input::new("test-input", self.state.clone())
|
|
.placeholder("Placeholder")
|
|
.disabled(self.disabled),
|
|
)
|
|
}
|
|
}
|
|
|
|
fn input_window(
|
|
initial: &str,
|
|
disabled: bool,
|
|
) -> (TestAppContext, Entity<InputState>, VisualTestContext) {
|
|
let mut cx = TestAppContext::single();
|
|
cx.update(Theme::init);
|
|
let state = cx.update(|cx| InputState::new_with_text(initial, cx));
|
|
let state_for_window = state.clone();
|
|
let window = cx.add_window(move |_, _| Harness {
|
|
state: state_for_window,
|
|
disabled,
|
|
});
|
|
let mut visual = VisualTestContext::from_window(window.into(), &cx);
|
|
visual.update(|window, cx| {
|
|
window.draw(cx).clear(cx);
|
|
});
|
|
(cx, state, visual)
|
|
}
|
|
|
|
fn value(cx: &TestAppContext, state: &Entity<InputState>) -> String {
|
|
cx.update(|cx| state.read(cx).value().to_string())
|
|
}
|
|
|
|
fn focus(visual: &mut VisualTestContext, state: &Entity<InputState>) {
|
|
// Programmatic focus: a click would move the caret to the click point.
|
|
visual.update(|window, cx| {
|
|
let handle = state.read(cx).focus_handle();
|
|
window.focus(&handle, cx);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn typing_inserts_at_the_caret() {
|
|
let (cx, state, mut visual) = input_window("", false);
|
|
focus(&mut visual, &state);
|
|
visual.simulate_keystrokes("h e l l o");
|
|
assert_eq!(value(&cx, &state), "hello");
|
|
visual.simulate_keystrokes("space w o r l d");
|
|
assert_eq!(value(&cx, &state), "hello world");
|
|
}
|
|
|
|
#[test]
|
|
fn arrow_left_moves_the_caret_and_typing_splits_the_text() {
|
|
let (cx, state, mut visual) = input_window("ab", false);
|
|
focus(&mut visual, &state);
|
|
visual.simulate_keystrokes("left");
|
|
visual.simulate_keystrokes("x");
|
|
assert_eq!(value(&cx, &state), "axb");
|
|
}
|
|
|
|
#[test]
|
|
fn backspace_deletes_before_the_caret_and_delete_after() {
|
|
let (cx, state, mut visual) = input_window("abc", false);
|
|
focus(&mut visual, &state);
|
|
visual.simulate_keystrokes("backspace");
|
|
assert_eq!(value(&cx, &state), "ab");
|
|
// The caret sits between 'a' and 'b'; forward delete removes 'b'.
|
|
visual.simulate_keystrokes("left");
|
|
visual.simulate_keystrokes("delete");
|
|
assert_eq!(value(&cx, &state), "a");
|
|
}
|
|
|
|
#[test]
|
|
fn alt_arrow_moves_by_words() {
|
|
let (cx, state, mut visual) = input_window("hello world", false);
|
|
focus(&mut visual, &state);
|
|
visual.simulate_keystrokes("alt-left");
|
|
visual.simulate_keystrokes("x");
|
|
assert_eq!(value(&cx, &state), "hello xworld");
|
|
visual.simulate_keystrokes("alt-left alt-left");
|
|
visual.simulate_keystrokes("shift-right shift-right");
|
|
visual.simulate_keystrokes("z");
|
|
assert_eq!(value(&cx, &state), "zllo xworld");
|
|
}
|
|
|
|
#[test]
|
|
fn select_all_then_type_replaces_the_value() {
|
|
let (cx, state, mut visual) = input_window("abcd", false);
|
|
focus(&mut visual, &state);
|
|
visual.simulate_keystrokes("cmd-a");
|
|
visual.simulate_keystrokes("z");
|
|
assert_eq!(value(&cx, &state), "z");
|
|
}
|
|
|
|
#[test]
|
|
fn shift_arrow_selects_and_backspace_removes_the_selection() {
|
|
let (cx, state, mut visual) = input_window("ab", false);
|
|
focus(&mut visual, &state);
|
|
// Caret starts at the end; selecting left twice covers "ab".
|
|
visual.simulate_keystrokes("shift-left shift-left");
|
|
visual.simulate_keystrokes("backspace");
|
|
assert_eq!(value(&cx, &state), "");
|
|
}
|
|
|
|
#[test]
|
|
fn disabled_input_ignores_typing_and_clicks() {
|
|
// No programmatic focus: a disabled field must not take focus, so the
|
|
// key events fall to nothing and the input handler is never registered.
|
|
let (cx, state, mut visual) = input_window("", true);
|
|
visual.simulate_click(point(px(20.), px(14.)), Modifiers::default());
|
|
visual.simulate_keystrokes("h");
|
|
assert_eq!(value(&cx, &state), "");
|
|
}
|
|
|
|
#[test]
|
|
fn set_value_replaces_the_buffer() {
|
|
let (cx, state, mut visual) = input_window("", false);
|
|
visual.update(|window, cx| {
|
|
state.update(cx, |state, cx| state.set_value("preset", window, cx));
|
|
});
|
|
assert_eq!(value(&cx, &state), "preset");
|
|
}
|