312 lines
14 KiB
TypeScript
312 lines
14 KiB
TypeScript
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/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
await expect(authenticatedPage.getByRole("heading", { name: "诊断分析" })).toBeVisible({ timeout: 15000 });
|
||
});
|
||
|
||
test("诊断分析页面副标题正确显示", async ({ authenticatedPage }) => {
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
await expect(authenticatedPage.getByText("全面评估品牌在搜索引擎和AI生成式引擎中的可见性")).toBeVisible({ timeout: 15000 });
|
||
});
|
||
|
||
test("无品牌时显示空状态", async ({ authenticatedPage }) => {
|
||
if (await hasProjects(authenticatedPage)) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const emptyTitle = authenticatedPage.getByText("暂无品牌数据");
|
||
const hasEmpty = await emptyTitle.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasEmpty) { test.skip(); return; }
|
||
|
||
await expect(emptyTitle).toBeVisible();
|
||
});
|
||
});
|
||
|
||
test.describe("诊断分析 - 诊断流程测试", () => {
|
||
test("有品牌时显示重新诊断按钮", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const refreshBtn = authenticatedPage.getByRole("button", { name: /重新诊断/ });
|
||
await expect(refreshBtn).toBeVisible({ timeout: 15000 });
|
||
});
|
||
|
||
test("诊断页面显示三个评分卡片", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
await expect(authenticatedPage.getByText("综合评分")).toBeVisible({ timeout: 15000 });
|
||
await expect(authenticatedPage.getByText("SEO诊断评分")).toBeVisible();
|
||
await expect(authenticatedPage.getByText("GEO诊断评分")).toBeVisible();
|
||
});
|
||
|
||
test("诊断页面显示三个Tab标签", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
// 分别检查每个 tab,避免 .or() strict mode 问题
|
||
const combinedTab = authenticatedPage.getByRole("tab", { name: "综合诊断" });
|
||
const seoTab = authenticatedPage.getByRole("tab", { name: "SEO诊断" });
|
||
const geoTab = authenticatedPage.getByRole("tab", { name: "GEO诊断" });
|
||
const hasCombined = await combinedTab.isVisible({ timeout: 10000 }).catch(() => false);
|
||
const hasSeo = await seoTab.isVisible({ timeout: 3000 }).catch(() => false);
|
||
const hasGeo = await geoTab.isVisible({ timeout: 3000 }).catch(() => false);
|
||
expect(hasCombined || hasSeo || hasGeo).toBeTruthy();
|
||
});
|
||
|
||
test("点击SEO诊断Tab显示SEO诊断详情", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const seoTab = authenticatedPage.getByRole("tab", { name: "SEO诊断" });
|
||
const hasTab = await seoTab.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasTab) { test.skip(); return; }
|
||
|
||
await seoTab.click();
|
||
|
||
// 分别检查两种可能的状态
|
||
const seoDetail = authenticatedPage.getByText("SEO诊断详情");
|
||
const seoEmpty = authenticatedPage.getByText("暂无SEO诊断数据");
|
||
const hasDetail = await seoDetail.isVisible({ timeout: 10000 }).catch(() => false);
|
||
const hasEmpty = await seoEmpty.isVisible({ timeout: 3000 }).catch(() => false);
|
||
expect(hasDetail || hasEmpty).toBeTruthy();
|
||
});
|
||
|
||
test("点击GEO诊断Tab显示GEO诊断详情", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const geoTab = authenticatedPage.getByRole("tab", { name: "GEO诊断" });
|
||
const hasTab = await geoTab.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasTab) { test.skip(); return; }
|
||
|
||
await geoTab.click();
|
||
|
||
const geoDetail = authenticatedPage.getByText("GEO诊断详情");
|
||
const geoEmpty = authenticatedPage.getByText("暂无GEO诊断数据");
|
||
const hasDetail = await geoDetail.isVisible({ timeout: 10000 }).catch(() => false);
|
||
const hasEmpty = await geoEmpty.isVisible({ timeout: 3000 }).catch(() => false);
|
||
expect(hasDetail || hasEmpty).toBeTruthy();
|
||
});
|
||
|
||
test("诊断结果显示5维度评分", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const geoTab = authenticatedPage.getByRole("tab", { name: "GEO诊断" });
|
||
const hasTab = await geoTab.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasTab) { test.skip(); return; }
|
||
|
||
await geoTab.click();
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const dimensionLabels = authenticatedPage.getByText(/内容可提取性|实体清晰度|E-E-A-T信号|Schema标记|主题权威|引用就绪度/);
|
||
const count = await dimensionLabels.count();
|
||
if (count === 0) { test.skip(); return; }
|
||
expect(count).toBeGreaterThanOrEqual(1);
|
||
});
|
||
|
||
test("点击重新诊断按钮触发刷新", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const refreshBtn = authenticatedPage.getByRole("button", { name: /重新诊断/ });
|
||
if (await refreshBtn.isVisible()) {
|
||
await refreshBtn.click();
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
}
|
||
});
|
||
});
|
||
|
||
test.describe("诊断分析 - 优先优化建议测试", () => {
|
||
test("诊断结果包含优先优化建议", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const recommendations = authenticatedPage.getByText("优先优化建议");
|
||
const hasRecommendations = await recommendations.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasRecommendations) { test.skip(); return; }
|
||
|
||
await expect(recommendations).toBeVisible();
|
||
});
|
||
|
||
test("建议列表包含基于诊断制定GEO方案按钮", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const geoPlanBtn = authenticatedPage.getByRole("button", { name: /基于诊断制定GEO方案/ });
|
||
const hasBtn = await geoPlanBtn.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasBtn) { test.skip(); return; }
|
||
|
||
await expect(geoPlanBtn).toBeVisible();
|
||
});
|
||
|
||
test("点击基于诊断制定GEO方案跳转到策略页面", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const geoPlanBtn = authenticatedPage.getByRole("button", { name: /基于诊断制定GEO方案/ });
|
||
const hasBtn = await geoPlanBtn.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasBtn) { test.skip(); return; }
|
||
|
||
await geoPlanBtn.click();
|
||
await expect(authenticatedPage).toHaveURL(/\/dashboard\/strategy/, { timeout: 15000 });
|
||
});
|
||
});
|
||
|
||
test.describe("策略制定 - 页面加载测试", () => {
|
||
test("策略制定页面标题正确显示", async ({ authenticatedPage }) => {
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
await expect(authenticatedPage.getByRole("heading", { name: "策略制定" })).toBeVisible({ timeout: 15000 });
|
||
});
|
||
|
||
test("策略制定页面副标题正确显示", async ({ authenticatedPage }) => {
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
await expect(authenticatedPage.getByText("制定GEO优化策略、关键词规划与目标设定")).toBeVisible({ timeout: 15000 });
|
||
});
|
||
|
||
test("无方案时显示生成新方案按钮", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const generateBtn = authenticatedPage.getByRole("button", { name: /生成新方案|生成优化方案/ });
|
||
const hasBtn = await generateBtn.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasBtn) { test.skip(); return; }
|
||
|
||
await expect(generateBtn.first()).toBeVisible();
|
||
});
|
||
});
|
||
|
||
test.describe("策略制定 - 方案详情测试", () => {
|
||
test("有方案时显示诊断分数和目标分数", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const scoreLabel = authenticatedPage.getByText("诊断分数 → 目标分数");
|
||
const hasScore = await scoreLabel.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasScore) { test.skip(); return; }
|
||
|
||
await expect(scoreLabel).toBeVisible();
|
||
});
|
||
|
||
test("有方案时显示预计周数", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const weeksLabel = authenticatedPage.getByText("预计周数");
|
||
const hasWeeks = await weeksLabel.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasWeeks) { test.skip(); return; }
|
||
|
||
await expect(weeksLabel).toBeVisible();
|
||
});
|
||
|
||
test("有方案时显示行动项进度", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const progressLabel = authenticatedPage.getByText("行动项进度");
|
||
const hasProgress = await progressLabel.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasProgress) { test.skip(); return; }
|
||
|
||
await expect(progressLabel).toBeVisible();
|
||
});
|
||
|
||
test("有方案时显示行动项列表", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const actionList = authenticatedPage.getByText("行动项列表");
|
||
const hasActions = await actionList.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasActions) { test.skip(); return; }
|
||
|
||
await expect(actionList).toBeVisible();
|
||
});
|
||
|
||
test("行动项包含AI生成内容按钮", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/strategy");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const aiGenBtn = authenticatedPage.getByRole("button", { name: /AI生成内容/ });
|
||
const hasBtn = await aiGenBtn.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasBtn) { test.skip(); return; }
|
||
|
||
await expect(aiGenBtn.first()).toBeVisible();
|
||
});
|
||
});
|
||
|
||
test.describe("诊断→策略完整流程测试", () => {
|
||
test("从诊断页面导航到策略制定页面", async ({ authenticatedPage }) => {
|
||
if (!(await hasProjects(authenticatedPage))) { test.skip(); return; }
|
||
|
||
await authenticatedPage.goto("/dashboard/diagnosis");
|
||
await authenticatedPage.waitForLoadState("networkidle");
|
||
|
||
const geoPlanBtn = authenticatedPage.getByRole("button", { name: /基于诊断制定GEO方案/ });
|
||
const hasBtn = await geoPlanBtn.isVisible({ timeout: 10000 }).catch(() => false);
|
||
if (!hasBtn) { test.skip(); return; }
|
||
|
||
await geoPlanBtn.click();
|
||
await expect(authenticatedPage).toHaveURL(/\/dashboard\/strategy/, { timeout: 15000 });
|
||
await expect(authenticatedPage.getByRole("heading", { name: "策略制定" })).toBeVisible({ timeout: 15000 });
|
||
});
|
||
});
|