geo/frontend/e2e/tests/diagnosis-strategy.spec.ts

312 lines
14 KiB
TypeScript
Raw 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/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 });
});
});