Files
djk/internal/app/provider_huangdou_vip_test.go

104 lines
3.8 KiB
Go

package app
import (
"context"
"encoding/json"
"net/http"
"testing"
)
func TestHuangdouVIPKnownFreeAndUnknownRemainDistinct(t *testing.T) {
for _, test := range []struct {
body string
want int
}{
{`{"pay_type":"vip"}`, 1},
{`{"pay_type":"free"}`, 0},
{`{"is_vip":"y"}`, 1},
{`{"is_vip":false}`, 0},
{`{"vip_episodes":[3,"4"]}`, 1},
{`{"pay_type":"free","vip_episodes":[3]}`, 1},
{`{"episodes":[{"type":"free"},{"type":"vip"}]}`, 1},
{`{"name":"VIP 是标题文字"}`, -1},
{`{"pay_type":"unknown","vip_episodes":[0,-1,"invalid"]}`, -1},
{`{"vip_episodes":[]}`, -1},
} {
var row map[string]any
if err := json.Unmarshal([]byte(test.body), &row); err != nil {
t.Fatal(err)
}
row["id"], row["name"] = "fixture", "无图 VIP 样本"
drama := huangdouDramaFromMap(row)
actual := -1
if drama.VIP != nil {
actual = 0
if *drama.VIP {
actual = 1
}
}
if actual != test.want {
t.Fatalf("%s: VIP %d, want %d", test.body, actual, test.want)
}
ranking, err := parseHuangdouRanking(map[string]any{"list": []any{row}}, 1)
if err != nil {
t.Fatal(err)
}
ranked := ranking.Items[0].Drama
if (ranked.VIP == nil) != (drama.VIP == nil) || ranked.VIP != nil && *ranked.VIP != *drama.VIP {
t.Fatal("ranking lost VIP metadata")
}
}
paid, free := true, false
previous := Drama{ID: "huangdou:fixture", VIP: &paid}
if value := mergeDramaMetadata(Drama{}, previous).VIP; value == nil || !*value {
t.Fatal("incomplete metadata erased VIP flag")
}
if value := mergeDramaMetadata(Drama{VIP: &free}, previous).VIP; value == nil || *value {
t.Fatal("fresh free metadata did not replace VIP flag")
}
}
func TestHuangdouVIPEpisodesPreserveFreeEpisodesAndPreviewRefusal(t *testing.T) {
d := rankingTestDownloader(t, func(request *http.Request) (*http.Response, error) {
if request.URL.Path != "/api/drama/detail" {
t.Fatal("unexpected upstream path", request.URL.Path)
}
return rankingHTTPResponse(request, 200, `{"data":{"id":"fixture","name":"无图分集样本","pay_type":"vip","free_episodes":1,"episode_count":4,"vip_episodes":[3],"episodes":[{"seq":1,"type":"free"},{"seq":2,"type":"vip"},{"seq":3},{"seq":4,"type":"free"}]}}`), nil
})
_, chapters, err := d.fetchHuangdouChapters(context.Background(), "fixture")
if err != nil || len(chapters) != 4 {
t.Fatal(err, len(chapters))
}
for i, want := range []bool{false, true, true, false} {
if chapters[i].VIP != want {
t.Fatal("incorrect episode restriction", i+1, chapters[i].VIP)
}
}
if !huangdouPreviewOnly(map[string]any{"is_preview": true}, "https://example.invalid/preview.mp4", "https://example.invalid") {
t.Fatal("preview mistaken for a complete episode")
}
}
func TestHuangdouVIPBackfillOnlyWhenInformationMissing(t *testing.T) {
calls := 0
d := rankingTestDownloader(t, func(request *http.Request) (*http.Response, error) {
calls++
if request.URL.Path != "/api/drama/detail" {
t.Fatal("unexpected upstream path", request.URL.Path)
}
return rankingHTTPResponse(request, 200, `{"data":{"id":"fixture","name":"无图样本","pay_type":"vip","issue_date":"2026-03-16","click":0,"hot_rate":"123"}}`), nil
})
cached := Drama{ID: "huangdou:fixture", Source: sourceHuangdou, OnlineDate: "2026-03-16", Views: "0", Heat: "123", SortMetadata: &sortMetadataState{Version: sortMetadataVersion}}
if !needsSortMetadata(cached) {
t.Fatal("manual update cannot backfill old VIP information")
}
patch, err := d.fetchDramaSortMetadata(context.Background(), cached)
if err != nil || patch.VIP == nil || !*patch.VIP || calls != 1 {
t.Fatal("VIP backfill failed", err, calls)
}
cached = mergeDramaMetadata(patch, cached)
if _, err = d.fetchDramaSortMetadata(context.Background(), cached); err != nil || calls != 1 {
t.Fatal("known VIP caused unnecessary detail request")
}
}