import { expect, test } from "@playwright/test"; import { DEFAULT_DETAIL_REPLACEMENT_IMAGE_MODEL_ID, normalizeDetailReplacementImageModelConfig, } from "@/lib/ai/detail-replacement-image-model-config"; import { buildReplacementProductStructureLockLines, normalizeReplacementProductImageIndexes, parseReplacementProductIdentityProfile, } from "@/lib/ai/replacement-product-identity"; import { selectDetailReplacementGenerationInputs, shouldIncludeDetailReplacementModelImage, } from "@/lib/ai/detail-replacement-inputs"; test("parses a reusable multi-view product structure profile", () => { const profile = parseReplacementProductIdentityProfile( ` \`\`\`json { "identitySummary": "胡桃木桌面与黑色钢架电脑桌", "structureSummary": "左右均为闭合口字型侧框,桌面下方由三组矩形横梁连接", "structuralRisks": "禁止改成 K 型或 X 型腿,禁止横梁断裂或错接", "viewSummaries": [ {"imageIndex": 4, "cameraSummary": "右前方三分之四视角", "visibleStructure": "右侧框和全部纵向横梁清楚"}, {"imageIndex": 1, "cameraSummary": "左前方三分之四视角", "visibleStructure": "左侧框和桌面比例清楚"}, {"imageIndex": 9, "cameraSummary": "无效编号", "visibleStructure": "应被过滤"} ] } \`\`\` `, 4, ); expect(profile).toEqual({ identitySummary: "胡桃木桌面与黑色钢架电脑桌", structureSummary: "左右均为闭合口字型侧框,桌面下方由三组矩形横梁连接", structuralRisks: "禁止改成 K 型或 X 型腿,禁止横梁断裂或错接", viewSummaries: [ { imageIndex: 4, cameraSummary: "右前方三分之四视角", visibleStructure: "右侧框和全部纵向横梁清楚", }, { imageIndex: 1, cameraSummary: "左前方三分之四视角", visibleStructure: "左侧框和桌面比例清楚", }, ], }); }); test("keeps only two valid, unique, one-based product image indexes", () => { expect(normalizeReplacementProductImageIndexes([4, "1", 4, 0, 7], 4)).toEqual([ 4, 1, ]); }); test("makes product topology authoritative over the old detail product", () => { const prompt = buildReplacementProductStructureLockLines({ productImageCount: 2, structureSummary: "左右均为口字型矩形侧框", structuralRisks: "禁止变成 K 型或 X 型腿", }).join("\n"); expect(prompt).toContain("产品结构身份锁"); expect(prompt).toContain("最后一张详情底板只决定"); expect(prompt).toContain("绝不决定新产品的腿型"); expect(prompt).toContain("严禁把口字型框架改成 K/X/A/V 型"); expect(prompt).toContain("旧商品结构必须完整移除"); }); test("binds non-Pro detail replacement to GPT Image 2.5 in database config", () => { expect(DEFAULT_DETAIL_REPLACEMENT_IMAGE_MODEL_ID).toBe("gpt-image-2.5"); expect(normalizeDetailReplacementImageModelConfig(null)).toEqual({ modelId: "gpt-image-2.5", }); expect( normalizeDetailReplacementImageModelConfig({ modelId: "custom-image-model" }), ).toEqual({ modelId: "custom-image-model" }); }); test("keeps model-identity images on people-oriented detail pages", () => { expect(shouldIncludeDetailReplacementModelImage({ peoplePolicy: "preserve", useModelImage: false })).toBe(true); expect(shouldIncludeDetailReplacementModelImage({ sceneSummary: "固定模特在客厅展示产品" })).toBe(true); expect(shouldIncludeDetailReplacementModelImage({ pageKind: "product_detail", peoplePolicy: "none" })).toBe(false); }); test("keeps the product, required model identity, and final layout within three inputs", () => { const selected = selectDetailReplacementGenerationInputs({ productImageUrls: ["https://assets.test/product-1.png", "https://assets.test/product-2.png"], modelImageUrl: "https://assets.test/model.png", includeModelImage: true, rerunReferenceImageUrls: ["https://assets.test/rerun.png"], referenceImageUrl: "https://assets.test/layout.png", }); expect(selected.imageUrls).toEqual([ "https://assets.test/product-1.png", "https://assets.test/model.png", "https://assets.test/layout.png", ]); expect(selected.inputImageRoleByUrl).toEqual({ "https://assets.test/product-1.png": "product", "https://assets.test/model.png": "model", "https://assets.test/layout.png": "layout", }); }); test("prioritizes an explicit rerun reference while always keeping the final layout", () => { const selected = selectDetailReplacementGenerationInputs({ productImageUrls: ["https://assets.test/product-1.png", "https://assets.test/product-2.png"], rerunReferenceImageUrls: ["https://assets.test/rerun.png"], referenceImageUrl: "https://assets.test/layout.png", }); expect(selected.imageUrls).toEqual([ "https://assets.test/product-1.png", "https://assets.test/rerun.png", "https://assets.test/layout.png", ]); });