hover_test.go RawHistoryFolder
1package input
2
3import (
4 "context"
5 "reflect"
6 "testing"
7
8 "github.com/bnema/dumber/internal/domain/entity"
9 "github.com/bnema/puregotk/v4/gtk"
10)
11
12func TestHoverHandlerSchedulesCallbackOnGLibAndRejectsStaleGeneration(t *testing.T) {
13 h := NewHoverHandler(context.Background(), entity.PaneID("pane-1"))
14 var scheduled func(uintptr) bool
15 h.schedule = func(_ uint, fn func(uintptr) bool) uint {
16 scheduled = fn
17 return 7
18 }
19
20 var calls int
21 h.SetOnEnter(func(entity.PaneID) { calls++ })
22 h.handleEnter()
23 first := scheduled
24 h.handleEnter()
25 if first(0) {
26 t.Fatal("hover source must be one-shot")
27 }
28 if calls != 0 {
29 t.Fatalf("stale hover callback ran %d times", calls)
30 }
31 if scheduled == nil {
32 t.Fatal("current hover callback was not scheduled")
33 }
34 if scheduled(0) {
35 t.Fatal("hover source must be one-shot")
36 }
37 if calls != 1 {
38 t.Fatalf("current hover callback ran %d times, want 1", calls)
39 }
40}
41
42func TestHoverHandlerDetachRemovesNativeControllerAndSignalsExactlyOnce(t *testing.T) {
43 widget := >k.Widget{}
44 controller := >k.EventControllerMotion{}
45 h := NewHoverHandler(context.Background(), entity.PaneID("pane-1"))
46 h.attachedWidget = widget
47 h.motionCtrl = controller
48 h.enterSignalID = 1
49 h.leaveSignalID = 2
50 h.motionSignalID = 3
51 var disconnected []uint
52 var removed int
53 h.disconnectSignal = func(_ *gtk.EventControllerMotion, id uint) { disconnected = append(disconnected, id) }
54 h.removeController = func(gotWidget *gtk.Widget, gotController *gtk.EventController) {
55 if gotWidget != widget || gotController != &controller.EventController {
56 t.Fatal("detach removed the wrong native controller")
57 }
58 removed++
59 }
60
61 h.Detach()
62 h.Detach()
63
64 if got, want := disconnected, []uint{1, 2, 3}; !reflect.DeepEqual(got, want) {
65 t.Fatalf("disconnected signals = %v, want %v", got, want)
66 }
67 if removed != 1 {
68 t.Fatalf("native controllers removed = %d, want 1", removed)
69 }
70 if h.attachedWidget != nil || h.motionCtrl != nil || h.enterCb != nil || h.leaveCb != nil || h.motionCb != nil {
71 t.Fatal("detach must clear native and callback ownership")
72 }
73}
74
75func TestHoverHandlerDetachInvalidatesScheduledCallbackAndRemovesSource(t *testing.T) {
76 h := NewHoverHandler(context.Background(), entity.PaneID("pane-1"))
77 var scheduled func(uintptr) bool
78 var removed []uint
79 h.schedule = func(_ uint, fn func(uintptr) bool) uint { scheduled = fn; return 9 }
80 h.removeSource = func(id uint) bool { removed = append(removed, id); return true }
81 h.SetOnEnter(func(entity.PaneID) { t.Fatal("detached hover callback ran") })
82 h.handleEnter()
83 h.Detach()
84 if len(removed) != 1 || removed[0] != 9 {
85 t.Fatalf("removed sources = %v, want [9]", removed)
86 }
87 if scheduled == nil || scheduled(0) {
88 t.Fatal("detached callback must be rejected and one-shot")
89 }
90}