thread-master/backend/internal/library/viral/discover_graceful_test.go

119 lines
3.6 KiB
Go
Raw Permalink Normal View History

2026-06-26 08:37:04 +00:00
package viral
import (
"context"
"errors"
"testing"
"haixun-backend/internal/library/placement"
)
func TestRunDiscover_skipsFailedKeyword(t *testing.T) {
calls := 0
crawler := func(ctx context.Context, m placement.MemberContext, keyword string, limit int) ([]placement.DiscoverPost, error) {
calls++
if keyword == "bad" {
return nil, errors.New("api timeout")
}
return []placement.DiscoverPost{{
Text: "轉職面試技巧分享心得", Author: "ok_user", LikeCount: 30, ReplyCount: 4,
Permalink: "https://www.threads.net/@ok_user/post/1", Source: placement.DiscoverCrawler,
}}, nil
}
member := placement.MemberContext{
AllowsCrawler: true,
BrowserConnected: true,
SearchSourceMode: placement.SearchSourceCrawler,
}
out, err := RunDiscover(context.Background(), DiscoverInput{
Keywords: []string{"bad", "轉職"},
Member: member,
Crawler: crawler,
MissionScan: true,
}, nil)
if err != nil {
t.Fatalf("expected partial success, got err: %v", err)
}
if len(out) != 1 {
t.Fatalf("expected 1 candidate, got %d", len(out))
}
if calls != 2 {
t.Fatalf("expected 2 keyword attempts, got %d", calls)
}
}
func TestRunDiscover_missionRelaxedFallbackWithoutVerified(t *testing.T) {
crawler := func(ctx context.Context, m placement.MemberContext, keyword string, limit int) ([]placement.DiscoverPost, error) {
return []placement.DiscoverPost{{
Text: "轉職心得分享", Author: "plain_user", LikeCount: 12, ReplyCount: 2,
Permalink: "https://www.threads.net/@plain_user/post/2", Source: placement.DiscoverThreadsAPI,
}}, nil
}
member := placement.MemberContext{
AllowsCrawler: true,
BrowserConnected: true,
SearchSourceMode: placement.SearchSourceCrawler,
}
out, err := RunDiscover(context.Background(), DiscoverInput{
Keywords: []string{"轉職"},
Member: member,
Crawler: crawler,
MissionScan: true,
}, nil)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(out) != 1 {
t.Fatalf("expected relaxed fallback candidate, got %d", len(out))
}
if out[0].AuthorVerified {
t.Fatal("verified should remain false when API omits it")
}
}
2026-06-28 08:28:42 +00:00
func TestRunDiscover_missionFiltersOffTopicCrawlerDrift(t *testing.T) {
crawler := func(ctx context.Context, m placement.MemberContext, keyword string, limit int) ([]placement.DiscoverPost, error) {
return []placement.DiscoverPost{
{
Text: "毛小孩飲食心得分享,最近很多人問罐罐怎麼挑",
Author: "pet_user",
LikeCount: 200,
ReplyCount: 40,
Permalink: "https://www.threads.net/@pet_user/post/pet",
Source: placement.DiscoverCrawler,
},
{
Text: "備孕精蟲品質心得分享:作息、壓力和檢查報告怎麼一起看",
Author: "fertility_user",
LikeCount: 26,
ReplyCount: 6,
Permalink: "https://www.threads.net/@fertility_user/post/quality",
Source: placement.DiscoverCrawler,
},
}, nil
}
member := placement.MemberContext{
AllowsCrawler: true,
BrowserConnected: true,
SearchSourceMode: placement.SearchSourceCrawler,
}
out, err := RunDiscover(context.Background(), DiscoverInput{
Keywords: []string{"精蟲品質"},
SeedQuery: "精蟲品質",
Label: "備孕內容",
TopicHints: []string{"備孕", "精蟲品質"},
Member: member,
Crawler: crawler,
MissionScan: true,
}, nil)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if len(out) != 1 {
t.Fatalf("expected only topic-matched candidate, got %d", len(out))
}
if out[0].Author != "fertility_user" {
t.Fatalf("expected fertility candidate, got %q", out[0].Author)
}
}