package service import ( "testing" "fashionapi/internal/model" "fashionapi/internal/pkg/imgurl" ) // TestBuildSnapImages 验证公开详情的 image 只含主图、副图嵌套在其主图的 Detail 下, // 且「副图的副图」上浮归并到该副图所在组的主图。 // // 5 张图:A 主,B 副(挂 A);C 主;D 副(挂 C);E 副(挂 B → 应上浮归并到 A) // // 期望 images 只有 2 张主图:A(Detail=[B,E])、C(Detail=[D])。 func TestBuildSnapImages(t *testing.T) { s := &streetSnapService{img: imgurl.New("", "", "")} imgs := []model.StreetSnapImage{ {ID: 1, Image: "A", Name: "A", IsDetail: 0, ParentImageID: 0}, {ID: 2, Image: "B", Name: "B", IsDetail: 1, ParentImageID: 1}, {ID: 3, Image: "C", Name: "C", IsDetail: 0, ParentImageID: 0}, {ID: 4, Image: "D", Name: "D", IsDetail: 1, ParentImageID: 3}, {ID: 5, Image: "E", Name: "E", IsDetail: 1, ParentImageID: 2}, // 2 是副图 → 上浮到 A } out := s.buildSnapImages(imgs) if len(out) != 2 { t.Fatalf("images 应只含 2 张主图,实际 %d", len(out)) } a := out[0] if a.Name != "A" || a.IsDetail != 0 { t.Fatalf("第 1 张应为 A 主图,实际 name=%s is_detail=%d", a.Name, a.IsDetail) } if len(a.Detail) != 2 || a.Detail[0].Name != "B" || a.Detail[1].Name != "E" { t.Fatalf("A 的副图应依序为 [B,E],实际 %d 张", len(a.Detail)) } for _, d := range a.Detail { if d.IsDetail != 1 { t.Fatalf("副图 %s 的 is_detail 应为 1,实际 %d", d.Name, d.IsDetail) } } c := out[1] if c.Name != "C" { t.Fatalf("第 2 张应为 C 主图,实际 name=%s", c.Name) } if len(c.Detail) != 1 || c.Detail[0].Name != "D" { t.Fatalf("C 的副图应为 [D],实际 %d 张", len(c.Detail)) } } // TestBuildSnapImagesOrphan 父引用指向失效行(不存在)时,该图按主图渲染,不丢图。 func TestBuildSnapImagesOrphan(t *testing.T) { s := &streetSnapService{img: imgurl.New("", "", "")} imgs := []model.StreetSnapImage{ {ID: 1, Image: "A", Name: "A", IsDetail: 1, ParentImageID: 99}, // 父 99 不存在 {ID: 2, Image: "B", Name: "B", IsDetail: 0, ParentImageID: 0}, } out := s.buildSnapImages(imgs) if len(out) != 2 { t.Fatalf("孤儿副图应自成主图:images=%d", len(out)) } if out[0].Name != "A" || out[0].IsDetail != 0 || len(out[0].Detail) != 0 { t.Fatalf("A 应作为无副图的主图,实际 name=%s is_detail=%d details=%d", out[0].Name, out[0].IsDetail, len(out[0].Detail)) } }