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

92 lines
3.3 KiB
Go

package usecase
import (
"context"
"errors"
"testing"
"apps/backend/internal/module/scout/domain"
"apps/backend/internal/module/scout/repository"
)
func TestRunPublishVisibilityBarrierAndCounters(t *testing.T) {
ctx := context.Background()
store := repository.NewMemory()
run := domain.NewRun("run-publish", "job-publish", 7, domain.RunBrief{
Intent: "市集", Mode: domain.ModeActivity, TargetCount: 3,
}, 100)
if err := store.CreateRun(ctx, run); err != nil {
t.Fatal(err)
}
if err := run.Transition(domain.RunRunning, 200); err != nil {
t.Fatal(err)
}
if err := store.ReplaceRunGuarded(ctx, 7, run.ID, []string{domain.RunQueued}, run); err != nil {
t.Fatal(err)
}
svc := New(store)
posts := []*domain.Post{
{ID: "publish-new", RunID: run.ID, OwnerUID: 7, OutreachStatus: domain.OutreachNew, PostedAt: 200, CreatedAt: 20},
{ID: "publish-old", RunID: run.ID, OwnerUID: 7, OutreachStatus: domain.OutreachDrafted, PostedAt: 100, CreatedAt: 10},
}
if err := svc.StageRunPosts(ctx, 7, run.ID, posts); err != nil {
t.Fatal(err)
}
staged, err := store.ListRunPosts(ctx, 7, run.ID, 1, 10)
if err != nil || staged.Pagination.Total != 0 || len(staged.Items) != 0 {
t.Fatalf("staged posts leaked: %+v %v", staged, err)
}
if err := svc.PublishRun(ctx, 7, run.ID, posts); err != nil {
t.Fatal(err)
}
visible, err := store.ListRunPosts(ctx, 7, run.ID, 1, 10)
if err != nil || visible.Pagination.Total != 2 || len(visible.Items) != 2 || visible.Items[0].ID != "publish-new" {
t.Fatalf("published results=%+v %v", visible, err)
}
got, err := store.GetRun(ctx, 7, run.ID)
if err != nil || got.Status != domain.RunSucceeded || got.EligibleCount != 2 || got.PendingCount != 2 || got.ShortfallCount != 1 {
t.Fatalf("published run=%+v %v", got, err)
}
seen, err := store.HasSeenIdentity(ctx, 7, "id:publish-new")
if err != nil || !seen {
t.Fatalf("published identity not marked: %v %v", seen, err)
}
}
func TestRunPublishFailureLeavesResultsHiddenAndTerminalGuard(t *testing.T) {
ctx := context.Background()
store := repository.NewMemory()
run := domain.NewRun("run-fail", "job-fail", 7, domain.RunBrief{Intent: "市集", Mode: domain.ModeActivity}, 100)
if err := store.CreateRun(ctx, run); err != nil {
t.Fatal(err)
}
if err := run.Transition(domain.RunRunning, 200); err != nil {
t.Fatal(err)
}
if err := store.ReplaceRunGuarded(ctx, 7, run.ID, []string{domain.RunQueued}, run); err != nil {
t.Fatal(err)
}
svc := New(store)
posts := []*domain.Post{{ID: "hidden", RunID: run.ID, OwnerUID: 7}}
if err := svc.StageRunPosts(ctx, 7, run.ID, posts); err != nil {
t.Fatal(err)
}
if err := svc.FailRun(ctx, 7, run.ID, "provider timeout"); err != nil {
t.Fatal(err)
}
page, err := store.ListRunPosts(ctx, 7, run.ID, 1, 10)
if err != nil || page.Pagination.Total != 0 || len(page.Items) != 0 {
t.Fatalf("failed run exposed posts: %+v %v", page, err)
}
failed, err := store.GetRun(ctx, 7, run.ID)
if err != nil || failed.Status != domain.RunFailed || failed.Error != "provider timeout" {
t.Fatalf("failed run=%+v %v", failed, err)
}
if err := svc.FailRun(ctx, 7, run.ID, "retry"); err != nil {
t.Fatal(err)
}
if err := svc.StageRunPosts(ctx, 7, run.ID, posts); !errors.Is(err, domain.ErrIllegalRunStatus) {
t.Fatalf("terminal stage error=%v", err)
}
}