thread-master/apps/backend/internal/module/scout/usecase/m5_scout_test.go

202 lines
7.1 KiB
Go
Raw Normal View History

2026-07-13 01:15:30 +00:00
package usecase_test
import (
"context"
"testing"
"apps/backend/internal/module/scout/domain"
"apps/backend/internal/module/scout/repository"
"apps/backend/internal/module/scout/usecase"
studioPublish "apps/backend/internal/module/studio/publish"
"github.com/stretchr/testify/require"
)
type staticDevMode struct {
on bool
}
func (s *staticDevMode) DevModeEnabled(_ context.Context, _ int64) (bool, error) {
return s.on, nil
}
func newScout() (*usecase.Service, *studioPublish.FakeTransport, *staticDevMode) {
tp := studioPublish.NewFake()
dev := &staticDevMode{}
svc := usecase.New(repository.NewMemory())
svc.Transport = tp
svc.Settings = dev
return svc, tp, dev
}
func TestSC_01_CreateBrandProduct(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_001)
b, err := svc.CreateBrand(context.Background(), uid, "海港", "敏感肌")
require.NoError(t, err)
p, err := svc.SaveProduct(context.Background(), uid, &domain.Product{
BrandID: b.ID, Label: "無香洗髮", PainPoints: []string{"刺鼻"}, MatchTags: []string{"洗髮"},
})
require.NoError(t, err)
list, err := svc.ListProducts(context.Background(), uid, b.ID)
require.NoError(t, err)
require.Len(t, list, 1)
require.Equal(t, p.ID, list[0].ID)
}
func TestSC_02_DeleteBrandWithProductsRefused(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_002)
b, _ := svc.CreateBrand(context.Background(), uid, "B", "")
_, _ = svc.SaveProduct(context.Background(), uid, &domain.Product{BrandID: b.ID, Label: "P"})
err := svc.RemoveBrand(context.Background(), uid, b.ID)
require.ErrorIs(t, err, domain.ErrHasProducts)
}
func TestSC_03_PrepareBrief(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_003)
brief, err := svc.PrepareBrief(context.Background(), uid, "敏感肌保養", "", "", "value", false)
require.NoError(t, err)
require.NotEmpty(t, brief.ScanTerms)
require.Equal(t, "敏感肌保養", brief.Intent)
}
func TestSC_04_PrepareBriefEmptyIntent(t *testing.T) {
svc, _, _ := newScout()
_, err := svc.PrepareBrief(context.Background(), 1, " ", "", "", "", false)
require.Error(t, err)
}
func TestSC_05_ApiPath(t *testing.T) {
svc, _, dev := newScout()
uid := int64(5_002_005)
dev.on = false
brief, _ := svc.PrepareBrief(context.Background(), uid, "遠端辦公", "", "", "value", false)
posts, err := svc.RunScanFromBrief(context.Background(), uid, brief)
require.NoError(t, err)
require.NotEmpty(t, posts)
require.Equal(t, domain.PathAPI, posts[0].ScanPath)
}
func TestSC_06_CrawlerPath(t *testing.T) {
svc, _, dev := newScout()
uid := int64(5_002_006)
dev.on = true
require.NoError(t, svc.SetCrawlerSession(context.Background(), uid, "ext-session-1"))
brief, _ := svc.PrepareBrief(context.Background(), uid, "成分黨", "", "", "value", false)
posts, err := svc.RunScanFromBrief(context.Background(), uid, brief)
require.NoError(t, err)
require.Equal(t, domain.PathCrawler, posts[0].ScanPath)
}
func TestSC_07_NoSession(t *testing.T) {
svc, _, dev := newScout()
uid := int64(5_002_007)
dev.on = true
brief, _ := svc.PrepareBrief(context.Background(), uid, "無 session", "", "", "value", false)
_, err := svc.RunScanFromBrief(context.Background(), uid, brief)
require.ErrorIs(t, err, domain.ErrNoCrawlerSession)
}
func TestSC_08_ListPostsAfterScan(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_008)
brief, _ := svc.PrepareBrief(context.Background(), uid, "list test", "", "", "value", false)
_, _ = svc.RunScanFromBrief(context.Background(), uid, brief)
list, err := svc.ListPosts(context.Background(), uid, "")
require.NoError(t, err)
require.NotEmpty(t, list)
require.True(t, list[0].CreatedAt > 0)
}
func TestSC_09_DraftOutreach(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_009)
brief, _ := svc.PrepareBrief(context.Background(), uid, "draft", "", "", "value", false)
posts, _ := svc.RunScanFromBrief(context.Background(), uid, brief)
p, err := svc.DraftOutreach(context.Background(), uid, posts[0].ID, "")
require.NoError(t, err)
require.Equal(t, domain.OutreachDrafted, p.OutreachStatus)
require.NotEmpty(t, p.DraftText)
}
func TestSC_10_SkipAndMark(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_010)
brief, _ := svc.PrepareBrief(context.Background(), uid, "skip", "", "", "value", false)
posts, _ := svc.RunScanFromBrief(context.Background(), uid, brief)
p, err := svc.SkipOutreach(context.Background(), uid, posts[0].ID)
require.NoError(t, err)
require.Equal(t, domain.OutreachSkipped, p.OutreachStatus)
if len(posts) > 1 {
p2, err := svc.MarkPublished(context.Background(), uid, posts[1].ID)
require.NoError(t, err)
require.Equal(t, domain.OutreachPublished, p2.OutreachStatus)
}
}
func TestSC_11_SendOutreach(t *testing.T) {
svc, tp, _ := newScout()
uid := int64(5_002_011)
brief, _ := svc.PrepareBrief(context.Background(), uid, "send", "", "", "value", false)
posts, _ := svc.RunScanFromBrief(context.Background(), uid, brief)
p, err := svc.SendOutreach(context.Background(), uid, posts[0].ID, "你好呀", "acc1")
require.NoError(t, err)
require.Equal(t, domain.OutreachPublished, p.OutreachStatus)
require.Equal(t, 1, tp.CallCount())
// fail path
tp.Fail = true
brief2, _ := svc.PrepareBrief(context.Background(), uid, "sendfail", "", "", "value", false)
posts2, _ := svc.RunScanFromBrief(context.Background(), uid, brief2)
_, err = svc.SendOutreach(context.Background(), uid, posts2[0].ID, "nope", "")
require.Error(t, err)
got, _ := svc.ListPosts(context.Background(), uid, "")
for _, x := range got {
if x.ID == posts2[0].ID {
require.NotEqual(t, domain.OutreachPublished, x.OutreachStatus)
}
}
}
func TestSC_12_RemovePostTheme(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_012)
brief, _ := svc.PrepareBrief(context.Background(), uid, "rm", "", "", "value", false)
posts, _ := svc.RunScanFromBrief(context.Background(), uid, brief)
require.NoError(t, svc.RemovePost(context.Background(), uid, posts[0].ID))
require.NoError(t, svc.RemoveTheme(context.Background(), uid, brief.ThemeKey))
list, _ := svc.ListPosts(context.Background(), uid, "")
require.Empty(t, list)
}
func TestSC_13_Homework(t *testing.T) {
svc, _, _ := newScout()
uid := int64(5_002_013)
brief, _ := svc.PrepareBrief(context.Background(), uid, "hw", "", "", "value", false)
h, err := svc.SaveHomework(context.Background(), uid, &domain.Homework{
ThemeKey: brief.ThemeKey, ThemeLabel: brief.ThemeLabel, Purpose: "value", Brief: *brief,
})
require.NoError(t, err)
list, err := svc.ListHomework(context.Background(), uid)
require.NoError(t, err)
require.Len(t, list, 1)
got, err := svc.GetHomework(context.Background(), uid, h.ThemeKey)
require.NoError(t, err)
require.Equal(t, brief.Intent, got.Brief.Intent)
require.NoError(t, svc.RemoveHomework(context.Background(), uid, h.ThemeKey))
}
func TestSC_14_ImportProductFromUrl(t *testing.T) {
svc, _, _ := newScout()
d, err := svc.ImportProductFromURL(context.Background(), "https://shop.example.com/item/1")
require.NoError(t, err)
require.NotEmpty(t, d.Label)
require.Equal(t, "https://shop.example.com/item/1", d.PlacementURL)
}
func TestSC_TopicRemoved(t *testing.T) {
svc, _, _ := newScout()
require.ErrorIs(t, svc.TopicRemoved(), domain.ErrTopicRemoved)
}