diff --git a/internal/anime/recommendations_cache_test.go b/internal/anime/recommendations_cache_test.go index 737576d8..7953663d 100644 --- a/internal/anime/recommendations_cache_test.go +++ b/internal/anime/recommendations_cache_test.go @@ -7,6 +7,7 @@ import ( "time" "mal/integrations/jikan" + "mal/internal/anime/recommendations" "mal/internal/domain" ) @@ -37,6 +38,46 @@ func TestGetTopPicksForYouReturnsEmptyOnCacheMissAndRefreshesInBackground(t *tes } } +func TestTopPickAndTopPicksShareCache(t *testing.T) { + refreshed := make(chan struct{}, 1) + limits := make(chan int, 1) + svc := NewAnimeService(nil, nil) + svc.computeTopPicks = func(_ context.Context, _ string, limit int) (domain.CatalogSectionData, error) { + limits <- limit + animes := make([]domain.Anime, recommendations.TopPickLimit+1) + for i := range animes { + animes[i].MalID = i + 1 + } + refreshed <- struct{}{} + return domain.CatalogSectionData{Animes: animes}, nil + } + + if _, err := svc.GetTopPickForYou(context.Background(), "user-1"); err != nil { + t.Fatalf("GetTopPickForYou cache miss: %v", err) + } + waitForRefresh(t, refreshed) + + carousel, err := svc.GetTopPickForYou(context.Background(), "user-1") + if err != nil { + t.Fatalf("GetTopPickForYou cache hit: %v", err) + } + if len(carousel.Animes) != recommendations.TopPickLimit { + t.Fatalf("carousel animes = %d, want %d", len(carousel.Animes), recommendations.TopPickLimit) + } + + all, err := svc.GetTopPicksForYou(context.Background(), "user-1") + if err != nil { + t.Fatalf("GetTopPicksForYou shared cache: %v", err) + } + if len(all.Animes) != recommendations.TopPickLimit+1 { + t.Fatalf("all animes = %d, want %d", len(all.Animes), recommendations.TopPickLimit+1) + } + + if limit := <-limits; limit != recommendations.TopPicksLimit { + t.Fatalf("computed limit = %d, want %d", limit, recommendations.TopPicksLimit) + } +} + func TestGetTopPicksForYouReturnsStaleDataWhenRefreshFails(t *testing.T) { svc := NewAnimeService(nil, nil) svc.topPicksCacheTTL = time.Nanosecond