import { test, expect } from "../fixtures"; test.describe("知识库 - 创建知识库交互测试", () => { test.beforeEach(async ({ authenticatedPage }) => { await authenticatedPage.goto("/dashboard/knowledge"); await authenticatedPage.waitForLoadState("networkidle"); }); test("点击创建知识库按钮打开对话框", async ({ authenticatedPage }) => { const createBtn = authenticatedPage.getByRole("button", { name: /创建知识库/ }).first(); await expect(createBtn).toBeVisible({ timeout: 15000 }); await createBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 验证对话框标题 await expect(dialog.getByRole("heading", { name: "创建知识库" })).toBeVisible(); }); test("创建知识库对话框包含名称和描述输入框", async ({ authenticatedPage }) => { const createBtn = authenticatedPage.getByRole("button", { name: /创建知识库/ }).first(); await expect(createBtn).toBeVisible({ timeout: 15000 }); await createBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 验证名称输入框 const nameInput = dialog.locator("#kb-name"); const hasNameInput = await nameInput.isVisible({ timeout: 5000 }).catch(() => false); expect(hasNameInput).toBeTruthy(); // 验证描述输入框 const descTextarea = dialog.locator("#kb-desc"); const hasDesc = await descTextarea.isVisible({ timeout: 3000 }).catch(() => false); expect(hasDesc).toBeTruthy(); }); test("填写知识库名称后创建按钮可点击", async ({ authenticatedPage }) => { const createBtn = authenticatedPage.getByRole("button", { name: /创建知识库/ }).first(); await expect(createBtn).toBeVisible({ timeout: 15000 }); await createBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 初始状态下创建按钮应禁用 const submitBtn = dialog.getByRole("button", { name: "创建" }); const isDisabled = await submitBtn.isDisabled().catch(() => true); expect(isDisabled).toBeTruthy(); // 填写名称 const nameInput = dialog.locator("#kb-name"); await nameInput.fill("E2E测试知识库"); // 创建按钮应变为可点击 await expect(submitBtn).toBeEnabled(); }); test("填写完整信息后点击创建提交", async ({ authenticatedPage }) => { const createBtn = authenticatedPage.getByRole("button", { name: /创建知识库/ }).first(); await expect(createBtn).toBeVisible({ timeout: 15000 }); await createBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 填写名称 const nameInput = dialog.locator("#kb-name"); await nameInput.fill("E2E测试知识库"); // 填写描述 const descTextarea = dialog.locator("#kb-desc"); await descTextarea.fill("E2E自动化测试创建的知识库"); // 点击创建 const submitBtn = dialog.getByRole("button", { name: "创建" }); await submitBtn.click(); // 等待创建完成(对话框关闭或显示加载状态) await authenticatedPage.waitForTimeout(3000); }); test("点击取消按钮关闭创建对话框", async ({ authenticatedPage }) => { const createBtn = authenticatedPage.getByRole("button", { name: /创建知识库/ }).first(); await expect(createBtn).toBeVisible({ timeout: 15000 }); await createBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 点击取消 const cancelBtn = dialog.getByRole("button", { name: "取消" }); await cancelBtn.click(); // 验证对话框关闭 await expect(dialog).not.toBeVisible({ timeout: 5000 }); }); }); test.describe("知识库 - 文档列表交互测试", () => { test.beforeEach(async ({ authenticatedPage }) => { await authenticatedPage.goto("/dashboard/knowledge"); await authenticatedPage.waitForLoadState("networkidle"); }); test("切换企业知识库和行业知识库Tab", async ({ authenticatedPage }) => { const enterpriseTab = authenticatedPage.getByRole("tab", { name: /企业知识库/ }); const industryTab = authenticatedPage.getByRole("tab", { name: /行业知识库/ }); const hasEnterprise = await enterpriseTab.isVisible({ timeout: 15000 }).catch(() => false); const hasIndustry = await industryTab.isVisible({ timeout: 3000 }).catch(() => false); if (!hasEnterprise && !hasIndustry) { test.skip(); return; } // 切换到行业知识库 if (hasIndustry) { await industryTab.click(); await authenticatedPage.waitForTimeout(1000); } // 切换回企业知识库 if (hasEnterprise) { await enterpriseTab.click(); await authenticatedPage.waitForTimeout(1000); } }); test("搜索知识库功能", async ({ authenticatedPage }) => { // 查找搜索输入框 const searchInput = authenticatedPage.locator('input[placeholder*="搜索知识库"]'); const hasSearch = await searchInput.isVisible({ timeout: 15000 }).catch(() => false); if (!hasSearch) { test.skip(); return; } // 输入搜索关键词 await searchInput.fill("测试搜索"); // 验证搜索已触发(前端过滤,无需等待API) await authenticatedPage.waitForTimeout(500); // 清空搜索 await searchInput.clear(); await authenticatedPage.waitForTimeout(500); }); test("展开知识库卡片查看文档列表", async ({ authenticatedPage }) => { // 等待知识库列表加载 await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 查找知识库卡片 const kbCards = authenticatedPage.locator("div.grid.grid-cols-1 > div.space-y-3 > div.cursor-pointer, div.grid.gap-4 > div.space-y-3 > div.cursor-pointer"); const cardCount = await kbCards.count(); if (cardCount === 0) { // 尝试更通用的选择器 const allCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const allCount = await allCards.count(); if (allCount === 0) { test.skip(); return; } // 点击第一张卡片展开 await allCards.first().click(); } else { // 点击第一张卡片展开 await kbCards.first().click(); } // 等待文档列表加载 await authenticatedPage.waitForTimeout(2000); // 验证文档列表标题可见 const docListTitle = authenticatedPage.getByText("文档列表"); const hasDocList = await docListTitle.isVisible({ timeout: 10000 }).catch(() => false); if (!hasDocList) { test.skip(); return; } await expect(docListTitle).toBeVisible(); }); test("文档列表显示上传文档按钮", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 展开第一个知识库 const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); // 验证上传文档按钮 const uploadBtn = authenticatedPage.getByRole("button", { name: /上传文档/ }); const hasUpload = await uploadBtn.isVisible({ timeout: 10000 }).catch(() => false); if (!hasUpload) { test.skip(); return; } await expect(uploadBtn).toBeVisible(); }); }); test.describe("知识库 - 上传文档交互测试", () => { test.beforeEach(async ({ authenticatedPage }) => { await authenticatedPage.goto("/dashboard/knowledge"); await authenticatedPage.waitForLoadState("networkidle"); }); test("点击上传文档按钮打开上传对话框", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 展开第一个知识库 const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); // 点击上传文档按钮 const uploadBtn = authenticatedPage.getByRole("button", { name: /上传文档/ }); const hasUpload = await uploadBtn.isVisible({ timeout: 10000 }).catch(() => false); if (!hasUpload) { test.skip(); return; } await uploadBtn.click(); // 验证上传对话框 const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 验证对话框标题 await expect(dialog.getByRole("heading", { name: "上传文档" })).toBeVisible(); }); test("上传文档对话框包含标题、来源类型和内容输入", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); const uploadBtn = authenticatedPage.getByRole("button", { name: /上传文档/ }); const hasUpload = await uploadBtn.isVisible({ timeout: 10000 }).catch(() => false); if (!hasUpload) { test.skip(); return; } await uploadBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 验证标题输入框 const titleInput = dialog.locator("#doc-title"); const hasTitle = await titleInput.isVisible({ timeout: 5000 }).catch(() => false); expect(hasTitle).toBeTruthy(); // 验证来源类型选择器 const sourceTypeLabel = dialog.getByText("来源类型"); const hasSourceType = await sourceTypeLabel.isVisible({ timeout: 3000 }).catch(() => false); expect(hasSourceType).toBeTruthy(); }); test("切换来源类型为URL后显示URL输入框", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); const uploadBtn = authenticatedPage.getByRole("button", { name: /上传文档/ }); const hasUpload = await uploadBtn.isVisible({ timeout: 10000 }).catch(() => false); if (!hasUpload) { test.skip(); return; } await uploadBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 点击来源类型下拉框 const sourceTypeTrigger = dialog.locator("button").filter({ hasText: /文本|URL|Markdown/ }).first(); const hasTrigger = await sourceTypeTrigger.isVisible({ timeout: 5000 }).catch(() => false); if (!hasTrigger) { test.skip(); return; } await sourceTypeTrigger.click(); // 选择URL选项 const urlOption = authenticatedPage.getByRole("option", { name: "URL" }) .or(authenticatedPage.locator("[data-radix-collection-item]").filter({ hasText: "URL" })); const hasUrlOption = await urlOption.first().isVisible({ timeout: 5000 }).catch(() => false); if (!hasUrlOption) { test.skip(); return; } await urlOption.first().click(); // 验证URL输入框出现 const urlInput = dialog.locator("#doc-url"); const hasUrlInput = await urlInput.isVisible({ timeout: 5000 }).catch(() => false); expect(hasUrlInput).toBeTruthy(); }); test("填写文档信息后上传按钮可点击", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); const uploadBtn = authenticatedPage.getByRole("button", { name: /上传文档/ }); const hasUpload = await uploadBtn.isVisible({ timeout: 10000 }).catch(() => false); if (!hasUpload) { test.skip(); return; } await uploadBtn.click(); const dialog = authenticatedPage.getByRole("dialog"); await expect(dialog).toBeVisible({ timeout: 10000 }); // 填写标题 const titleInput = dialog.locator("#doc-title"); await titleInput.fill("E2E测试文档"); // 填写内容(默认是文本类型) const contentTextarea = dialog.locator("#doc-content"); const hasContent = await contentTextarea.isVisible({ timeout: 3000 }).catch(() => false); if (hasContent) { await contentTextarea.fill("这是E2E自动化测试上传的文档内容"); } // 验证上传按钮可点击 const submitBtn = dialog.getByRole("button", { name: "上传" }); await expect(submitBtn).toBeEnabled(); }); }); test.describe("知识库 - 删除文档交互测试", () => { test.beforeEach(async ({ authenticatedPage }) => { await authenticatedPage.goto("/dashboard/knowledge"); await authenticatedPage.waitForLoadState("networkidle"); }); test("展开知识库后文档列表中每行显示删除按钮", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 展开第一个知识库 const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); // 查找文档表格 const docTable = authenticatedPage.locator("table"); const hasTable = await docTable.isVisible({ timeout: 10000 }).catch(() => false); if (!hasTable) { // 可能没有文档 const noDocs = authenticatedPage.getByText("暂无文档"); const hasNoDocs = await noDocs.isVisible({ timeout: 5000 }).catch(() => false); if (hasNoDocs) { test.skip(); return; } test.skip(); return; } // 验证操作列存在 const actionHeader = authenticatedPage.getByText("操作"); const hasActionHeader = await actionHeader.isVisible({ timeout: 5000 }).catch(() => false); expect(hasActionHeader).toBeTruthy(); }); test("点击文档删除按钮移除文档", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 展开第一个知识库 const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } await kbCards.first().click(); await authenticatedPage.waitForTimeout(2000); // 查找文档表格行 const docRows = authenticatedPage.locator("table tbody tr"); const rowCount = await docRows.count(); if (rowCount === 0) { test.skip(); return; } // 查找第一行的删除按钮 const firstRowDeleteBtn = docRows.first().locator("button").filter({ has: authenticatedPage.locator("svg.lucide-trash-2"), }); const hasDeleteBtn = await firstRowDeleteBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!hasDeleteBtn) { test.skip(); return; } // 点击删除 await firstRowDeleteBtn.click(); // 等待删除完成 await authenticatedPage.waitForTimeout(2000); }); test("知识库卡片显示删除按钮", async ({ authenticatedPage }) => { await authenticatedPage.waitForTimeout(2000); const emptyState = authenticatedPage.getByText("还没有知识库"); const hasEmpty = await emptyState.isVisible({ timeout: 5000 }).catch(() => false); if (hasEmpty) { test.skip(); return; } // 查找知识库卡片中的删除按钮 const kbCards = authenticatedPage.locator("div.cursor-pointer.rounded-xl"); const cardCount = await kbCards.count(); if (cardCount === 0) { test.skip(); return; } // 在第一张卡片中查找删除按钮 const deleteBtn = kbCards.first().locator("button").filter({ has: authenticatedPage.locator("svg.lucide-trash-2"), }); const hasDeleteBtn = await deleteBtn.isVisible({ timeout: 5000 }).catch(() => false); if (!hasDeleteBtn) { test.skip(); return; } await expect(deleteBtn).toBeVisible(); }); });