ai-chatbot/tests/routes/openclaw-folder-attachments.test.ts

150 lines
4.4 KiB
TypeScript

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);
});
});