geo/frontend/e2e/tests/content-monitoring.spec.ts

337 lines
15 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from "../fixtures";
import { DashboardPage } from "../pages/dashboard.page";
async function hasProjects(page: import("@playwright/test").Page): Promise<boolean> {
// 先导航到 dashboard 页面
await page.goto("/dashboard");
await page.waitForLoadState("networkidle");
const emptyMsg = page.getByText("开始优化您的AI可见性");
const errorTitle = page.getByText("数据加载失败");
const title = page.getByRole("heading", { name: "品牌健康中心" });
const hasTitle = await title.isVisible({ timeout: 15000 }).catch(() => false);
if (!hasTitle) return false;
const isEmpty = await emptyMsg.isVisible().catch(() => false);
const isError = await errorTitle.isVisible().catch(() => false);
return !isEmpty && !isError;
}
test.describe("内容工坊 - 页面加载测试", () => {
test("内容工坊页面标题正确显示", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByRole("heading", { name: "内容工坊" })).toBeVisible({ timeout: 15000 });
});
test("内容工坊页面副标题正确显示", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByText("AI驱动的内容生产流水线")).toBeVisible({ timeout: 15000 });
});
test("内容工坊页面显示AI生成新内容按钮", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ });
await expect(generateBtn.first()).toBeVisible({ timeout: 15000 });
});
});
test.describe("内容工坊 - 内容列表测试", () => {
test("有内容时显示内容卡片列表", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
// 检查是否有空状态
const emptyState = authenticatedPage.getByText("还没有内容");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
// 检查是否有错误
const errorBanner = authenticatedPage.getByText(/加载失败/);
const hasError = await errorBanner.isVisible({ timeout: 3000 }).catch(() => false);
if (hasError) { test.skip(); return; }
// 使用更宽泛的选择器匹配内容卡片
const contentCards = authenticatedPage.locator("[class*='bg-white'][class*='rounded-xl'][class*='border']");
const count = await contentCards.count();
if (count === 0) { test.skip(); return; }
expect(count).toBeGreaterThanOrEqual(1);
});
test("内容卡片显示状态标签", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("还没有内容");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
const errorBanner = authenticatedPage.getByText(/加载失败/);
const hasError = await errorBanner.isVisible({ timeout: 3000 }).catch(() => false);
if (hasError) { test.skip(); return; }
const statusBadge = authenticatedPage.getByText(/草稿|待审核|已审核|已发布|已归档/).first();
const hasBadge = await statusBadge.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasBadge) { test.skip(); return; }
await expect(statusBadge).toBeVisible();
});
test("内容卡片显示类型标签", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("还没有内容");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
const errorBanner = authenticatedPage.getByText(/加载失败/);
const hasError = await errorBanner.isVisible({ timeout: 3000 }).catch(() => false);
if (hasError) { test.skip(); return; }
const typeBadge = authenticatedPage.getByText(/文章|问答|知识库|社媒/).first();
const hasBadge = await typeBadge.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasBadge) { test.skip(); return; }
await expect(typeBadge).toBeVisible();
});
test("空状态时显示引导文案和AI生成按钮", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("还没有内容");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (!hasEmpty) { test.skip(); return; }
await expect(emptyState).toBeVisible();
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ });
await expect(generateBtn.first()).toBeVisible();
});
});
test.describe("内容工坊 - 内容生成测试", () => {
test("点击AI生成新内容打开生成对话框", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ }).first();
await generateBtn.click();
await expect(authenticatedPage.getByRole("dialog")).toBeVisible({ timeout: 10000 });
});
test("生成对话框包含目标关键词输入框", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ }).first();
await generateBtn.click();
await expect(authenticatedPage.locator("#keyword")).toBeVisible({ timeout: 10000 });
});
test("生成对话框包含目标平台选择器", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ }).first();
await generateBtn.click();
await expect(authenticatedPage.locator("#platform")).toBeVisible({ timeout: 10000 });
});
test("未填写必填项时开始AI生成按钮禁用", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ }).first();
await generateBtn.click();
const submitBtn = authenticatedPage.getByRole("button", { name: /开始AI生成/ });
await expect(submitBtn).toBeDisabled({ timeout: 10000 });
});
test("填写关键词和平台后开始AI生成按钮启用", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
const generateBtn = authenticatedPage.getByRole("button", { name: /AI生成新内容/ }).first();
await generateBtn.click();
const keywordInput = authenticatedPage.locator("#keyword");
await keywordInput.fill("AI营销");
const platformSelect = authenticatedPage.locator("#platform");
await platformSelect.click();
await authenticatedPage.getByText("通用").click();
const submitBtn = authenticatedPage.getByRole("button", { name: /开始AI生成/ });
await expect(submitBtn).toBeEnabled({ timeout: 10000 });
});
});
test.describe("监测优化 - 页面加载测试", () => {
test("监测优化页面标题正确显示", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByRole("heading", { name: "监测优化" })).toBeVisible({ timeout: 15000 });
});
test("监测优化页面副标题正确显示", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByText("实时监控品牌AI可见性及时响应告警通知")).toBeVisible({ timeout: 15000 });
});
test("监测优化页面显示告警配置按钮", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const settingsBtn = authenticatedPage.getByRole("button", { name: /告警配置/ });
await expect(settingsBtn).toBeVisible({ timeout: 15000 });
});
test("监测优化页面显示监测记录和告警通知Tab", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
// 使用 waitFor 等待 tab 出现
const recordsTab = authenticatedPage.getByRole("tab", { name: "监测记录" });
const alertsTab = authenticatedPage.getByRole("tab", { name: "告警通知" });
// 至少一个 tab 应该可见
await expect(recordsTab.first()).toBeVisible({ timeout: 15000 }).catch(async () => {
await expect(alertsTab.first()).toBeVisible({ timeout: 5000 });
});
});
});
test.describe("监测优化 - 监测记录测试", () => {
test("无监测记录时显示空状态", async ({ authenticatedPage }) => {
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("暂无监测记录");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (!hasEmpty) { test.skip(); return; }
await expect(emptyState).toBeVisible();
});
test("有监测记录时显示记录卡片", async ({ authenticatedPage }) => {
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("暂无监测记录");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
const checkBtn = authenticatedPage.getByRole("button", { name: /立即检测/ });
const count = await checkBtn.count();
expect(count).toBeGreaterThanOrEqual(1);
});
test("监测记录卡片包含立即检测按钮", async ({ authenticatedPage }) => {
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("暂无监测记录");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
const checkBtn = authenticatedPage.getByRole("button", { name: /立即检测/ }).first();
await expect(checkBtn).toBeVisible({ timeout: 10000 });
});
test("监测记录卡片包含暂停/启用按钮", async ({ authenticatedPage }) => {
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const emptyState = authenticatedPage.getByText("暂无监测记录");
const hasEmpty = await emptyState.isVisible({ timeout: 10000 }).catch(() => false);
if (hasEmpty) { test.skip(); return; }
const toggleBtn = authenticatedPage.getByRole("button", { name: /暂停|启用/ }).first();
const hasBtn = await toggleBtn.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasBtn) { test.skip(); return; }
await expect(toggleBtn).toBeVisible();
});
});
test.describe("监测优化 - 告警通知测试", () => {
test("点击告警通知Tab切换到告警列表", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
// 滚动到页面顶部确保 Tab 可见
await authenticatedPage.evaluate(() => window.scrollTo(0, 0));
const alertsTab = authenticatedPage.getByRole("tab", { name: /告警通知/ });
const hasTab = await alertsTab.isVisible({ timeout: 15000 }).catch(() => false);
if (!hasTab) {
// 尝试通过文本定位
const alertsText = authenticatedPage.getByText("告警通知").first();
const hasText = await alertsText.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasText) { test.skip(); return; }
await alertsText.click();
} else {
await alertsTab.click();
}
// 分别检查两种可能的状态 — 使用 toBeVisible 确保等待
let found = false;
try {
await expect(authenticatedPage.getByText("告警列表")).toBeVisible({ timeout: 10000 });
found = true;
} catch {
try {
await expect(authenticatedPage.getByText("暂无告警")).toBeVisible({ timeout: 5000 });
found = true;
} catch {
// 两者都不可见
}
}
expect(found).toBeTruthy();
});
test("告警通知Tab显示统计卡片", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
const alertsTab = authenticatedPage.getByRole("tab", { name: /告警通知/ });
const hasTab = await alertsTab.isVisible({ timeout: 10000 }).catch(() => false);
if (!hasTab) { test.skip(); return; }
await alertsTab.click();
const statCards = authenticatedPage.getByText(/未读告警|严重告警|今日新增|已处理/);
const count = await statCards.count();
if (count === 0) { test.skip(); return; }
expect(count).toBeGreaterThanOrEqual(1);
});
});
test.describe("内容→监测完整流程测试", () => {
test("从内容工坊导航到监测优化页面", async ({ authenticatedPage }) => {
await authenticatedPage.goto("/dashboard/content");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByRole("heading", { name: "内容工坊" })).toBeVisible({ timeout: 15000 });
await authenticatedPage.goto("/dashboard/monitoring");
await authenticatedPage.waitForLoadState("networkidle");
await expect(authenticatedPage.getByRole("heading", { name: "监测优化" })).toBeVisible({ timeout: 15000 });
});
});