package helpers_test import ( "testing" "time" "github.com/jfraeys/fetch_ml/internal/api/helpers" ) func TestDBContext(t *testing.T) { ctx, cancel := helpers.DBContext(3 * time.Second) defer cancel() deadline, ok := ctx.Deadline() if !ok { t.Error("expected deadline to be set") } // Deadline should be within a reasonable time window now := time.Now() if deadline.Before(now) { t.Error("deadline is in the past") } if deadline.After(now.Add(4 * time.Second)) { t.Error("deadline is too far in the future") } // Context should not be cancelled select { case <-ctx.Done(): t.Error("context should not be cancelled yet") default: // Good } } func TestDBContextShort(t *testing.T) { ctx, cancel := helpers.DBContextShort() defer cancel() deadline, ok := ctx.Deadline() if !ok { t.Error("expected deadline to be set") } now := time.Now() diff := deadline.Sub(now) // Should be around 3 seconds if diff < 2*time.Second || diff > 4*time.Second { t.Errorf("expected deadline ~3s, got %v", diff) } } func TestDBContextMedium(t *testing.T) { ctx, cancel := helpers.DBContextMedium() defer cancel() deadline, ok := ctx.Deadline() if !ok { t.Error("expected deadline to be set") } now := time.Now() diff := deadline.Sub(now) // Should be around 5 seconds if diff < 4*time.Second || diff > 6*time.Second { t.Errorf("expected deadline ~5s, got %v", diff) } } func TestDBContextLong(t *testing.T) { ctx, cancel := helpers.DBContextLong() defer cancel() deadline, ok := ctx.Deadline() if !ok { t.Error("expected deadline to be set") } now := time.Now() diff := deadline.Sub(now) // Should be around 10 seconds if diff < 9*time.Second || diff > 11*time.Second { t.Errorf("expected deadline ~10s, got %v", diff) } } func TestDBContextCancellation(t *testing.T) { ctx, cancel := helpers.DBContextShort() // Cancel immediately cancel() // Context should be cancelled select { case <-ctx.Done(): // Good - context was cancelled default: t.Error("context should be cancelled after calling cancel()") } // Check error if ctx.Err() == nil { t.Error("expected non-nil error after cancellation") } } func TestStringSliceContains(t *testing.T) { tests := []struct { name string slice []string item string want bool }{ { name: "contains", slice: []string{"a", "b", "c"}, item: "b", want: true, }, { name: "not contains", slice: []string{"a", "b", "c"}, item: "d", want: false, }, { name: "empty slice", slice: []string{}, item: "a", want: false, }, { name: "nil slice", slice: nil, item: "a", want: false, }, { name: "empty string item", slice: []string{"a", "", "c"}, item: "", want: true, }, { name: "case sensitive", slice: []string{"Apple", "Banana"}, item: "apple", want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.StringSliceContains(tt.slice, tt.item) if got != tt.want { t.Errorf("StringSliceContains() = %v, want %v", got, tt.want) } }) } } func TestStringSliceFilter(t *testing.T) { tests := []struct { name string slice []string predicate func(string) bool want []string }{ { name: "filter by prefix", slice: []string{"apple", "banana", "apricot", "cherry"}, predicate: func(s string) bool { return len(s) > 0 && s[0] == 'a' }, want: []string{"apple", "apricot"}, }, { name: "filter empty strings", slice: []string{"a", "", "b", "", "c"}, predicate: func(s string) bool { return s != "" }, want: []string{"a", "b", "c"}, }, { name: "all match", slice: []string{"a", "b", "c"}, predicate: func(s string) bool { return true }, want: []string{"a", "b", "c"}, }, { name: "none match", slice: []string{"a", "b", "c"}, predicate: func(s string) bool { return false }, want: []string{}, }, { name: "empty slice", slice: []string{}, predicate: func(s string) bool { return true }, want: []string{}, }, { name: "nil slice", slice: nil, predicate: func(s string) bool { return true }, want: []string{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.StringSliceFilter(tt.slice, tt.predicate) if len(got) != len(tt.want) { t.Errorf("StringSliceFilter() returned %d items, want %d", len(got), len(tt.want)) return } for i := range got { if got[i] != tt.want[i] { t.Errorf("StringSliceFilter()[%d] = %q, want %q", i, got[i], tt.want[i]) } } }) } }