feat: unify owned and competitor work analysis
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package creator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCreatorPostgresWorkAnalysisSourcesFiltersAndOrdering(t *testing.T) {
|
||||
store, accounts, ctx := openCreatorIntegrationStore(t)
|
||||
ownedID := createIntegrationAccount(t, ctx, accounts, "analysis-owned")
|
||||
competitor, err := store.CreateCompetitor(ctx, CompetitorInput{Platform: PlatformDouyin, PlatformAccountKey: "analysis-competitor", Nickname: "分析竞品", HomepageURL: "https://www.douyin.com/user/analysis-competitor"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
older := now.Add(-72 * time.Hour)
|
||||
newer := now.Add(-48 * time.Hour)
|
||||
inputs := []WorkInput{
|
||||
{Platform: PlatformDouyin, WorkKey: "zero", SourceType: SourceOwned, SourceID: ownedID, PublishedAt: &older, Likes: int64Ptr(0), CommentsCount: int64Ptr(0), Shares: int64Ptr(0), CollectCount: int64Ptr(0), PlayCount: int64Ptr(0)},
|
||||
{Platform: PlatformDouyin, WorkKey: "positive", SourceType: SourceOwned, SourceID: ownedID, PublishedAt: &newer, Likes: int64Ptr(10), CommentsCount: int64Ptr(10), Shares: int64Ptr(10), CollectCount: int64Ptr(10), PlayCount: int64Ptr(10)},
|
||||
{Platform: PlatformDouyin, WorkKey: "unknown", SourceType: SourceOwned, SourceID: ownedID},
|
||||
{Platform: PlatformDouyin, WorkKey: "competitor", SourceType: SourceCompetitor, SourceID: competitor.ID, PublishedAt: &newer, Likes: int64Ptr(999)},
|
||||
}
|
||||
works := make([]Work, len(inputs))
|
||||
for i, input := range inputs {
|
||||
work, _, err := store.UpsertWork(ctx, input, now.Add(-26*time.Hour))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
works[i] = work
|
||||
}
|
||||
for _, field := range []string{"published_at", "likes", "comments_count", "shares", "collect_count", "play_count"} {
|
||||
for _, order := range []string{"asc", "desc"} {
|
||||
t.Run(fmt.Sprintf("%s_%s", field, order), func(t *testing.T) {
|
||||
filter := WorkFilter{SourceType: SourceOwned, SortBy: field, SortOrder: order}
|
||||
first := works[0].ID
|
||||
second := works[1].ID
|
||||
if order == "desc" {
|
||||
first, second = second, first
|
||||
}
|
||||
for pageNumber, id := range []string{first, second, works[2].ID} {
|
||||
page, err := store.ListWorksPage(ctx, filter, pageNumber+1, 1)
|
||||
if err != nil || page.Total != 3 || len(page.Data) != 1 || page.Data[0].ID != id {
|
||||
t.Fatalf("page=%+v expected=%s err=%v", page, id, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
for _, filter := range []WorkFilter{
|
||||
{SourceType: SourceOwned, SourceID: ownedID, MinCollectCount: int64Ptr(0), MinPlayCount: int64Ptr(0)},
|
||||
{SourceType: SourceOwned, MinLikes: int64Ptr(0), MinComments: int64Ptr(0), MinShares: int64Ptr(0)},
|
||||
{SourceType: SourceOwned, PublishedAtStatus: "verified"},
|
||||
} {
|
||||
page, err := store.ListWorksPage(ctx, filter, 1, 10)
|
||||
if err != nil || page.Total != 2 {
|
||||
t.Fatalf("filter=%+v page=%+v err=%v", filter, page, err)
|
||||
}
|
||||
}
|
||||
page, err := store.ListWorksPage(ctx, WorkFilter{SourceType: SourceCompetitor, SourceID: competitor.ID}, 1, 10)
|
||||
if err != nil || page.Total != 1 || page.Data[0].ID != works[3].ID {
|
||||
t.Fatalf("competitor leaked owned works: %+v %v", page, err)
|
||||
}
|
||||
page, err = store.ListWorksPage(ctx, WorkFilter{SourceType: SourceOwned, SourceID: "missing"}, 1, 10)
|
||||
if err != nil || page.Total != 0 || page.Data == nil {
|
||||
t.Fatalf("empty account: %+v %v", page, err)
|
||||
}
|
||||
settings, err := store.GetSettings(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, growth := range []int64{50, 5} {
|
||||
for _, point := range []struct {
|
||||
at time.Time
|
||||
likes int64
|
||||
}{{now.Add(-25 * time.Hour), 100}, {now.Add(-time.Hour), 100 + growth}} {
|
||||
if _, err := store.RecordMetric(ctx, MetricInput{WorkID: works[i].ID, CollectedAt: point.at, Likes: int64Ptr(point.likes)}, settings, point.at); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, order := range []string{"asc", "desc"} {
|
||||
filter := WorkFilter{SourceType: SourceOwned, SortBy: "likes_growth", SortOrder: order, Growth: WorkGrowthFilter{Hours: 24}}
|
||||
expected := works[0].ID
|
||||
if order == "asc" {
|
||||
expected = works[1].ID
|
||||
}
|
||||
page, err = store.ListWorksPage(ctx, filter, 1, 1)
|
||||
if err != nil || page.Total != 3 || page.Data[0].ID != expected {
|
||||
t.Fatalf("growth ordering: %+v err=%v", page, err)
|
||||
}
|
||||
filter.Growth.MinLikes = int64Ptr(10)
|
||||
page, err = store.ListWorksPage(ctx, filter, 1, 1)
|
||||
if err != nil || page.Total != 1 || page.Data[0].ID != works[0].ID {
|
||||
t.Fatalf("growth threshold before page: %+v err=%v", page, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user