Skip to content

Commit f41125f

Browse files
committed
test
1 parent ef0e5ac commit f41125f

File tree

1 file changed

+115
-144
lines changed

1 file changed

+115
-144
lines changed

internal/filterable_viewport/filterable_viewport_test.go

+115-144
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import (
1212
)
1313

1414
var (
15-
filterKeyMsg = tea.KeyPressMsg{Code: '/', Text: "/"}
16-
enterKeyMsg = tea.KeyPressMsg{Code: tea.KeyEnter, Text: "enter"}
17-
clearKeyMsg = tea.KeyPressMsg{Code: tea.KeyEscape, Text: "esc"}
15+
focusFilterKeyMsg = tea.KeyPressMsg{Code: '/', Text: "/"}
16+
focusRegexFilterKeyMsg = tea.KeyPressMsg{Code: 'r', Text: "r"}
17+
enterKeyMsg = tea.KeyPressMsg{Code: tea.KeyEnter, Text: "enter"}
18+
clearKeyMsg = tea.KeyPressMsg{Code: tea.KeyEscape, Text: "esc"}
19+
wrapKeyMsg = tea.KeyPressMsg{Code: 'w', Text: "w"}
1820
)
1921

2022
func makeKeyPressMsg(key rune) tea.Msg {
@@ -81,7 +83,7 @@ func newFilterableViewport() FilterableViewport[TestItem] {
8183
)
8284
}
8385

