package cpweeklyrank_test import ( "context" "errors" "strconv" "testing" "time" "hyapp/pkg/appcode" domain "hyapp/services/activity-service/internal/domain/cpweeklyrank" service "hyapp/services/activity-service/internal/service/cpweeklyrank" ) func TestGetStatusReturnsPreviousEntriesFromPreviousWeek(t *testing.T) { now := time.Date(2026, 6, 24, 12, 0, 0, 0, time.UTC) currentStart, currentEnd := service.WeekWindow(now) previousStart, previousEnd := service.PreviousWeekWindow(now) rankSource := &fakeCPWeeklyRankSource{ windows: map[[2]int64][]domain.Entry{ {currentStart.UnixMilli(), currentEnd.UnixMilli()}: cpWeeklyRankEntries(2, 1000), {previousStart.UnixMilli(), previousEnd.UnixMilli()}: cpWeeklyRankEntries(5, 5000), }, } svc := service.New(&fakeCPWeeklyRankRepository{config: domain.Config{ AppCode: "lalu", ActivityCode: domain.ActivityCode, Enabled: true, RelationType: "cp", TopCount: 10, }}, rankSource, nil) svc.SetClock(func() time.Time { return now }) status, err := svc.GetStatus(appcode.WithContext(context.Background(), "lalu"), 1, 0) if err != nil { t.Fatalf("GetStatus failed: %v", err) } if len(status.Entries) != 1 { t.Fatalf("current entries mismatch: %+v", status.Entries) } if len(status.PreviousEntries) != 3 { t.Fatalf("previous entries should be limited to 3, got %+v", status.PreviousEntries) } if status.PreviousEntries[0].UserA.Username != "left-1" || status.PreviousEntries[0].UserA.Avatar != "https://avatar/left-1.png" || status.PreviousEntries[0].UserB.Username != "right-1" || status.PreviousEntries[0].UserB.Avatar != "https://avatar/right-1.png" || status.PreviousEntries[0].Score != 5001 { t.Fatalf("previous entry should keep user snapshots and intimacy score: %+v", status.PreviousEntries[0]) } if len(rankSource.calls) != 2 { t.Fatalf("rank source call count mismatch: %+v", rankSource.calls) } if rankSource.calls[0].startMS != currentStart.UnixMilli() || rankSource.calls[0].endMS != currentEnd.UnixMilli() || rankSource.calls[0].limit != 1 { t.Fatalf("current window call mismatch: %+v", rankSource.calls[0]) } if rankSource.calls[1].startMS != previousStart.UnixMilli() || rankSource.calls[1].endMS != previousEnd.UnixMilli() || rankSource.calls[1].limit != 3 { t.Fatalf("previous window call mismatch: %+v", rankSource.calls[1]) } } type fakeCPWeeklyRankRepository struct { config domain.Config } func (r *fakeCPWeeklyRankRepository) GetCPWeeklyRankConfig(context.Context) (domain.Config, bool, error) { return r.config, true, nil } func (r *fakeCPWeeklyRankRepository) UpdateCPWeeklyRankConfig(context.Context, domain.Config, int64) (domain.Config, error) { return domain.Config{}, errors.New("not implemented") } func (r *fakeCPWeeklyRankRepository) ListCPWeeklyRankSettlements(context.Context, int64, int64) ([]domain.Settlement, error) { return nil, errors.New("not implemented") } func (r *fakeCPWeeklyRankRepository) PrepareCPWeeklyRankSettlements(context.Context, domain.Config, []domain.Entry, int64, int64, int64) ([]domain.Settlement, error) { return nil, errors.New("not implemented") } func (r *fakeCPWeeklyRankRepository) ListPendingCPWeeklyRankSettlements(context.Context, int64, int64, int) ([]domain.Settlement, error) { return nil, errors.New("not implemented") } func (r *fakeCPWeeklyRankRepository) MarkCPWeeklyRankSettlementGranted(context.Context, string, string, int64) error { return errors.New("not implemented") } func (r *fakeCPWeeklyRankRepository) MarkCPWeeklyRankSettlementFailed(context.Context, string, string, int64) error { return errors.New("not implemented") } type fakeCPWeeklyRankSource struct { calls []fakeCPWeeklyRankSourceCall windows map[[2]int64][]domain.Entry } type fakeCPWeeklyRankSourceCall struct { relationType string startMS int64 endMS int64 limit int32 } func (s *fakeCPWeeklyRankSource) ListCPWeeklyRankEntries(_ context.Context, relationType string, startMS int64, endMS int64, limit int32) ([]domain.Entry, error) { s.calls = append(s.calls, fakeCPWeeklyRankSourceCall{ relationType: relationType, startMS: startMS, endMS: endMS, limit: limit, }) entries := append([]domain.Entry(nil), s.windows[[2]int64{startMS, endMS}]...) if limit > 0 && len(entries) > int(limit) { entries = entries[:limit] } return entries, nil } func cpWeeklyRankEntries(count int, baseScore int64) []domain.Entry { entries := make([]domain.Entry, 0, count) for index := 1; index <= count; index++ { suffix := strconv.Itoa(index) entries = append(entries, domain.Entry{ Rank: int64(index), RelationshipID: "cp-rel-" + suffix, RelationType: "cp", Score: baseScore + int64(index), UserA: domain.User{ UserID: int64(1000 + index), DisplayUserID: "L" + suffix, Username: "left-" + suffix, Avatar: "https://avatar/left-" + suffix + ".png", }, UserB: domain.User{ UserID: int64(2000 + index), DisplayUserID: "R" + suffix, Username: "right-" + suffix, Avatar: "https://avatar/right-" + suffix + ".png", }, }) } return entries }