import { test, expect, describe, Page } from "@playwright/test"; import { LoginPage } from "../pages/login.page"; const TEST_USER = { email: "admin@example.com", password: "admin@123", }; class OnboardingPage { page: Page; brandNameInput: ReturnType; startAnalysisButton: ReturnType; skipToDashboardButton: ReturnType; competitorCheckboxes: ReturnType; addCompetitorInput: ReturnType; addCompetitorButton: ReturnType; nextButton: ReturnType; backButton: ReturnType; skipStepButton: ReturnType; platformCheckboxes: ReturnType; selectAllButton: ReturnType; queryFrequencyOptions: ReturnType; healthScore: ReturnType; healthLevelBadge: ReturnType; viewActionsButton: ReturnType; completeButton: ReturnType; progressSteps: ReturnType; constructor(page: Page) { this.page = page; this.brandNameInput = this.page.locator("#brandName"); this.startAnalysisButton = this.page.getByRole("button", { name: /开始分析/, }); this.skipToDashboardButton = this.page.getByRole("button", { name: /跳过.*Dashboard/, }); this.competitorCheckboxes = this.page .locator(".border.rounded-lg") .filter({ has: this.page.locator(".flex.h-5.w-5") }); this.addCompetitorInput = this.page.locator( 'input[placeholder="输入竞品名称"]', ); this.addCompetitorButton = this.page .locator('button:has-text("添加")') .first(); this.nextButton = this.page.getByRole("button", { name: /继续/ }); this.backButton = this.page.getByRole("button", { name: /上一步/ }); this.skipStepButton = this.page.getByRole("button", { name: /跳过此步骤/ }); this.platformCheckboxes = this.page.locator(".grid.gap-3 button"); this.selectAllButton = this.page.getByRole("button", { name: "全选" }); this.queryFrequencyOptions = this.page.locator(".grid.gap-3 button"); this.healthScore = this.page.locator("text-7xl.font-bold"); this.healthLevelBadge = this.page.locator("text-base.px-4.py-1"); this.viewActionsButton = this.page.getByRole("button", { name: /查看行动建议/, }); this.completeButton = this.page.getByRole("button", { name: /完成设置/ }); this.progressSteps = this.page.locator( ".flex.items-center.justify-between .flex.flex-1.items-center", ); } async goto() { await this.page.goto("/onboarding"); } async loginAndGoToOnboarding() { const loginPage = new LoginPage(this.page); await loginPage.goto(); await loginPage.login(TEST_USER.email, TEST_USER.password); try { await this.page.waitForURL(/\/dashboard/, { timeout: 60000 }); } catch { const currentUrl = this.page.url(); if (!currentUrl.includes("/dashboard")) { await loginPage.goto(); await loginPage.login(TEST_USER.email, TEST_USER.password); await this.page.waitForURL(/\/dashboard/, { timeout: 60000 }); } } await this.page.waitForLoadState("networkidle"); await this.page.goto("/onboarding"); await this.page.waitForLoadState("networkidle"); } async fillBrandName(name: string) { await this.brandNameInput.fill(name); } async clickStartAnalysis() { await this.startAnalysisButton.click(); } async selectCompetitor(name: string) { const competitorCard = this.page .locator(".border.rounded-lg") .filter({ hasText: name }); await competitorCard.click(); } async selectPlatform(platformName: string) { const platformCard = this.page .locator(".grid.gap-3 button") .filter({ hasText: platformName }); await platformCard.click(); } async selectQueryFrequency(frequency: string) { await this.queryFrequencyOptions.filter({ hasText: frequency }).click(); } } describe("新用户引导向导 - 完整流程测试", () => { test.beforeEach(async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.loginAndGoToOnboarding(); }); test("Step 1: 应该显示品牌名称输入页面", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await expect( page.getByRole("heading", { name: /输入您的品牌名称/ }), ).toBeVisible(); await expect(onboardingPage.brandNameInput).toBeVisible(); await expect(onboardingPage.startAnalysisButton).toBeVisible(); await expect(onboardingPage.skipToDashboardButton).toBeVisible(); await expect(onboardingPage.progressSteps).toHaveCount(5); }); test("Step 1: 品牌名称验证 - 太短应显示错误", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("a"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByText(/至少需要2个字符/)).toBeVisible(); }); test("Step 1: 正确输入品牌名称应进入下一步", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); }); test("Step 2: 可以选择竞品并继续", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await page.waitForTimeout(2000); const firstCompetitor = page .locator(".border.rounded-lg") .filter({ has: page.locator(".flex.h-5.w-5") }) .first(); if (await firstCompetitor.isVisible()) { await firstCompetitor.click(); } await onboardingPage.nextButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); }); test("Step 2: 跳过应进入下一步", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await onboardingPage.skipStepButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); }); test("Step 3: 平台默认全选", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await onboardingPage.skipStepButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); await expect(page.getByText(/\d+\/\d+ 个平台/)).toBeVisible(); }); test("Step 3: 可以选择不同频率", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await onboardingPage.skipStepButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); await onboardingPage.selectQueryFrequency("每日"); await expect(page.locator(".border-primary.bg-primary\\/5")).toBeVisible(); }); test("Step 3: 返回上一步", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await onboardingPage.skipStepButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); await onboardingPage.backButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); }); test("Step 4: 跳过直接进入Dashboard", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await expect( page.getByRole("heading", { name: /输入您的品牌名称/ }), ).toBeVisible(); await onboardingPage.skipToDashboardButton.click(); await expect(page).toHaveURL(/\/dashboard/, { timeout: 15000 }); }); }); describe("新用户引导向导 - 响应式设计测试", () => { test("移动端视图应该正常显示", async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); const onboardingPage = new OnboardingPage(page); await onboardingPage.loginAndGoToOnboarding(); await expect( page.getByRole("heading", { name: /输入您的品牌名称/ }), ).toBeVisible(); await expect(onboardingPage.startAnalysisButton).toBeVisible(); }); test("平板视图应该正常显示", async ({ page }) => { await page.setViewportSize({ width: 768, height: 1024 }); const onboardingPage = new OnboardingPage(page); await onboardingPage.loginAndGoToOnboarding(); await expect( page.getByRole("heading", { name: /输入您的品牌名称/ }), ).toBeVisible(); }); }); describe("新用户引导向导 - 进度指示器测试", () => { test.beforeEach(async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.loginAndGoToOnboarding(); }); test("初始应显示Step 1为当前步骤", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); const firstStepIndicator = page .locator(".flex.flex-col.items-center") .first(); await expect( firstStepIndicator.locator(".border-primary.bg-primary\\/10"), ).toBeVisible(); }); test("完成Step 1后Step 2应为当前步骤", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.goto(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); const secondStepIndicator = page .locator(".flex.flex-col.items-center") .nth(1); await expect(secondStepIndicator.locator(".border-primary")).toBeVisible(); }); }); describe("新用户引导向导 - 健康等级颜色测试", () => { test("健康等级应使用正确的颜色", async ({ page }) => { const onboardingPage = new OnboardingPage(page); await onboardingPage.loginAndGoToOnboarding(); await onboardingPage.fillBrandName("华为"); await onboardingPage.startAnalysisButton.click(); await expect(page.getByRole("heading", { name: /确认竞品/ })).toBeVisible({ timeout: 10000, }); await onboardingPage.skipStepButton.click(); await expect( page.getByRole("heading", { name: /选择监控平台/ }), ).toBeVisible({ timeout: 10000 }); await onboardingPage.selectPlatform("文心一言"); await expect(onboardingPage.nextButton).toBeEnabled({ timeout: 10000 }); await onboardingPage.nextButton.click(); await page.waitForTimeout(2000); const healthLabels = ["优秀", "良好", "及格", "危险"]; for (const label of healthLabels) { const labelElement = page.getByText(label); if (await labelElement.isVisible()) { break; } } }); });