112 lines
4.2 KiB
Go
112 lines
4.2 KiB
Go
|
|
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)
|
||
|
|
}
|
||
|
|
}
|