Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

116 lines
4.5 KiB
Go

package dramaser
import (
"fmt"
"net/http/httptest"
"reflect"
"testing"
"time"
"91porn-server/models/v/mediamod"
"github.com/gin-gonic/gin/binding"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func TestDramaListSortMatchesMediaLibraryEnum(t *testing.T) {
tests := []struct {
name string
sortType int
want bson.D
}{
{name: "热门推荐", sortType: 1, want: bson.D{{Key: "sortCode", Value: -1}, {Key: "createdAt", Value: -1}, {Key: "_id", Value: -1}}},
{name: "最新上架", sortType: 2, want: bson.D{{Key: "latestPublishedAt", Value: -1}, {Key: "createdAt", Value: -1}, {Key: "_id", Value: -1}}},
{name: "最热", sortType: 3, want: bson.D{{Key: "countLike", Value: -1}, {Key: "createdAt", Value: -1}, {Key: "_id", Value: -1}}},
{name: "最多收藏", sortType: 4, want: bson.D{{Key: "countCollect", Value: -1}, {Key: "createdAt", Value: -1}, {Key: "_id", Value: -1}}},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
request := httptest.NewRequest("GET", fmt.Sprintf("/?pageNumber=1&pageSize=20&sortType=%d", test.sortType), nil)
var params ListRequest
if err := binding.Query.Bind(request, &params); err != nil {
t.Fatalf("bind sortType=%d: %v", test.sortType, err)
}
if got := dramaListSort(params.SortType); !reflect.DeepEqual(got, test.want) {
t.Fatalf("dramaListSort(%d) = %#v, want %#v", test.sortType, got, test.want)
}
})
}
legacyRequest := httptest.NewRequest("GET", "/?pageNumber=1&pageSize=20&sortType=7", nil)
if err := binding.Query.Bind(legacyRequest, &ListRequest{}); err == nil {
t.Fatal("bind legacy sortType=7 succeeded, want validation error")
}
}
func TestDramaFeedQueueVersionChangesWithCandidateSet(t *testing.T) {
now := time.Date(2026, 8, 28, 10, 0, 0, 0, time.FixedZone("CST", 8*60*60))
first := dramaFeedQueueVersion(now, []string{"media-b", "media-a"})
sameSet := dramaFeedQueueVersion(now.Add(time.Hour), []string{"media-a", "media-b"})
withNewDrama := dramaFeedQueueVersion(now.Add(time.Hour), []string{"media-a", "media-b", "media-c"})
nextDay := dramaFeedQueueVersion(now.Add(24*time.Hour), []string{"media-a", "media-b"})
if first != sameSet {
t.Fatalf("same-day candidate set produced different versions: %q != %q", first, sameSet)
}
if first == withNewDrama {
t.Fatalf("new candidate did not change queue version: %q", first)
}
if first == nextDay {
t.Fatalf("next day did not change queue version: %q", first)
}
}
func TestOrderFeedCandidatesPrioritizesRecommendedAndIsStable(t *testing.T) {
now := time.Date(2026, 8, 24, 12, 0, 0, 0, time.UTC)
recommended := &mediamod.Media{ID: primitive.NewObjectID(), SortCode: 10, CreatedAt: now.Add(-time.Hour)}
high := &mediamod.Media{ID: primitive.NewObjectID(), CountLike: 100, CreatedAt: now.Add(-48 * time.Hour)}
recent := &mediamod.Media{ID: primitive.NewObjectID(), CreatedAt: now.Add(-time.Hour)}
candidates := []*mediamod.Media{high, recent, recommended}
ordered := orderFeedCandidates(candidates, now)
again := orderFeedCandidates(candidates, now.Add(time.Minute))
if len(ordered) != 3 || len(again) != 3 {
t.Fatalf("ordered lengths = %d/%d, want 3/3", len(ordered), len(again))
}
if ordered[0].ID != recommended.ID {
t.Fatalf("first item = %s, want recommended %s", ordered[0].ID, recommended.ID)
}
for i := range ordered {
if ordered[i].ID != again[i].ID {
t.Fatalf("same-day queue changed at %d: %s != %s", i, ordered[i].ID, again[i].ID)
}
}
}
func TestValidateAnalyticsEventRequiresCheckoutContextForPaywall(t *testing.T) {
event := AnalyticsEvent{
EventID: "event-1", EventName: "DRAMA_PAYWALL_EXPOSURE", SessionID: "session-1",
OccurredAt: time.Now(), MediaID: primitive.NewObjectID(), ContentID: primitive.NewObjectID(),
Scene: "detail",
}
if err := validateAnalyticsEvent(event); err == nil {
t.Fatal("validateAnalyticsEvent() should reject missing checkoutContextId")
}
event.CheckoutContextID = "drama-checkout-test"
if err := validateAnalyticsEvent(event); err != nil {
t.Fatalf("validateAnalyticsEvent() error = %v", err)
}
}
func TestDramaInteractionScoreUses91PWeights(t *testing.T) {
media := &mediamod.Media{
CountLike: 1, CountCollect: 2, CountComment: 3, CountShare: 4, CountBrowse: 999,
}
if got, want := dramaInteractionScore(media), int64(34); got != want {
t.Fatalf("dramaInteractionScore() = %d, want %d", got, want)
}
}
func TestObjectIDStringReturnsEmptyForZeroID(t *testing.T) {
if got := objectIDString(primitive.NilObjectID); got != "" {
t.Fatalf("objectIDString(zero) = %q, want empty", got)
}
}