import { expect, test } from "@playwright/test"; import { countOpenClawArchiveRootFolders, sanitizeOpenClawArchiveEntryPath, sanitizeOpenClawArchiveName, } from "@/lib/openclaw-chat/folder-archive"; import { buildOpenClawArchiveDisplayText, buildOpenClawArchiveReferenceText, buildOpenClawFileReferenceText, getOpenClawChatFileContentType, isOpenClawChatFolderFileAllowed, isOpenClawChatArchiveAttachment, isOpenClawChatFileAttachment, normalizeOpenClawChatMediaAttachments, OPENCLAW_CHAT_FILE_MAX_BYTES, } from "@/lib/openclaw-chat/media-attachments"; test.describe("OpenClaw folder attachments", () => { test("keeps safe folder structure while removing traversal segments", () => { expect( sanitizeOpenClawArchiveEntryPath( "../../设计资料/主图:终稿.png", "主图.png", 0 ) ).toBe("设计资料/主图-终稿.png"); expect(sanitizeOpenClawArchiveName(" 商品/资料:* ")).toBe("商品-资料--"); }); test("counts multiple selected root folders", () => { expect( countOpenClawArchiveRootFolders([ "产品A/图片/1.png", "产品A/文档/readme.md", "产品B/图片/2.png", ]) ).toBe(2); }); test("normalizes ZIP URLs as file attachments", () => { const attachments = normalizeOpenClawChatMediaAttachments([ { type: "file", url: "https://cdn.example.com/产品资料.zip", name: "产品资料.zip", contentType: "application/zip", }, ]); expect(attachments).toEqual([ { type: "file", url: "https://cdn.example.com/产品资料.zip", name: "产品资料.zip", content_type: "application/zip", }, ]); expect( isOpenClawChatArchiveAttachment( attachments[0].url, attachments[0].content_type ) ).toBe(true); }); test("adds the public archive URL to the OpenClaw fallback message", () => { const attachments = normalizeOpenClawChatMediaAttachments([ { type: "file", url: "https://cdn.example.com/catalog.zip", name: "catalog.zip", }, ]); expect(buildOpenClawArchiveDisplayText(attachments)).toContain("catalog.zip"); expect(buildOpenClawArchiveReferenceText(attachments)).toContain( "https://cdn.example.com/catalog.zip" ); expect(buildOpenClawArchiveReferenceText(attachments)).toContain("解压"); }); test("accepts 2GB spreadsheet and folder-manifest attachments", () => { expect(OPENCLAW_CHAT_FILE_MAX_BYTES).toBe(2 * 1024 * 1024 * 1024); expect( getOpenClawChatFileContentType({ name: "清单.xlsx", type: "application/octet-stream", }) ).toBe( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ); expect( getOpenClawChatFileContentType({ name: "产品资料.folder.json", type: "application/vnd.yedir.folder-manifest+json", }) ).toBe("application/vnd.yedir.folder-manifest+json"); const attachments = normalizeOpenClawChatMediaAttachments([ { type: "file", url: "https://cdn.example.com/清单.xlsx", name: "清单.xlsx", contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", }, { type: "file", url: "https://cdn.example.com/产品资料.folder.json", name: "产品资料.folder.json", contentType: "application/vnd.yedir.folder-manifest+json", }, ]); expect(attachments).toHaveLength(2); expect( isOpenClawChatFileAttachment( attachments[0].url, attachments[0].content_type ) ).toBe(true); expect(buildOpenClawFileReferenceText(attachments)).toContain("表格请下载"); expect(buildOpenClawFileReferenceText(attachments)).toContain( "application/vnd.yedir.folder-manifest+json" ); }); test("allows normal folder media while blocking executable web content", () => { expect( isOpenClawChatFolderFileAllowed({ name: "商品图/主图.png", type: "image/png", }) ).toBe(true); expect( isOpenClawChatFolderFileAllowed({ name: "页面/index.html", type: "text/html", }) ).toBe(false); expect( isOpenClawChatFolderFileAllowed({ name: "工具/setup.exe", type: "application/octet-stream", }) ).toBe(false); }); });