1package completions
2
3import (
4 "testing"
5
6 "charm.land/lipgloss/v2"
7 "github.com/sahilm/fuzzy"
8 "github.com/stretchr/testify/require"
9)
10
11// TestCompletionItem_MutatorsBumpVersion covers F6 ยง4.5 for the
12// completions popup: SetMatch and SetFocused must bump Version()
13// when the observable state changes, and dedupe (no bump) when the
14// supplied value is identical to the current state. Without
15// dedupe, the steady completions popup would invalidate the
16// list-level memo on every keystroke that produced the same match.
17func TestCompletionItem_MutatorsBumpVersion(t *testing.T) {
18 t.Parallel()
19
20 mkItem := func() *CompletionItem {
21 return NewCompletionItem(
22 "internal/ui/chat/user.go",
23 FileCompletionValue{Path: "internal/ui/chat/user.go"},
24 lipgloss.NewStyle(),
25 lipgloss.NewStyle(),
26 lipgloss.NewStyle(),
27 )
28 }
29
30 t.Run("SetFocused", func(t *testing.T) {
31 t.Parallel()
32 item := mkItem()
33
34 // First transition (false -> true) must bump.
35 before := item.Version()
36 item.SetFocused(true)
37 require.Greater(t, item.Version(), before, "SetFocused(true) must bump")
38
39 // Re-applying the same focus state must not bump.
40 stable := item.Version()
41 item.SetFocused(true)
42 require.Equal(t, stable, item.Version(), "SetFocused with same value must not bump")
43
44 // Transition back must bump.
45 item.SetFocused(false)
46 require.Greater(t, item.Version(), stable, "SetFocused(false) must bump")
47 })
48
49 t.Run("SetMatch", func(t *testing.T) {
50 t.Parallel()
51 item := mkItem()
52
53 match := fuzzy.Match{
54 Str: "user",
55 Index: 0,
56 Score: 5,
57 MatchedIndexes: []int{0, 1, 2, 3},
58 }
59 before := item.Version()
60 item.SetMatch(match)
61 require.Greater(t, item.Version(), before, "SetMatch with new value must bump")
62
63 // Re-applying an equivalent match (same fields, equal slice
64 // contents) must not bump.
65 stable := item.Version()
66 same := fuzzy.Match{
67 Str: "user",
68 Index: 0,
69 Score: 5,
70 MatchedIndexes: []int{0, 1, 2, 3},
71 }
72 item.SetMatch(same)
73 require.Equal(t, stable, item.Version(), "SetMatch with equivalent value must not bump")
74
75 // A different match (different MatchedIndexes) must bump.
76 different := fuzzy.Match{
77 Str: "user",
78 Index: 0,
79 Score: 5,
80 MatchedIndexes: []int{0, 2},
81 }
82 item.SetMatch(different)
83 require.Greater(t, item.Version(), stable, "SetMatch with different indexes must bump")
84 })
85}