11package ui
22
33import (
4+ "fmt"
45 "testing"
56)
67
@@ -52,21 +53,21 @@ func TestApplyFilters(t *testing.T) {
5253 }
5354
5455 m := InitialModel ("test.log" , lines , nil )
55-
56+
5657 // Test 1: No filters
5758 m .applyFilters (true )
5859 if len (m .filteredLines ) != 4 {
5960 t .Errorf ("Expected 4 lines, got %d" , len (m .filteredLines ))
6061 }
6162
62- // Test 2: Filter Text
63+ // Test 2: Filter Text includes matching lines with surrounding context
6364 m .filterText = "Error"
6465 m .applyFilters (true )
65- if len (m .filteredLines ) != 1 {
66- t .Errorf ("Expected 1 error line , got %d" , len (m .filteredLines ))
66+ if len (m .filteredLines ) != 4 {
67+ t .Errorf ("Expected 4 context lines , got %d" , len (m .filteredLines ))
6768 }
68- if len (m .filteredLines ) > 0 && m .filteredLines [0 ] != lines [2 ] {
69- t .Errorf ("Expected line to be '%s', got '%s'" , lines [2 ], m .filteredLines [0 ])
69+ if len (m .filteredLines ) > 2 && m .filteredLines [2 ] != lines [2 ] {
70+ t .Errorf ("Expected line to be '%s', got '%s'" , lines [2 ], m .filteredLines [2 ])
7071 }
7172
7273 // Test 3: Level Filtering (Toggle off INFO)
@@ -79,6 +80,54 @@ func TestApplyFilters(t *testing.T) {
7980 }
8081}
8182
83+ func TestApplyFiltersAddsKeywordContext (t * testing.T ) {
84+ lines := make ([]string , 35 )
85+ for i := range lines {
86+ lines [i ] = fmt .Sprintf ("2023-01-01 10:00:%02d INFO line %02d" , i , i )
87+ }
88+ lines [20 ] = "2023-01-01 10:00:20 ERROR target keyword"
89+
90+ m := InitialModel ("test.log" , lines , nil )
91+ m .filterText = "keyword"
92+ m .applyFilters (true )
93+
94+ if len (m .filteredLines ) != 21 {
95+ t .Fatalf ("expected 21 lines with context, got %d" , len (m .filteredLines ))
96+ }
97+ if m .filteredLines [0 ] != lines [10 ] {
98+ t .Fatalf ("expected context to start at line 10, got %q" , m .filteredLines [0 ])
99+ }
100+ if m .filteredLines [10 ] != lines [20 ] {
101+ t .Fatalf ("expected match at context index 10, got %q" , m .filteredLines [10 ])
102+ }
103+ if m .filteredLines [20 ] != lines [30 ] {
104+ t .Fatalf ("expected context to end at line 30, got %q" , m .filteredLines [20 ])
105+ }
106+ }
107+
108+ func TestApplyFiltersMergesOverlappingKeywordContext (t * testing.T ) {
109+ lines := make ([]string , 40 )
110+ for i := range lines {
111+ lines [i ] = fmt .Sprintf ("2023-01-01 10:00:%02d INFO line %02d" , i , i )
112+ }
113+ lines [12 ] = "2023-01-01 10:00:12 ERROR target keyword"
114+ lines [18 ] = "2023-01-01 10:00:18 ERROR another keyword"
115+
116+ m := InitialModel ("test.log" , lines , nil )
117+ m .filterText = "keyword"
118+ m .applyFilters (true )
119+
120+ if len (m .filteredLines ) != 27 {
121+ t .Fatalf ("expected merged context range without duplicates, got %d lines" , len (m .filteredLines ))
122+ }
123+ if m .filteredLines [0 ] != lines [2 ] {
124+ t .Fatalf ("expected merged context to start at line 2, got %q" , m .filteredLines [0 ])
125+ }
126+ if m .filteredLines [26 ] != lines [28 ] {
127+ t .Fatalf ("expected merged context to end at line 28, got %q" , m .filteredLines [26 ])
128+ }
129+ }
130+
82131func TestResolvePos (t * testing.T ) {
83132 // Setup a model with forced width
84133 lines := []string {
0 commit comments