classify_test.go
package tui
import (
"testing"
tea "charm.land/bubbletea/v2"
"skraak/tools/calls"
)
func TestWrapText(t *testing.T) {
tests := []struct {
name string
input string
maxWidth int
want string
}{
{
name: "short text unchanged",
input: "hello world",
maxWidth: 20,
want: "hello world",
},
{
name: "wraps at word boundary",
input: "hello world this is a test",
maxWidth: 10,
want: "hello\nworld this\nis a test",
},
{
name: "handles multiple lines",
input: "hello world\nfoo bar baz",
maxWidth: 8,
want: "hello\nworld\nfoo bar\nbaz",
},
{
name: "empty string",
input: "",
maxWidth: 10,
want: "",
},
{
name: "single long word",
input: "abcdefghijklmnopqrstuvwxyz",
maxWidth: 10,
want: "abcdefghij\nklmnopqrstuvwxyz",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := wrapText(tt.input, tt.maxWidth)
if got != tt.want {
t.Errorf("wrapText() = %q, want %q", got, tt.want)
}
})
}
}
func TestKeyRank(t *testing.T) {
tests := []struct {
key string
want int
}{
{"a", 0},
{"z", 0},
{"m", 0},
{"A", 1},
{"Z", 1},
{"0", 2},
{"9", 2},
{"!", 3},
{"@", 3},
{"", 3},
// Note: keyRank checks first char only, so "ab" ranks as 'a' (lowercase = 0)
{"ab", 0},
}
for _, tt := range tests {
t.Run(tt.key, func(t *testing.T) {
if got := keyRank(tt.key); got != tt.want {
t.Errorf("keyRank(%q) = %d, want %d", tt.key, got, tt.want)
}
})
}
}
func TestBuildBindingsHelp(t *testing.T) {
tests := []struct {
name string
bindings []calls.KeyBinding
want string
}{
{
name: "empty bindings",
bindings: nil,
want: "",
},
{
name: "single binding species only",
bindings: []calls.KeyBinding{
{Key: "k", Species: "Kiwi"},
},
want: "k=Kiwi",
},
{
name: "single binding with calltype",
bindings: []calls.KeyBinding{
{Key: "k", Species: "Kiwi", CallType: "Male"},
},
want: "k=Kiwi/Male",
},
{
name: "multiple bindings sorted a-z then 0-9",
bindings: []calls.KeyBinding{
{Key: "9", Species: "Nine"},
{Key: "a", Species: "Alpha"},
{Key: "1", Species: "One"},
{Key: "b", Species: "Beta"},
},
want: "a=Alpha b=Beta 1=One 9=Nine",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := buildBindingsHelp(tt.bindings)
if got != tt.want {
t.Errorf("buildBindingsHelp() = %q, want %q", got, tt.want)
}
})
}
}
func TestHandleCommentKeyCode(t *testing.T) {
tests := []struct {
name string
initialText string
initialCursor int
keyCode rune
wantText string
wantCursor int
wantHandled bool
}{
{
name: "left arrow moves cursor",
initialText: "hello",
initialCursor: 3,
keyCode: tea.KeyLeft,
wantText: "hello",
wantCursor: 2,
wantHandled: true,
},
{
name: "left arrow at start does nothing",
initialText: "hello",
initialCursor: 0,
keyCode: tea.KeyLeft,
wantText: "hello",
wantCursor: 0,
wantHandled: true,
},
{
name: "right arrow moves cursor",
initialText: "hello",
initialCursor: 2,
keyCode: tea.KeyRight,
wantText: "hello",
wantCursor: 3,
wantHandled: true,
},
{
name: "right arrow at end does nothing",
initialText: "hello",
initialCursor: 5,
keyCode: tea.KeyRight,
wantText: "hello",
wantCursor: 5,
wantHandled: true,
},
{
name: "backspace deletes char before cursor",
initialText: "hello",
initialCursor: 3,
keyCode: tea.KeyBackspace,
wantText: "helo",
wantCursor: 2,
wantHandled: true,
},
{
name: "backspace at start does nothing",
initialText: "hello",
initialCursor: 0,
keyCode: tea.KeyBackspace,
wantText: "hello",
wantCursor: 0,
wantHandled: true,
},
{
name: "delete removes char at cursor",
initialText: "hello",
initialCursor: 2,
keyCode: tea.KeyDelete,
wantText: "helo",
wantCursor: 2,
wantHandled: true,
},
{
name: "delete at end does nothing",
initialText: "hello",
initialCursor: 5,
keyCode: tea.KeyDelete,
wantText: "hello",
wantCursor: 5,
wantHandled: true,
},
{
name: "space inserts space",
initialText: "hello",
initialCursor: 2,
keyCode: tea.KeySpace,
wantText: "he llo",
wantCursor: 3,
wantHandled: true,
},
{
name: "space respects max length",
initialText: string(make([]byte, maxCommentLength)),
initialCursor: 10,
keyCode: tea.KeySpace,
wantText: string(make([]byte, maxCommentLength)),
wantCursor: 10,
wantHandled: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := &Model{
commentText: tt.initialText,
commentCursor: tt.initialCursor,
}
key := tea.Key{Code: tt.keyCode}
gotHandled := m.handleCommentKeyCode(key)
if gotHandled != tt.wantHandled {
t.Errorf("handleCommentKeyCode() handled = %v, want %v", gotHandled, tt.wantHandled)
}
if m.commentText != tt.wantText {
t.Errorf("commentText = %q, want %q", m.commentText, tt.wantText)
}
if m.commentCursor != tt.wantCursor {
t.Errorf("commentCursor = %d, want %d", m.commentCursor, tt.wantCursor)
}
})
}
}
func TestHandleCommentCtrl(t *testing.T) {
tests := []struct {
name string
initialText string
initialCursor int
input string
wantText string
wantCursor int
wantHandled bool
}{
{
name: "ctrl+u clears text",
initialText: "hello world",
initialCursor: 5,
input: "ctrl+u",
wantText: "",
wantCursor: 0,
wantHandled: true,
},
{
name: "ctrl+a moves to start",
initialText: "hello",
initialCursor: 3,
input: "ctrl+a",
wantText: "hello",
wantCursor: 0,
wantHandled: true,
},
{
name: "ctrl+e moves to end",
initialText: "hello",
initialCursor: 2,
input: "ctrl+e",
wantText: "hello",
wantCursor: 5,
wantHandled: true,
},
{
name: "unknown ctrl combo not handled",
initialText: "hello",
initialCursor: 2,
input: "ctrl+x",
wantText: "hello",
wantCursor: 2,
wantHandled: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := &Model{
commentText: tt.initialText,
commentCursor: tt.initialCursor,
}
gotHandled := m.handleCommentCtrl(tt.input)
if gotHandled != tt.wantHandled {
t.Errorf("handleCommentCtrl() handled = %v, want %v", gotHandled, tt.wantHandled)
}
if m.commentText != tt.wantText {
t.Errorf("commentText = %q, want %q", m.commentText, tt.wantText)
}
if m.commentCursor != tt.wantCursor {
t.Errorf("commentCursor = %d, want %d", m.commentCursor, tt.wantCursor)
}
})
}
}
func TestMaxCommentLength(t *testing.T) {
if maxCommentLength != 140 {
t.Errorf("maxCommentLength = %d, want 140", maxCommentLength)
}
}
func TestMaxClipPrefixLength(t *testing.T) {
if maxClipPrefixLength != 64 {
t.Errorf("maxClipPrefixLength = %d, want 64", maxClipPrefixLength)
}
}