use gpui::{
Context, FocusHandle, IntoElement, KeyBinding, KeyContext, NoAction, Render, TestAppContext,
VisualTestContext, Window, actions, div, prelude::*, px, size,
};
use ui::{keys, menu::Item};
actions!(keys_test, [Bold, Italic, Unbound]);
#[cfg(target_os = "windows")]
const SUPER: &str = "Win+";
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
const SUPER: &str = "Super+";
const SURFACE: &str = "Surface";
struct Host {
surface: FocusHandle,
}
impl Render for Host {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let mut context = KeyContext::default();
context.add(SURFACE);
div().size_full().child(
div()
.key_context(context)
.track_focus(&self.surface)
.on_action(cx.listener(|_: &mut Host, _: &Bold, _, _| {})),
)
}
}
fn open(bindings: Vec<KeyBinding>, cx: &mut TestAppContext) -> VisualTestContext {
cx.update(|cx| {
theme::Theme::install(theme::Appearance::Dark, cx);
cx.bind_keys(bindings);
});
let window = cx.add_window(|_, cx| Host {
surface: cx.focus_handle(),
});
let host = window.root(cx).unwrap();
let mut visual = VisualTestContext::from_window(window.into(), cx);
visual.simulate_resize(size(px(200.0), px(200.0)));
let surface = host.read_with(&visual, |host, _| host.surface.clone());
visual.update(|window, cx| surface.focus(window, cx));
visual.run_until_parked();
visual
}
#[gpui::test]
fn modifiers_are_in_the_platform_order(cx: &mut TestAppContext) {
let mut visual = open(
vec![KeyBinding::new("ctrl-alt-shift-cmd-b", Bold, Some(SURFACE))],
cx,
);
let label = visual
.update(|window, _| keys::shortcut(&Bold, window))
.unwrap();
#[cfg(target_os = "macos")]
assert_eq!(label.as_ref(), "⌃⌥⇧⌘B");
#[cfg(not(target_os = "macos"))]
assert_eq!(label.as_ref(), format!("{SUPER}Ctrl+Alt+Shift+B"));
}
#[gpui::test]
fn named_keys_print_as_the_platform_writes_them(cx: &mut TestAppContext) {
let mut visual = open(
vec![
KeyBinding::new("cmd-backspace", Bold, Some(SURFACE)),
KeyBinding::new("shift-enter", Italic, Some(SURFACE)),
],
cx,
);
let (bold, italic) = visual.update(|window, _| {
(
keys::shortcut(&Bold, window).unwrap(),
keys::shortcut(&Italic, window).unwrap(),
)
});
#[cfg(target_os = "macos")]
{
assert_eq!(bold.as_ref(), "⌘⌫");
assert_eq!(italic.as_ref(), "⇧↩");
}
#[cfg(not(target_os = "macos"))]
{
assert_eq!(bold.as_ref(), format!("{SUPER}Backspace"));
assert_eq!(italic.as_ref(), "Shift+Enter");
}
}
#[gpui::test]
fn a_chord_prints_as_two_keystrokes(cx: &mut TestAppContext) {
let mut visual = open(
vec![KeyBinding::new("ctrl-k ctrl-b", Bold, Some(SURFACE))],
cx,
);
let label = visual
.update(|window, _| keys::shortcut(&Bold, window))
.unwrap();
#[cfg(target_os = "macos")]
assert_eq!(label.as_ref(), "⌃K ⌃B");
#[cfg(not(target_os = "macos"))]
assert_eq!(label.as_ref(), "Ctrl+K Ctrl+B");
}
#[gpui::test]
fn an_unbound_action_has_no_label(cx: &mut TestAppContext) {
let mut visual = open(vec![KeyBinding::new("cmd-b", Bold, Some(SURFACE))], cx);
assert_eq!(
visual.update(|window, _| keys::shortcut(&Unbound, window)),
None
);
}
#[gpui::test]
fn a_global_binding_resolves_from_inside_a_context(cx: &mut TestAppContext) {
let mut visual = open(vec![KeyBinding::new("cmd-k", Bold, None)], cx);
let label = visual
.update(|window, _| keys::shortcut(&Bold, window))
.unwrap();
#[cfg(target_os = "macos")]
assert_eq!(label.as_ref(), "⌘K");
#[cfg(not(target_os = "macos"))]
assert_eq!(label.as_ref(), format!("{SUPER}K"));
}
#[gpui::test]
fn rebinding_moves_the_label(cx: &mut TestAppContext) {
let mut visual = open(
vec![
KeyBinding::new("cmd-b", Bold, Some(SURFACE)),
KeyBinding::new("cmd-shift-b", Bold, Some(SURFACE)),
],
cx,
);
let label = visual
.update(|window, _| keys::shortcut(&Bold, window))
.unwrap();
#[cfg(target_os = "macos")]
assert_eq!(label.as_ref(), "⇧⌘B");
#[cfg(not(target_os = "macos"))]
assert_eq!(label.as_ref(), format!("{SUPER}Shift+B"));
}
#[gpui::test]
fn unbinding_takes_the_label_away(cx: &mut TestAppContext) {
let mut visual = open(
vec![
KeyBinding::new("cmd-b", Bold, Some(SURFACE)),
KeyBinding::new("cmd-b", NoAction, Some(SURFACE)),
],
cx,
);
assert_eq!(
visual.update(|window, _| keys::shortcut(&Bold, window)),
None
);
}
#[gpui::test]
fn a_context_out_of_the_focus_path_needs_shortcut_in(cx: &mut TestAppContext) {
let mut visual = open(vec![KeyBinding::new("cmd-b", Bold, Some("Elsewhere"))], cx);
assert_eq!(
visual.update(|window, _| keys::shortcut(&Bold, window)),
None
);
let label = visual
.update(|window, _| keys::shortcut_in(&Bold, "Elsewhere", window))
.unwrap();
#[cfg(target_os = "macos")]
assert_eq!(label.as_ref(), "⌘B");
#[cfg(not(target_os = "macos"))]
assert_eq!(label.as_ref(), format!("{SUPER}B"));
}
#[gpui::test]
fn a_menu_row_fills_its_accelerator_from_the_keymap(cx: &mut TestAppContext) {
let mut visual = open(vec![KeyBinding::new("cmd-b", Bold, Some("Elsewhere"))], cx);
let (bound, unbound, printed) = visual.update(|window, _| {
(
Item::action("Bold").with_shortcut_in(&Bold, "Elsewhere", window),
Item::action("Italic").with_shortcut_in(&Italic, "Elsewhere", window),
keys::shortcut_in(&Bold, "Elsewhere", window).unwrap(),
)
});
assert_eq!(bound, Item::action("Bold").with_keystroke(printed));
assert_eq!(unbound, Item::action("Italic"));
}