Files
cthulhu/internal/app/key_bindings_test.go

133 lines
5.0 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"context"
"errors"
"git.stormux.org/storm/cthulhu/internal/config"
"git.stormux.org/storm/cthulhu/internal/input"
"git.stormux.org/storm/cthulhu/internal/preferences"
"log/slog"
"path/filepath"
"reflect"
"testing"
)
type bindingRecorder struct {
values []input.BindingOverride
calls int
err error
}
func (recorder *bindingRecorder) SetKeyBindings(_ context.Context, values []input.BindingOverride) error {
recorder.calls++
if recorder.err != nil {
return recorder.err
}
recorder.values = input.CloneBindingOverrides(values)
return nil
}
func TestPreferencesKeyBindingsApplySaveResetAndFailure(t *testing.T) {
settings := config.DefaultSettings()
settings.Path = filepath.Join(t.TempDir(), "settings.toml")
worker := newPreferencesWorker(slog.New(slog.DiscardHandler), settings, nil)
recorder := &bindingRecorder{}
worker.bindings = recorder
values := preferences.FromSettings(settings)
values.KeyBindings = []input.BindingOverride{{Layout: input.DesktopKeyboardLayout, Scope: "global", Command: input.Preferences, Keys: []string{"Cthulhu+F8"}}}
recorder.err = errors.New("grab conflict")
response := worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if response.Accepted || len(worker.settings.KeyBindings) != 0 {
t.Fatal("failed update committed")
}
recorder.err = nil
response = worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if !response.Accepted || !reflect.DeepEqual(values.KeyBindings, recorder.values) {
t.Fatalf("apply: %+v", response)
}
loaded, err := config.Load(settings.Path)
if err != nil || !reflect.DeepEqual(values.KeyBindings, loaded.KeyBindings) {
t.Fatalf("save: %v", err)
}
calls := recorder.calls
values.KeyBindings[0].Keys = []string{"Cthulhu+q"}
response = worker.apply(context.Background(), preferences.Request{Values: values})
if response.Accepted || recorder.calls != calls {
t.Fatal("invalid bindings reached backend")
}
values.KeyBindings[0].Keys = []string{"Cthulhu+F9"}
rate := 70.0
values.Rate = &rate
response = worker.apply(context.Background(), preferences.Request{Values: values})
if response.Accepted || recorder.values[0].Keys[0] != "Cthulhu+F8" {
t.Fatal("later backend failure did not restore keys")
}
values.Rate = nil
values.KeyBindings = nil
response = worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if !response.Accepted || len(recorder.values) != 0 {
t.Fatal("reset was not applied")
}
}
type keyboardRecorder struct {
bindingRecorder
layout input.KeyboardLayout
modifiers []string
}
func (recorder *keyboardRecorder) SetKeyboardConfiguration(ctx context.Context, layout input.KeyboardLayout, modifiers []string, overrides []input.BindingOverride) error {
if err := recorder.SetKeyBindings(ctx, overrides); err != nil {
return err
}
recorder.layout = layout
recorder.modifiers = append([]string(nil), modifiers...)
return nil
}
func TestPreferencesKeyboardConfigurationApplySaveRollback(t *testing.T) {
settings := config.DefaultSettings()
settings.Path = filepath.Join(t.TempDir(), "settings.toml")
worker := newPreferencesWorker(slog.New(slog.DiscardHandler), settings, nil)
recorder := &keyboardRecorder{}
worker.bindings = recorder
values := preferences.FromSettings(settings)
values.KeyboardLayout = 2
values.CthulhuModifierKeys = []string{"Caps_Lock"}
recorder.err = errors.New("modifier grab conflict")
response := worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if response.Accepted || worker.settings.KeyboardLayout != 1 {
t.Fatal("failed modifier update committed")
}
recorder.err = nil
response = worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if !response.Accepted || recorder.layout != input.LaptopKeyboardLayout || !reflect.DeepEqual(recorder.modifiers, values.CthulhuModifierKeys) {
t.Fatalf("apply: %+v", response)
}
loaded, err := config.Load(settings.Path)
if err != nil || loaded.KeyboardLayout != 2 || !reflect.DeepEqual(loaded.CthulhuModifierKeys, values.CthulhuModifierKeys) {
t.Fatalf("save keyboard: %v", err)
}
values.KeyboardLayout = 1
values.CthulhuModifierKeys = []string{"KP_Insert"}
rate := 70.0
values.Rate = &rate
response = worker.apply(context.Background(), preferences.Request{Values: values})
if response.Accepted || recorder.layout != input.LaptopKeyboardLayout || !reflect.DeepEqual(recorder.modifiers, []string{"Caps_Lock"}) {
t.Fatal("later backend failure did not restore keyboard configuration")
}
values.Rate = nil
values.CthulhuModifierKeys = []string{}
response = worker.apply(context.Background(), preferences.Request{Values: values, Save: true})
if !response.Accepted || len(recorder.modifiers) != 0 {
t.Fatalf("all unchecked: %+v", response)
}
loaded, err = config.Load(settings.Path)
if err != nil || len(loaded.CthulhuModifierKeys) != 0 {
t.Fatalf("reload all unchecked: %v", err)
}
}