package tui import ( "testing" "github.com/lerko/nib/internal/db" ) func ptr[T any](v T) *T { return &v } func TestFilterEntities(t *testing.T) { entities := []*db.Entity{ {ID: "1", Body: "buy groceries", Tags: []string{"errand", "food"}}, {ID: "2", Body: "read chapter 5", Title: ptr("Go Book"), Tags: []string{"study"}}, {ID: "3", Body: "fix login bug", Description: ptr("auth middleware broken"), Tags: []string{"work", "urgent"}}, {ID: "4", Body: "empty tags"}, } tests := []struct { name string query string tags []string wantIDs []string }{ {"no filter returns all", "", nil, []string{"1", "2", "3", "4"}}, {"query matches body", "groceries", nil, []string{"1"}}, {"query case insensitive", "GROCERIES", nil, []string{"1"}}, {"query matches title", "go book", nil, []string{"2"}}, {"query matches description", "middleware", nil, []string{"3"}}, {"query no match", "nonexistent", nil, nil}, {"single tag filter", "", []string{"study"}, []string{"2"}}, {"multi tag filter all present", "", []string{"work", "urgent"}, []string{"3"}}, {"multi tag filter partial miss", "", []string{"work", "food"}, nil}, {"tag filter no match", "", []string{"missing"}, nil}, {"query plus tag", "fix", []string{"work"}, []string{"3"}}, {"query plus tag mismatch", "groceries", []string{"work"}, nil}, {"entity with nil title and description", "empty", nil, []string{"4"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := filterEntities(entities, tt.query, tt.tags) gotIDs := make([]string, len(got)) for i, e := range got { gotIDs[i] = e.ID } if len(tt.wantIDs) == 0 && len(gotIDs) == 0 { return } if len(gotIDs) != len(tt.wantIDs) { t.Fatalf("got %v, want %v", gotIDs, tt.wantIDs) } for i := range gotIDs { if gotIDs[i] != tt.wantIDs[i] { t.Fatalf("got %v, want %v", gotIDs, tt.wantIDs) } } }) } } func TestMatchesSearch_NilFields(t *testing.T) { e := &db.Entity{Body: "hello world"} if !matchesSearch(e, "hello", nil) { t.Fatal("should match body") } if matchesSearch(e, "title", nil) { t.Fatal("should not match nil title") } }