thread-master/apps/backend/internal/logic/scout/run_logic_test.go

112 lines
4.2 KiB
Go
Raw Normal View History

2026-08-13 02:22:24 +00:00
package scout
import (
"context"
"errors"
"testing"
"apps/backend/internal/middleware"
"apps/backend/internal/module/scout/domain"
scoutRepo "apps/backend/internal/module/scout/repository"
scoutUC "apps/backend/internal/module/scout/usecase"
"apps/backend/internal/svc"
"apps/backend/internal/types"
)
func testRun(id string, owner int64, created int64, status string) *domain.Run {
r := domain.NewRun(id, "job-"+id, owner, domain.RunBrief{
Intent: "敏感肌保養", Mode: domain.ModeTheme, ThemeKey: "skin", ThemeLabel: "敏感肌保養",
}, created)
r.Status = status
if status == domain.RunSucceeded {
r.EligibleCount = 1
}
return r
}
func testScoutContext(uid int64, repo *scoutRepo.MemoryStore) (*svc.ServiceContext, context.Context) {
service := scoutUC.New(repo)
return &svc.ServiceContext{Scout: service}, middleware.WithUID(context.Background(), uid)
}
func TestRunListLogicOwnerScopedPagination(t *testing.T) {
repo := scoutRepo.NewMemory()
for _, run := range []*domain.Run{
testRun("run-old", 7, 100, domain.RunSucceeded),
testRun("run-new", 7, 200, domain.RunSucceeded),
testRun("run-other", 8, 300, domain.RunSucceeded),
} {
if err := repo.CreateRun(context.Background(), run); err != nil {
t.Fatal(err)
}
}
svcCtx, ctx := testScoutContext(7, repo)
data, err := NewListScoutRunsLogic(ctx, svcCtx).ListScoutRuns(&types.ScoutRunListReq{Page: 1, PageSize: 1})
if err != nil {
t.Fatal(err)
}
if data.Pagination.Total != 2 || data.Pagination.TotalPages != 2 || len(data.List) != 1 || data.List[0].Id != "run-new" {
t.Fatalf("unexpected run page: %+v", data)
}
if data.List[0].JobId == "" {
t.Fatal("run response omitted job id")
}
}
func TestRunPostsLogicReturnsRunAndIndependentPage(t *testing.T) {
repo := scoutRepo.NewMemory()
run := testRun("run-posts", 7, 100, domain.RunSucceeded)
if err := repo.CreateRun(context.Background(), run); err != nil {
t.Fatal(err)
}
for _, post := range []*domain.Post{
{ID: "post-old", RunID: run.ID, OwnerUID: 7, Text: "old", PostedAt: 100, CreatedAt: 100},
{ID: "post-new", RunID: run.ID, OwnerUID: 7, Text: "new", PostedAt: 200, CreatedAt: 200},
} {
if err := repo.PublishRunPosts(context.Background(), 7, run.ID, []*domain.Post{post}); err != nil {
t.Fatal(err)
}
}
svcCtx, ctx := testScoutContext(7, repo)
data, err := NewListScoutRunPostsLogic(ctx, svcCtx).ListScoutRunPosts(&types.ScoutRunPostsReq{RunId: run.ID, Page: 2, PageSize: 1})
if err != nil {
t.Fatal(err)
}
if data.Run.Id != run.ID || data.Pagination.Total != 2 || data.Pagination.Page != 2 || len(data.List) != 1 || data.List[0].Id != "post-old" {
t.Fatalf("unexpected run posts page: %+v", data)
}
}
func TestRunRemoveLogicGuardsNonTerminalAndOwner(t *testing.T) {
repo := scoutRepo.NewMemory()
queued := testRun("run-queued", 7, 100, domain.RunQueued)
done := testRun("run-done", 7, 200, domain.RunSucceeded)
for _, run := range []*domain.Run{queued, done} {
if err := repo.CreateRun(context.Background(), run); err != nil {
t.Fatal(err)
}
}
svcCtx, ctx := testScoutContext(7, repo)
if _, err := NewRemoveScoutRunLogic(ctx, svcCtx).RemoveScoutRun(&types.ScoutRunPostsReq{RunId: queued.ID}); !errors.Is(err, domain.ErrIllegalRunStatus) {
t.Fatalf("queued run removal error = %v, want illegal status", err)
}
otherCtx := middleware.WithUID(context.Background(), 8)
if _, err := NewRemoveScoutRunLogic(otherCtx, svcCtx).RemoveScoutRun(&types.ScoutRunPostsReq{RunId: done.ID}); !errors.Is(err, domain.ErrNotFound) {
t.Fatalf("cross-owner removal error = %v, want not found", err)
}
if data, err := NewRemoveScoutRunLogic(ctx, svcCtx).RemoveScoutRun(&types.ScoutRunPostsReq{RunId: done.ID}); err != nil || !data.Ok {
t.Fatalf("terminal run removal = %+v, %v", data, err)
}
if _, err := repo.GetRun(context.Background(), 7, done.ID); !errors.Is(err, domain.ErrNotFound) {
t.Fatalf("removed run still exists: %v", err)
}
}
func TestRunLogicRequiresAuth(t *testing.T) {
svcCtx := &svc.ServiceContext{Scout: scoutUC.New(scoutRepo.NewMemory())}
_, err := NewListScoutRunsLogic(context.Background(), svcCtx).ListScoutRuns(&types.ScoutRunListReq{})
if err == nil || err.Error() != "missing authorization" {
t.Fatalf("auth error = %v", err)
}
}