Files

123 lines
4.6 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package input
import (
"reflect"
"testing"
)
func TestBindingDefaultsRoundTrip(t *testing.T) {
for _, layout := range []KeyboardLayout{DesktopKeyboardLayout, LaptopKeyboardLayout} {
for chord := range BrowseCommandBindings(layout) {
parsed, err := ParseCommandChord(FormatCommandChord(chord))
if err != nil || parsed != chord {
t.Fatalf("%+v round trip: %+v %v", chord, parsed, err)
}
}
got, err := ResolveCommandBindings(layout, true, nil)
if err != nil || !reflect.DeepEqual(got, BrowseCommandBindings(layout)) {
t.Fatalf("default changed: %v", err)
}
}
}
func TestBindingOverridesScopesLayoutsAndDisable(t *testing.T) {
overrides := []BindingOverride{
{DesktopKeyboardLayout, "global", Preferences, []string{"Cthulhu+Ctrl+F8", "Alt+F9"}},
{DesktopKeyboardLayout, "browse", DocumentNextHeading, []string{"F6"}},
{DesktopKeyboardLayout, "global", Quit, []string{}},
}
if err := ValidateBindingOverrides(overrides); err != nil {
t.Fatal(err)
}
for _, browse := range []bool{false, true} {
bindings, err := ResolveCommandBindings(DesktopKeyboardLayout, browse, overrides)
if err != nil {
t.Fatal(err)
}
for _, key := range []string{"Cthulhu+Space", "Cthulhu+q"} {
chord, _ := ParseCommandChord(key)
if bindings[chord] != "" {
t.Fatalf("old binding %s remains", key)
}
}
chord, _ := ParseCommandChord("Alt+F9")
if bindings[chord] != Preferences {
t.Fatal("custom global missing")
}
if bindings[CommandChord{Symbol: 'h', CthulhuModifier: true}] != ToggleLearnMode {
t.Fatal("learn mode shortcut lost")
}
chord, _ = ParseCommandChord("F6")
if (bindings[chord] == DocumentNextHeading) != browse || bindings[CommandChord{Symbol: 'h'}] != "" {
t.Fatal("browse scope leaked or old heading remains")
}
}
laptop, _ := ResolveCommandBindings(LaptopKeyboardLayout, false, overrides)
if !reflect.DeepEqual(laptop, DefaultCommandBindings(LaptopKeyboardLayout)) {
t.Fatal("desktop override changed laptop")
}
if !reflect.DeepEqual(CloneBindingOverrides(overrides), overrides) {
t.Fatal("clone changed overrides")
}
clone := CloneBindingOverrides(overrides)
clone[0].Keys[0] = "F1"
if overrides[0].Keys[0] == "F1" {
t.Fatal("clone aliases keys")
}
}
func TestBindingValidation(t *testing.T) {
for _, overrides := range [][]BindingOverride{
{{DesktopKeyboardLayout, "global", Preferences, []string{"Cthulhu+q"}}},
{{DesktopKeyboardLayout, "global", Preferences, []string{"h"}}},
{{DesktopKeyboardLayout, "browse", DocumentNextHeading, []string{"Cthulhu+q"}}},
{{DesktopKeyboardLayout, "global", Preferences, []string{"F8", "f8"}}},
{{DesktopKeyboardLayout, "global", Preferences, []string{"Insert"}}},
{{DesktopKeyboardLayout, "global", Command("unknown"), []string{"F8"}}},
{{KeyboardLayout(0), "global", Preferences, []string{"F8"}}},
{{DesktopKeyboardLayout, "unknown", Preferences, []string{"F8"}}},
{{DesktopKeyboardLayout, "global", Preferences, nil}, {DesktopKeyboardLayout, "global", Preferences, nil}},
} {
if err := ValidateBindingOverrides(overrides); err == nil {
t.Fatalf("accepted %+v", overrides)
}
}
for _, key := range []string{"", "Ctrl+", "Ctrl+Ctrl+x", "Cthulhu+Cthulhu+x", "Hyper+x", "F36", "Ctrl+\n"} {
if _, err := ParseCommandChord(key); err == nil {
t.Fatalf("accepted %q", key)
}
}
swaps := []BindingOverride{{DesktopKeyboardLayout, "global", Quit, []string{"Cthulhu+Space"}}, {DesktopKeyboardLayout, "global", Preferences, []string{"Cthulhu+q"}}}
if err := ValidateBindingOverrides(swaps); err != nil {
t.Fatalf("swap: %v", err)
}
unbound := []BindingOverride{{DesktopKeyboardLayout, "global", PresentDate, []string{"F8"}}}
if err := ValidateBindingOverrides(unbound); err != nil {
t.Fatalf("unbound command: %v", err)
}
}
func TestCustomBindingRouterBalancedReleaseAndMultiPress(t *testing.T) {
overrides := []BindingOverride{{DesktopKeyboardLayout, "global", PresentTime, []string{"Cthulhu+Ctrl+Alt+F8"}}}
bindings, err := ResolveCommandBindings(DesktopKeyboardLayout, true, overrides)
if err != nil {
t.Fatal(err)
}
router := NewCommandRouter([]uint32{0xff63}, bindings)
for _, want := range []Command{PresentTime, PresentDate} {
router.Handle(0xff63, 1, 0, true)
consumed, command := router.Handle(0xffc5, 2, 4|8, true)
if !consumed || command != want {
t.Fatalf("%v %s want %s", consumed, command, want)
}
router.Handle(0xff63, 1, 0, false)
if consumed, command = router.Handle(0xffc5, 2, 4|8, false); !consumed || command != "" {
t.Fatal("custom release unbalanced")
}
}
}