104 lines
3.8 KiB
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")
|
|
}
|
|
}
|