1package tui
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 tea "charm.land/bubbletea/v2"
9 "github.com/floatpane/matcha/config"
10 "github.com/floatpane/matcha/theme"
11)
12
13func TestSettingsNavigationWraps(t *testing.T) {
14 settings := NewSettings(&config.Config{
15 Accounts: []config.Account{
16 {ID: "account-1", Email: "one@example.com"},
17 {ID: "account-2", Email: "two@example.com"},
18 },
19 MailingLists: []config.MailingList{
20 {Name: "List One"},
21 {Name: "List Two"},
22 },
23 })
24
25 t.Run("menu", func(t *testing.T) {
26 settings.menuCursor = 0
27 model, _ := settings.updateMenu(tea.KeyPressMsg{Code: tea.KeyUp})
28 settings = model.(*Settings)
29 if settings.menuCursor != int(CategoryPlugins) {
30 t.Fatalf("up from first menu item should wrap to last, got %d", settings.menuCursor)
31 }
32
33 model, _ = settings.updateMenu(tea.KeyPressMsg{Code: tea.KeyDown})
34 settings = model.(*Settings)
35 if settings.menuCursor != 0 {
36 t.Fatalf("down from last menu item should wrap to first, got %d", settings.menuCursor)
37 }
38 })
39
40 t.Run("general", func(t *testing.T) {
41 settings.generalCursor = 0
42 last := len(settings.buildGeneralOptions()) - 1
43
44 model, _ := settings.updateGeneral(tea.KeyPressMsg{Code: tea.KeyUp})
45 settings = model.(*Settings)
46 if settings.generalCursor != last {
47 t.Fatalf("up from first general item should wrap to last, got %d", settings.generalCursor)
48 }
49
50 model, _ = settings.updateGeneral(tea.KeyPressMsg{Code: tea.KeyDown})
51 settings = model.(*Settings)
52 if settings.generalCursor != 0 {
53 t.Fatalf("down from last general item should wrap to first, got %d", settings.generalCursor)
54 }
55 })
56
57 t.Run("accounts", func(t *testing.T) {
58 settings.accountsCursor = 0
59 last := len(settings.cfg.Accounts)
60
61 model, _ := settings.updateAccounts(tea.KeyPressMsg{Code: tea.KeyUp})
62 settings = model.(*Settings)
63 if settings.accountsCursor != last {
64 t.Fatalf("up from first account item should wrap to add account, got %d", settings.accountsCursor)
65 }
66
67 model, _ = settings.updateAccounts(tea.KeyPressMsg{Code: tea.KeyDown})
68 settings = model.(*Settings)
69 if settings.accountsCursor != 0 {
70 t.Fatalf("down from add account should wrap to first, got %d", settings.accountsCursor)
71 }
72 })
73
74 t.Run("mailing lists", func(t *testing.T) {
75 settings.listsCursor = 0
76 last := len(settings.cfg.MailingLists)
77
78 model, _ := settings.updateMailingLists(tea.KeyPressMsg{Code: tea.KeyUp})
79 settings = model.(*Settings)
80 if settings.listsCursor != last {
81 t.Fatalf("up from first mailing list should wrap to add list, got %d", settings.listsCursor)
82 }
83
84 model, _ = settings.updateMailingLists(tea.KeyPressMsg{Code: tea.KeyDown})
85 settings = model.(*Settings)
86 if settings.listsCursor != 0 {
87 t.Fatalf("down from add list should wrap to first, got %d", settings.listsCursor)
88 }
89 })
90
91 t.Run("theme", func(t *testing.T) {
92 themes := theme.AllThemes()
93 if len(themes) < 2 {
94 t.Skip("need at least two themes to test wrap-around")
95 }
96
97 settings.themeCursor = 0
98 model, _ := settings.updateTheme(tea.KeyPressMsg{Code: tea.KeyUp})
99 settings = model.(*Settings)
100 if settings.themeCursor != len(themes)-1 {
101 t.Fatalf("up from first theme should wrap to last, got %d", settings.themeCursor)
102 }
103
104 model, _ = settings.updateTheme(tea.KeyPressMsg{Code: tea.KeyDown})
105 settings = model.(*Settings)
106 if settings.themeCursor != 0 {
107 t.Fatalf("down from last theme should wrap to first, got %d", settings.themeCursor)
108 }
109 })
110}
111
112func TestFilePickerNavigationWraps(t *testing.T) {
113 dir := t.TempDir()
114 if err := os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a"), 0o600); err != nil {
115 t.Fatal(err)
116 }
117 if err := os.WriteFile(filepath.Join(dir, "b.txt"), []byte("b"), 0o600); err != nil {
118 t.Fatal(err)
119 }
120
121 picker := NewFilePicker(dir)
122 if len(picker.items) != 2 {
123 t.Fatalf("expected two picker items, got %d", len(picker.items))
124 }
125
126 model, _ := picker.Update(tea.KeyPressMsg{Code: tea.KeyUp})
127 picker = model.(*FilePicker)
128 if picker.cursor != len(picker.items)-1 {
129 t.Fatalf("up from first file should wrap to last, got %d", picker.cursor)
130 }
131
132 model, _ = picker.Update(tea.KeyPressMsg{Code: tea.KeyDown})
133 picker = model.(*FilePicker)
134 if picker.cursor != 0 {
135 t.Fatalf("down from last file should wrap to first, got %d", picker.cursor)
136 }
137}
138
139func TestFilePickerNavigationEmptyDirectoryDoesNotWrap(t *testing.T) {
140 picker := NewFilePicker(t.TempDir())
141 if len(picker.items) != 0 {
142 t.Fatalf("expected empty picker, got %d items", len(picker.items))
143 }
144
145 model, _ := picker.Update(tea.KeyPressMsg{Code: tea.KeyUp})
146 picker = model.(*FilePicker)
147 if picker.cursor != 0 {
148 t.Fatalf("empty picker cursor should remain zero after up, got %d", picker.cursor)
149 }
150
151 model, _ = picker.Update(tea.KeyPressMsg{Code: tea.KeyDown})
152 picker = model.(*FilePicker)
153 if picker.cursor != 0 {
154 t.Fatalf("empty picker cursor should remain zero after down, got %d", picker.cursor)
155 }
156}