feat(street): 审核 service 暴露主副图分组操作与详情分组视图
This commit is contained in:
134
internal/service/review_street_group_test.go
Normal file
134
internal/service/review_street_group_test.go
Normal file
@ -0,0 +1,134 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"fashionapi/internal/dto"
|
||||
"fashionapi/internal/model"
|
||||
"fashionapi/internal/pkg/imgurl"
|
||||
"fashionapi/internal/repository"
|
||||
)
|
||||
|
||||
// fakeGroupRepo 只实现分组相关的仓储方法,其余由嵌入的接口兜底(测试中不会调到未实现的方法)。
|
||||
type fakeGroupRepo struct {
|
||||
repository.ReviewRepository
|
||||
images []model.StreetSnapDraftImage
|
||||
detail *model.StreetSnapDraft
|
||||
attachFn func(draftID, mainID uint32, imgIDs []uint32) error
|
||||
}
|
||||
|
||||
func (f *fakeGroupRepo) StreetDraftDetail(_ context.Context, _ uint32) (*model.StreetSnapDraft, error) {
|
||||
return f.detail, nil
|
||||
}
|
||||
|
||||
func (f *fakeGroupRepo) StreetDraftImages(_ context.Context, _ uint32) ([]model.StreetSnapDraftImage, error) {
|
||||
return f.images, nil
|
||||
}
|
||||
|
||||
func (f *fakeGroupRepo) AttachStreetDraftImages(_ context.Context, draftID, mainID uint32, imgIDs []uint32) error {
|
||||
if f.attachFn != nil {
|
||||
return f.attachFn(draftID, mainID, imgIDs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeGroupRepo) AttachPrevStreetDraftImage(_ context.Context, _ uint32, _ uint32) error {
|
||||
if f.attachFn != nil {
|
||||
return f.attachFn(0, 0, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeGroupRepo) DetachStreetDraftImage(_ context.Context, _ uint32, _ uint32) error {
|
||||
if f.attachFn != nil {
|
||||
return f.attachFn(0, 0, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ repository.ReviewRepository = (*fakeGroupRepo)(nil)
|
||||
|
||||
func newGroupService(f *fakeGroupRepo) ReviewService {
|
||||
return NewReviewService(f, nil, imgurl.New("", "", ""), nil)
|
||||
}
|
||||
|
||||
// TestStreetGroupDetailExposesGrouping 详情必须输出可折叠分组:主图各成一组,副图归入主图。
|
||||
func TestStreetGroupDetailExposesGrouping(t *testing.T) {
|
||||
repo := &fakeGroupRepo{
|
||||
detail: &model.StreetSnapDraft{ID: 7, Title: "T", Year: 2026, City: "Beijing", Status: model.DraftStatusPending},
|
||||
images: []model.StreetSnapDraftImage{
|
||||
{ID: 1, Image: "main.jpg", Name: "main", SortOrder: 1, IsDetail: 0, ParentImageID: 0},
|
||||
{ID: 2, Image: "det.jpg", Name: "det", SortOrder: 2, IsDetail: 1, ParentImageID: 1},
|
||||
{ID: 3, Image: "solo.jpg", Name: "solo", SortOrder: 3, IsDetail: 0, ParentImageID: 0},
|
||||
},
|
||||
}
|
||||
svc := newGroupService(repo)
|
||||
v, err := svc.DraftDetail(context.Background(), dto.IngestKindStreet, 7)
|
||||
if err != nil {
|
||||
t.Fatalf("DraftDetail 失败: %v", err)
|
||||
}
|
||||
if len(v.Images) != 3 {
|
||||
t.Fatalf("Images 应保留扁平 3 张,实际 %d", len(v.Images))
|
||||
}
|
||||
if len(v.Groups) != 2 {
|
||||
t.Fatalf("Groups 应为 2 组,实际 %d", len(v.Groups))
|
||||
}
|
||||
if v.Groups[0].Image.ID != 1 || len(v.Groups[0].Details) != 1 {
|
||||
t.Fatalf("第 0 组应为 1 张主图 + 1 副图,实际 main=%d details=%d", v.Groups[0].Image.ID, len(v.Groups[0].Details))
|
||||
}
|
||||
if v.Groups[0].Image.DetailCount != 1 {
|
||||
t.Fatalf("主图 DetailCount 应为 1,实际 %d", v.Groups[0].Image.DetailCount)
|
||||
}
|
||||
if v.Groups[0].Details[0].ID != 2 {
|
||||
t.Fatalf("副图应为 id=2,实际 %d", v.Groups[0].Details[0].ID)
|
||||
}
|
||||
if v.Groups[1].Image.ID != 3 {
|
||||
t.Fatalf("第 1 组主图应为 id=3,实际 %d", v.Groups[1].Image.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStreetGroupAttachDelegates 并入必须透传参数到仓储。
|
||||
func TestStreetGroupAttachDelegates(t *testing.T) {
|
||||
var got struct {
|
||||
draftID uint32
|
||||
mainID uint32
|
||||
imgIDs []uint32
|
||||
}
|
||||
repo := &fakeGroupRepo{attachFn: func(draftID, mainID uint32, imgIDs []uint32) error {
|
||||
got.draftID, got.mainID, got.imgIDs = draftID, mainID, imgIDs
|
||||
return nil
|
||||
}}
|
||||
svc := newGroupService(repo)
|
||||
if err := svc.AttachDraftImages(context.Background(), dto.IngestKindStreet, 7, 1, []uint32{2, 3}); err != nil {
|
||||
t.Fatalf("AttachDraftImages 失败: %v", err)
|
||||
}
|
||||
if got.draftID != 7 || got.mainID != 1 || len(got.imgIDs) != 2 {
|
||||
t.Fatalf("参数透传错误: draftID=%d mainID=%d imgIDs=%v", got.draftID, got.mainID, got.imgIDs)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStreetGroupNonStreetRejected 走秀模块不允许主副图分组操作。
|
||||
func TestStreetGroupNonStreetRejected(t *testing.T) {
|
||||
repo := &fakeGroupRepo{}
|
||||
svc := newGroupService(repo)
|
||||
if err := svc.AttachDraftImages(context.Background(), dto.IngestKindRunway, 7, 1, []uint32{2}); !errors.Is(err, ErrInvalidImageGroup) {
|
||||
t.Fatalf("走秀并入应返回 ErrInvalidImageGroup,实际 %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStreetGroupPreventCrossDraft 仓储拦截跨草稿主图后,service 翻成中文用户错误。
|
||||
func TestStreetGroupPreventCrossDraft(t *testing.T) {
|
||||
repo := &fakeGroupRepo{attachFn: func(_, _ uint32, _ []uint32) error {
|
||||
return repository.ErrInvalidImageGroup
|
||||
}}
|
||||
svc := newGroupService(repo)
|
||||
err := svc.AttachDraftImages(context.Background(), dto.IngestKindStreet, 7, 1, []uint32{2, 3})
|
||||
if err == nil {
|
||||
t.Fatal("跨草稿应报错")
|
||||
}
|
||||
if err.Error() != "主图无效:它必须属于本草稿、未被删除,且自身是主图" {
|
||||
t.Fatalf("错误文案不符: %q", err.Error())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user