import { expect, test } from "@playwright/test"; import { buildReferenceImageOrderPrompt } from "@/lib/ai/providers/reference-image-order"; import { collectMessageImageAttachments } from "@/lib/chat/message-image-attachments"; test.describe("image message contracts", () => { test("normalizes every supported image part shape for message rendering", () => { const attachments = collectMessageImageAttachments({ parts: [ { type: "file", name: "图一", mediaType: "image/png", url: "https://cdn.example.com/one.png", }, { type: "image", name: "图二", image: "https://cdn.example.com/two.jpg", }, { type: "image_url", name: "图三", image_url: { url: "https://cdn.example.com/three.webp" }, }, { type: "input_image", data: "https://cdn.example.com/four.png", }, { type: "file", mediaType: "video/mp4", url: "https://cdn.example.com/video.mp4", }, ], attachments: [ { name: "重复图一", contentType: "image/png", url: "https://cdn.example.com/one.png", }, { name: "历史附件", contentType: "image/jpeg", url: "https://cdn.example.com/five.jpg", }, ], }); expect(attachments.map((attachment) => attachment.url)).toEqual([ "https://cdn.example.com/one.png", "https://cdn.example.com/two.jpg", "https://cdn.example.com/three.webp", "https://cdn.example.com/four.png", "https://cdn.example.com/five.jpg", ]); expect(attachments.map((attachment) => attachment.name)).toEqual([ "图一", "图二", "图三", "图片4", "历史附件", ]); }); test("adds explicit ordinal guidance only for multi-image edits", () => { const prompt = "把图二的横杆加到图一的桌子上,其他不变"; expect( buildReferenceImageOrderPrompt(prompt, ["https://cdn.example.com/one.png"]) ).toBe(prompt); const multiImagePrompt = buildReferenceImageOrderPrompt(prompt, [ "https://cdn.example.com/one.png", "https://cdn.example.com/two.png", ]); expect(multiImagePrompt).toContain("本次请求包含 2 张参考图"); expect(multiImagePrompt).toContain("不得忽略后续图片"); expect(multiImagePrompt).toContain("第二张图/图2/图二"); expect(multiImagePrompt).toContain("图A是对象素材来源,图B是目标底图"); expect(multiImagePrompt).toContain("不要输出拼图或并排对比图"); expect(multiImagePrompt.endsWith(prompt)).toBe(true); }); });