84-
func getLines(fv FilterableViewport[TestItem]) []string {
86+
func getTestLines(fv FilterableViewport[TestItem]) []string {
8587
var lines []string
8688
for _, line := range strings.Split(fv.View(), "\n") {
8789
if strings.TrimSpace(line) != "" {
@@ -91,6 +93,18 @@ func getLines(fv FilterableViewport[TestItem]) []string {
9193
return lines
9294
}
9395

96+
func applyTestFilter(fv FilterableViewport[TestItem], km tea.KeyPressMsg, s string) FilterableViewport[TestItem] {
97+
fv, _ = fv.Update(km)
98+
if !fv.Filter.Focused() {
99+
panic("filter should be focused")
100+
}
101+
for _, r := range s {
102+
fv, _ = fv.Update(makeKeyPressMsg(r))
103+
}
104+
fv, _ = fv.Update(enterKeyMsg)
105+
return fv
106+
}
107+
94108
func TestNewFilterableViewport(t *testing.T) {
95109
fv := newFilterableViewport()
96110
fv.SetAllRows([]TestItem{
@@ -117,6 +131,9 @@ func TestNewFilterableViewport(t *testing.T) {
117131
if fv.Filter.Focused() {
118132
t.Error("filter should not be focused")
119133
}
134+
if fv.focused {
135+
t.Error("viewport should start unfocused")
136+
}
120137
}
121138

122139
func TestFilterableViewport_FilterNoContext(t *testing.T) {
@@ -127,18 +144,10 @@ func TestFilterableViewport_FilterNoContext(t *testing.T) {
127144
{content: "another item"},
128145
})
129146

130-
// apply filter
131-
fv, _ = fv.Update(filterKeyMsg)
132-
if !fv.Filter.Focused() {
133-
t.Errorf("filter should be focused after %s key", filterKeyMsg.String())
134-
}
135-
for _, r := range "one" {
136-
fv, _ = fv.Update(makeKeyPressMsg(r))
137-
}
138-
fv, _ = fv.Update(enterKeyMsg)
147+
fv = applyTestFilter(fv, focusFilterKeyMsg, "one")
139148

140149
// check filter correctly identifies lines in view
141-
lines := getLines(fv)
150+
lines := getTestLines(fv)
142151
if lines[0] != "Test Header \x1b[48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m\x1b[38;2;0;0;0;48;2;225;225;225mfilter: \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225mone\x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m(matches only) \x1b[m\x1b[m" {
143152
t.Errorf("unexpected header with filter\n%q", fv.View())
144153
}
@@ -157,7 +166,7 @@ func TestFilterableViewport_FilterNoContext(t *testing.T) {
157166
{content: "another item"},
158167
}
159168
fv.SetAllRows(newItems)
160-
lines = getLines(fv)
169+
lines = getTestLines(fv)
161170
if len(lines) != 3 { // 1 for header
162171
t.Errorf("expected 2 visible item, got %d", len(lines)-1)
163172
}
@@ -167,7 +176,7 @@ func TestFilterableViewport_FilterNoContext(t *testing.T) {
167176

168177
// clear filter
169178
fv, _ = fv.Update(clearKeyMsg)
170-
lines = getLines(fv)
179+
lines = getTestLines(fv)
171180
if lines[0] != "Test Header '/' or 'r' to filter" {
172181
t.Errorf("unexpected header with filter\n%q", fv.View())
173182
}
@@ -185,14 +194,7 @@ func TestFilterableViewport_FilterShowContext(t *testing.T) {
185194
})
186195

187196
// apply filter
188-
fv, _ = fv.Update(filterKeyMsg)
189-
if !fv.Filter.Focused() {
190-
t.Errorf("filter should be focused after %s key", filterKeyMsg.String())
191-
}
192-
for _, r := range "one" {
193-
fv, _ = fv.Update(makeKeyPressMsg(r))
194-
}
195-
fv, _ = fv.Update(enterKeyMsg)
197+
fv = applyTestFilter(fv, focusFilterKeyMsg, "one")
196198

197199
// check show context
198200
if fv.Filter.ShowContext {
@@ -203,7 +205,7 @@ func TestFilterableViewport_FilterShowContext(t *testing.T) {
203205
t.Error("contextual filtering should be enabled")
204206
}
205207

206-
lines := getLines(fv)
208+
lines := getTestLines(fv)
207209
if lines[0] != "Test Header \x1b[48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m\x1b[38;2;0;0;0;48;2;225;225;225mfilter: \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225mone\x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m(1/1, n/N to cycle) \x1b[m\x1b[m" {
208210
t.Errorf("unexpected header with show context filter\n%q", fv.View())
209211
}
@@ -219,7 +221,7 @@ func TestFilterableViewport_FilterShowContext(t *testing.T) {
219221
{content: "item two"},
220222
{content: "another item"},
221223
})
222-
lines = getLines(fv)
224+
lines = getTestLines(fv)
223225
if lines[0] != "Test Header \x1b[48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m\x1b[38;2;0;0;0;48;2;225;225;225mfilter: \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225mone\x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m(1/2, n/N to cycle) \x1b[m\x1b[m" {
224226
t.Errorf("unexpected header with show context filter\n%q", fv.View())
225227
}
@@ -232,14 +234,14 @@ func TestFilterableViewport_FilterShowContext(t *testing.T) {
232234
if fv.Filter.ShowContext {
233235
t.Error("contextual filtering should be disabled")
234236
}
235-
lines = getLines(fv)
237+
lines = getTestLines(fv)
236238
if lines[0] != "Test Header \x1b[48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m\x1b[38;2;0;0;0;48;2;225;225;225mfilter: \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225mone\x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m(matches only) \x1b[m\x1b[m" {
237239
t.Errorf("unexpected header with filter\n%q", fv.View())
238240
}
239241

240242
// clear filter
241243
fv, _ = fv.Update(clearKeyMsg)
242-
lines = getLines(fv)
244+
lines = getTestLines(fv)
243245
if lines[0] != "Test Header '/' or 'r' to filter" {
244246
t.Errorf("unexpected header with filter\n%q", fv.View())
245247
}
@@ -248,119 +250,88 @@ func TestFilterableViewport_FilterShowContext(t *testing.T) {
248250
}
249251
}
250252

251-
// TODO focus filterable viewport
252-
253-
// TODO regex filter
254-
255-
// TODO clear filter
256-
257-
// TODO filter filterable viewport
258-
259-
//func TestFilterableViewport_RegexFilter(t *testing.T) {
260-
// fv := newFilterableViewport()
261-
//
262-
// // Activate regex filter
263-
// msg := tea.KeyMsg{Type: tea.KeyCtrl, Runes: []rune("/")}
264-
// fv, _ = fv.Update(msg)
265-
// if !fv.Filter.IsRegex() {
266-
// t.Error("filter should be in regex mode")
267-
// }
268-
//
269-
// // Type regex pattern
270-
// msg = tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("^item")}
271-
// fv, _ = fv.Update(msg)
272-
//
273-
// // Apply filter
274-
// msg = tea.KeyMsg{Type: tea.KeyEnter}
275-
// fv, _ = fv.Update(msg)
276-
//
277-
// // Verify only items starting with "item" are visible
278-
// content := fv.viewport.GetContent()
279-
// if len(content) != 2 {
280-
// t.Errorf("expected 2 visible items, got %d", len(content))
281-
// }
282-
// if content[0].String() != "item one" {
283-
// t.Errorf("expected 'item one', got '%s'", content[0].String())
284-
// }
285-
// if content[1].String() != "item two" {
286-
// t.Errorf("expected 'item two', got '%s'", content[1].String())
287-
// }
288-
//}
289-
//
290-
//func TestFilterableViewport_ClearFilter(t *testing.T) {
291-
// fv := newFilterableViewport()
292-
//
293-
// // Set up a filter first
294-
// msg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("/")}
295-
// fv, _ = fv.Update(msg)
296-
// msg = tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("one")}
297-
// fv, _ = fv.Update(msg)
298-
// msg = tea.KeyMsg{Type: tea.KeyEnter}
299-
// fv, _ = fv.Update(msg)
300-
//
301-
// // Clear the filter
302-
// msg = tea.KeyMsg{Type: tea.KeyEsc}
303-
// fv, _ = fv.Update(msg)
304-
//
305-
// // Verify all items are visible again
306-
// if len(fv.viewport.GetContent()) != 3 {
307-
// t.Errorf("expected 3 visible items after clear, got %d", len(fv.viewport.GetContent()))
308-
// }
309-
// if fv.Filter.Value() != "" {
310-
// t.Errorf("expected empty filter value, got '%s'", fv.Filter.Value())
311-
// }
312-
//}
313-
//
314-
//func TestFilterableViewport_ToggleWrap(t *testing.T) {
315-
// fv := newFilterableViewport()
316-
//
317-
// initialWrap := fv.viewport.GetWrapText()
318-
//
319-
// // Toggle wrap
320-
// msg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("w")}
321-
// fv, _ = fv.Update(msg)
322-
//
323-
// if fv.viewport.GetWrapText() == initialWrap {
324-
// t.Error("wrap text should have toggled")
325-
// }
326-
//}
327-
//
328-
//func TestFilterableViewport_Focus(t *testing.T) {
329-
// fv := newFilterableViewport()
330-
//
331-
// // Test unfocused state
332-
// if fv.focused {
333-
// t.Error("viewport should start unfocused")
334-
// }
335-
//
336-
// // Focus the viewport
337-
// fv.SetFocus(true)
338-
// if !fv.focused {
339-
// t.Error("viewport should be focused after SetFocus(true)")
340-
// }
341-
//
342-
// // Verify styles are updated
343-
// if fv.viewport.SelectedItemStyle != fv.styles.Inverse {
344-
// t.Error("focused viewport should have inverse selection style")
345-
// }
346-
//}
347-
//
348-
//func TestFilterableViewport_Selection(t *testing.T) {
349-
// fv := newFilterableViewport()
350-
//
351-
// // Test initial selection
352-
// selection := fv.GetSelection()
353-
// if selection == nil {
354-
// t.Fatal("initial selection should not be nil")
355-
// }
356-
// if selection.Render() != "item one" {
357-
// t.Errorf("expected initial selection 'item one', got '%s'", selection.Render())
358-
// }
359-
//
360-
// // Change selection
361-
// fv.SetSelectedContentIdx(1)
362-
// selection = fv.GetSelection()
363-
// if selection.Render() != "item two" {
364-
// t.Errorf("expected selection 'item two', got '%s'", selection.Render())
365-
// }
366-
//}
253+
func TestFilterableViewport_Focus(t *testing.T) {
254+
fv := newFilterableViewport()
255+
fv.SetAllRows([]TestItem{
256+
{content: "item one"},
257+
})
258+
259+
fv.SetFocus(true)
260+
if !fv.focused {
261+
t.Error("viewport should be focused after SetFocus(true)")
262+
}
263+
264+
// header should be styled when focused
265+
lines := getTestLines(fv)
266+
if lines[0] != "\x1b[38;2;0;0;0;46mTest Header\x1b[m '/' or 'r' to filter" {
267+
t.Errorf("unexpected header\n%q", fv.View())
268+
}
269+
270+
// selection should be styled when focused
271+
if lines[1] != "\x1b[38;2;0;0;0;48;2;255;255;255mitem one\x1b[m" {
272+
t.Errorf("unexpected selection\n%q", fv.View())
273+
}
274+
275+
// apply filter
276+
fv = applyTestFilter(fv, focusFilterKeyMsg, "one")
277+
278+
// selection should have styled filtered line
279+
lines = getTestLines(fv)
280+
if lines[1] != "\x1b[38;2;0;0;0;48;2;255;255;255mitem \x1b[m\x1b[38;2;255;255;255;48;2;0;0;0mone\x1b[m" {
281+
t.Errorf("unexpected selection\n%q", fv.View())
282+
}
283+
}
284+
285+
func TestFilterableViewport_Clear(t *testing.T) {
286+
fv := newFilterableViewport()
287+
fv.SetAllRows([]TestItem{
288+
{content: "item one"},
289+
{content: "item two"},
290+
})
291+
292+
// apply filter, focus filter, and clear
293+
fv = applyTestFilter(fv, focusFilterKeyMsg, "one")
294+
fv, _ = fv.Update(focusFilterKeyMsg)
295+
fv, _ = fv.Update(clearKeyMsg)
296+
lines := getTestLines(fv)
297+
if lines[0] != "Test Header '/' or 'r' to filter" {
298+
t.Errorf("unexpected header\n%q", fv.View())
299+
}
300+
301+
// apply filter and clear
302+
fv = applyTestFilter(fv, focusFilterKeyMsg, "one")
303+
fv, _ = fv.Update(clearKeyMsg)
304+
lines = getTestLines(fv)
305+
if lines[0] != "Test Header '/' or 'r' to filter" {
306+
t.Errorf("unexpected header\n%q", fv.View())
307+
}
308+
}
309+
310+
func TestFilterableViewport_ToggleWrap(t *testing.T) {
311+
fv := newFilterableViewport()
312+
313+
initialWrap := fv.viewport.GetWrapText()
314+
315+
fv, _ = fv.Update(wrapKeyMsg)
316+
317+
if fv.viewport.GetWrapText() == initialWrap {
318+
t.Error("wrap text should have toggled")
319+
}
320+
}
321+
322+
func TestFilterableViewport_FilterRegex(t *testing.T) {
323+
fv := newFilterableViewport()
324+
fv.SetAllRows([]TestItem{
325+
{content: "item one"},
326+
{content: "item two"},
327+
})
328+
329+
fv = applyTestFilter(fv, focusRegexFilterKeyMsg, "i.*m")
330+
lines := getTestLines(fv)
331+
if lines[0] != "Test Header \x1b[48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m\x1b[38;2;0;0;0;48;2;225;225;225mregex filter: \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225mi.*m\x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m \x1b[m\x1b[38;2;0;0;0;48;2;225;225;225m(matches only) \x1b[m\x1b[m" {
332+
t.Errorf("unexpected header with regex filter\n%q", fv.View())
333+
}
334+
if len(lines) != 3 { // 1 for header
335+
t.Errorf("expected 2 visible item, got %d", len(lines)-1)
336+
}
337+
}

0 commit comments

Comments
 (0)