1package input
2
3import (
4 "context"
5 "testing"
6
7 "github.com/bnema/puregotk/v4/gdk"
8 "github.com/stretchr/testify/assert"
9 "github.com/stretchr/testify/require"
10
11 "github.com/bnema/dumber/internal/domain/entity"
12)
13
14func TestPageKeyCaptureForwardsVimModeKeys(t *testing.T) {
15 ws := vimModeSequenceWorkspace(map[string]entity.ActionBinding{
16 "vim-scroll-down": {Keys: []string{"j"}},
17 "yank-section": {Keys: []string{"yah"}},
18 })
19 h := NewKeyboardHandler(context.Background(), ws, newTestSession())
20 actions := captureSequenceActions(h)
21 enterVimMode(t, h)
22
23 var forwarded []string
24 h.SetPageKeyCapture(func(key string) { forwarded = append(forwarded, key) })
25
26 require.True(t, h.handleKeyPress(uint('y'), 0, 0))
27 require.True(t, h.handleKeyPress(uint('J'), 0, gdk.ShiftMaskValue))
28 require.True(t, h.handleKeyPress(uint(gdk.KEY_Shift_L), 0, 0))
29 require.True(t, h.handleKeyPress(uint(gdk.KEY_Return), 0, 0))
30
31 assert.Equal(t, []string{"y", "J", "<Return>"}, forwarded)
32 assert.Empty(t, *actions, "captured keys must not reach Vim bindings")
33 assert.Equal(t, ModeVim, h.Mode(), "Enter is forwarded instead of confirming Vim Mode")
34 assert.Empty(t, h.PendingSequence())
35}
36
37func TestPageKeyCaptureEscapeIsForwardedAndKeepsCaptureForPageToEnd(t *testing.T) {
38 h := NewKeyboardHandler(context.Background(), vimModeSequenceWorkspace(nil), newTestSession())
39 enterVimMode(t, h)
40 var forwarded []string
41 h.SetPageKeyCapture(func(key string) { forwarded = append(forwarded, key) })
42
43 require.True(t, h.handleKeyPress(uint(gdk.KEY_Escape), 0, 0))
44
45 assert.Equal(t, []string{"<Escape>"}, forwarded)
46 assert.True(t, h.PageKeyCaptureActive(), "the page steps back or reports the end itself")
47 assert.Equal(t, ModeVim, h.Mode())
48
49 h.ClearPageKeyCapture()
50 assert.False(t, h.PageKeyCaptureActive())
51}
52
53func TestPageKeyCaptureClearedWhenLeavingVimMode(t *testing.T) {
54 h := NewKeyboardHandler(context.Background(), vimModeSequenceWorkspace(nil), newTestSession())
55 enterVimMode(t, h)
56 h.SetPageKeyCapture(func(string) {})
57
58 h.ExitMode()
59
60 assert.False(t, h.PageKeyCaptureActive())
61}
62
63func TestPageKeyCaptureModifiedEscapeForwardsPlainEscape(t *testing.T) {
64 h := NewKeyboardHandler(context.Background(), vimModeSequenceWorkspace(nil), newTestSession())
65 enterVimMode(t, h)
66 var forwarded []string
67 h.SetPageKeyCapture(func(key string) { forwarded = append(forwarded, key) })
68
69 require.True(t, h.handleKeyPress(uint(gdk.KEY_Escape), 0, gdk.ShiftMaskValue))
70
71 assert.Equal(t, []string{"<Escape>"}, forwarded)
72}
73
74// Capturing keys for the page must not report a cleared pending sequence:
75// the pending callback repaints the mode toast and would erase the sub-mode
76// label shown an instant earlier.
77func TestSetPageKeyCaptureDoesNotNotifyPendingListeners(t *testing.T) {
78 h := NewKeyboardHandler(context.Background(), vimModeSequenceWorkspace(nil), newTestSession())
79 enterVimMode(t, h)
80 pending := capturePending(h)
81
82 h.SetPageKeyCapture(func(string) {})
83
84 assert.Empty(t, *pending)
85 assert.Empty(t, h.PendingSequence())
86}
87
88// The Vim Mode toggle shortcut is the escape hatch from a page interaction:
89// it must reach Go, leave Vim Mode and release the capture, never the page.
90func TestPageKeyCaptureLeavesVimModeToggleShortcutToGo(t *testing.T) {
91 h := NewKeyboardHandler(context.Background(), vimModeSequenceWorkspace(nil), newTestSession())
92 enterVimMode(t, h)
93 var forwarded []string
94 h.SetPageKeyCapture(func(key string) { forwarded = append(forwarded, key) })
95 h.handleKeyRelease(uint('y')) // the activation press is over; this is a new press
96
97 require.True(t, h.handleKeyPress(uint('y'), 0, gdk.ControlMaskValue))
98
99 assert.Empty(t, forwarded, "the toggle shortcut must not be forwarded to the page")
100 assert.Equal(t, ModeNormal, h.Mode())
101 assert.False(t, h.PageKeyCaptureActive(), "leaving Vim Mode releases the capture")
102}
103
104func TestPageKeyCaptureHonorsConfiguredToggleShortcut(t *testing.T) {
105 ws := vimModeSequenceWorkspace(nil)
106 ws.VimMode.ActivationShortcut = "ctrl+g"
107 h := NewKeyboardHandler(context.Background(), ws, newTestSession())
108 h.EnterVimMode()
109 var forwarded []string
110 h.SetPageKeyCapture(func(key string) { forwarded = append(forwarded, key) })
111
112 require.True(t, h.handleKeyPress(uint('y'), 0, gdk.ControlMaskValue), "ctrl+y is an ordinary key now")
113 assert.Equal(t, []string{"<C-y>"}, forwarded)
114 require.True(t, h.handleKeyPress(uint('g'), 0, gdk.ControlMaskValue))
115
116 assert.Equal(t, []string{"<C-y>"}, forwarded)
117 assert.Equal(t, ModeNormal, h.Mode())
118}