refactor(*): 稳定期治理 - 收敛核心架构、错误语义并修复跨项目数据竞态
This commit is contained in:
@@ -8,9 +8,37 @@ import (
|
||||
"infinite-canvas/backend/internal/model"
|
||||
)
|
||||
|
||||
func testUserAssetPayload(kind string, extra map[string]any) map[string]any {
|
||||
payload := map[string]any{
|
||||
"id": "asset-1",
|
||||
"kind": kind,
|
||||
"title": "测试资产",
|
||||
"coverUrl": "",
|
||||
"tags": []string{},
|
||||
}
|
||||
switch kind {
|
||||
case "image":
|
||||
payload["data"] = map[string]any{"dataUrl": "https://example.com/a.png", "width": 1, "height": 1, "bytes": 1, "mimeType": "image/png"}
|
||||
case "video":
|
||||
payload["data"] = map[string]any{"url": "https://example.com/a.mp4", "width": 1, "height": 1, "bytes": 1, "mimeType": "video/mp4"}
|
||||
case "audio":
|
||||
payload["data"] = map[string]any{"url": "https://example.com/a.mp3", "bytes": 1, "mimeType": "audio/mpeg"}
|
||||
case "model":
|
||||
payload["data"] = map[string]any{"url": "https://example.com/a.glb", "bytes": 1, "mimeType": "model/gltf-binary", "fileName": "a.glb"}
|
||||
case "text":
|
||||
payload["data"] = map[string]any{"content": "正文"}
|
||||
default:
|
||||
payload["data"] = map[string]any{"definition": map[string]any{}}
|
||||
}
|
||||
for key, value := range extra {
|
||||
payload[key] = value
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func TestAssetFromJSONAcceptsDeterministicGenerationID(t *testing.T) {
|
||||
id := "generation_" + strings.Repeat("a", 64)
|
||||
raw, err := json.Marshal(map[string]any{"id": id, "kind": "image", "title": "生成图片"})
|
||||
raw, err := json.Marshal(testUserAssetPayload("image", map[string]any{"id": id, "title": "生成图片"}))
|
||||
if err != nil {
|
||||
t.Fatalf("marshal asset: %v", err)
|
||||
}
|
||||
@@ -41,7 +69,7 @@ func TestAssetFromJSONNormalizesLegacyAndUnclassifiedMediaCategories(t *testing.
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
raw, err := json.Marshal(map[string]any{"id": "asset-1", "kind": test.kind, "category": test.category, "title": "测试资产"})
|
||||
raw, err := json.Marshal(testUserAssetPayload(test.kind, map[string]any{"category": test.category}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -56,6 +84,37 @@ func TestAssetFromJSONNormalizesLegacyAndUnclassifiedMediaCategories(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssetFromJSONRejectsIncompleteLibraryPayload(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload map[string]any
|
||||
want string
|
||||
}{
|
||||
{name: "missing tags", payload: testUserAssetPayload("image", map[string]any{"tags": nil}), want: "tags"},
|
||||
{name: "malformed tags", payload: testUserAssetPayload("image", map[string]any{"tags": []any{"角色", 1}}), want: "tags"},
|
||||
{name: "missing data", payload: testUserAssetPayload("image", map[string]any{"data": nil}), want: "data"},
|
||||
{name: "image missing locator", payload: testUserAssetPayload("image", map[string]any{"data": map[string]any{"dataUrl": "", "width": 1, "height": 1, "bytes": 1, "mimeType": "image/png"}}), want: "dataUrl 或 storageKey"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if test.name == "missing tags" {
|
||||
delete(test.payload, "tags")
|
||||
}
|
||||
if test.name == "missing data" {
|
||||
delete(test.payload, "data")
|
||||
}
|
||||
raw, err := json.Marshal(test.payload)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = assetFromJSON("user-1", raw)
|
||||
if err == nil || !strings.Contains(err.Error(), test.want) {
|
||||
t.Fatalf("assetFromJSON error = %v, want %q", err, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssetFromJSONRejectsIDOverLimit(t *testing.T) {
|
||||
raw, err := json.Marshal(map[string]any{"id": strings.Repeat("a", model.AssetIDMaxLength+1), "kind": "image"})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user