import { test, expect } from '@playwright/test'; test.describe('用户旅程:潜在客户了解产品并咨询', () => { test('UJ-001: 首页浏览 → 产品探索 → 咨询联系', async ({ page }) => { await test.step('步骤1: 访问首页', async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); await expect(page).toHaveTitle(/睿新致远/); await expect(page.locator('h1')).toBeVisible(); }); await test.step('步骤2: 查看产品矩阵区域', async () => { await page.locator('h2', { hasText: '产品矩阵' }).scrollIntoViewIfNeeded(); await expect(page.locator('h2', { hasText: '产品矩阵' })).toBeVisible(); const productCards = page.locator('a', { hasText: '了解详情' }); await expect(productCards.first()).toBeVisible(); }); await test.step('步骤3: 点击产品卡片进入详情页', async () => { await page.locator('a', { hasText: '睿新ERP管理系统' }).first().click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/products\//); await expect(page.locator('h1')).toBeVisible(); }); await test.step('步骤4: 点击"立即咨询"按钮', async () => { const consultButton = page.locator('a', { hasText: '立即咨询' }).first(); await expect(consultButton).toBeVisible(); await consultButton.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/contact/); }); await test.step('步骤5: 填写联系表单', async () => { await page.fill('[data-testid="name-input"]', '张三'); await page.fill('[data-testid="phone-input"]', '13800138000'); await page.fill('[data-testid="email-input"]', 'zhangsan@example.com'); await page.fill('[data-testid="subject-input"]', 'ERP产品咨询'); await page.fill('[data-testid="message-input"]', '我想了解贵公司的ERP产品,请提供更多详情和报价信息。'); }); }); }); test.describe('用户旅程:了解公司服务与解决方案', () => { test('UJ-002: 服务浏览 → 方案探索 → 了解公司', async ({ page }) => { await test.step('步骤1: 从首页导航到服务页', async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); await page.locator('a', { hasText: '服务' }).first().click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/services/); }); await test.step('步骤2: 查看服务列表', async () => { await expect(page.locator('h1', { hasText: '服务' })).toBeVisible(); const serviceCards = page.locator('a[href*="/services/"]'); const count = await serviceCards.count(); expect(count).toBeGreaterThanOrEqual(4); }); await test.step('步骤3: 进入服务详情页', async () => { await page.locator('a[href="/services/software"]').click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/services\/software/); await expect(page.locator('h1', { hasText: '软件开发' })).toBeVisible(); }); await test.step('步骤4: 导航到解决方案页', async () => { await page.locator('a', { hasText: '解决方案' }).first().click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/solutions/); }); await test.step('步骤5: 进入行业方案详情', async () => { const solutionLink = page.locator('a[href*="/solutions/"]').first(); await expect(solutionLink).toBeVisible(); await solutionLink.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/solutions\//); }); }); }); test.describe('用户旅程:阅读新闻了解公司动态', () => { test('UJ-003: 新闻列表 → 新闻详情 → 返回列表', async ({ page }) => { await test.step('步骤1: 访问新闻列表页', async () => { await page.goto('/news'); await page.waitForLoadState('networkidle'); await expect(page.locator('h1', { hasText: '新闻动态' })).toBeVisible(); }); await test.step('步骤2: 查看新闻列表内容', async () => { const newsCards = page.locator('a[href*="/news/"]'); const count = await newsCards.count(); expect(count).toBeGreaterThanOrEqual(2); }); await test.step('步骤3: 点击进入新闻详情', async () => { await page.locator('a[href="/news/company-founded"]').click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/news\/company-founded/); await expect(page.locator('h1')).toBeVisible(); }); await test.step('步骤4: 返回新闻列表', async () => { const backButton = page.locator('a', { hasText: '返回新闻列表' }).or( page.locator('button', { hasText: '返回新闻列表' }) ).first(); if (await backButton.isVisible()) { await backButton.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/news/); } }); }); }); test.describe('用户旅程:导航菜单探索全站', () => { test('UJ-004: 通过导航菜单访问所有主要页面', async ({ page }) => { const pages = [ { label: '服务', url: /\/services/ }, { label: '关于我们', url: /\/about/ }, { label: '联系我们', url: /\/contact/ }, ]; for (const pageInfo of pages) { await test.step(`导航到${pageInfo.label}页`, async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); const navLink = page.locator(`nav a:has-text("${pageInfo.label}")`).first(); await navLink.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(pageInfo.url); }); } }); test('UJ-005: 通过Mega Dropdown菜单访问产品详情', async ({ page }) => { await test.step('步骤1: 打开产品下拉菜单', async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); const productButton = page.locator('nav button:has-text("产品")'); await productButton.click(); await page.waitForTimeout(300); }); await test.step('步骤2: 点击下拉菜单中的产品链接', async () => { const erpLink = page.locator('nav a:has-text("ERP 管理系统")').first(); await expect(erpLink).toBeVisible(); await erpLink.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\/products\/erp/); }); }); }); test.describe('用户旅程:Cookie同意与隐私', () => { test('UJ-006: Cookie同意横幅交互', async ({ page }) => { await test.step('步骤1: 首次访问显示Cookie横幅', async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); const cookieBanner = page.locator('text=我们使用 Cookie'); await expect(cookieBanner).toBeVisible(); }); await test.step('步骤2: 点击"管理偏好"打开设置', async () => { const manageButton = page.locator('button:has-text("管理偏好")'); await manageButton.click(); await page.waitForTimeout(300); await expect(page.locator('h3:has-text("Cookie 偏好设置")')).toBeVisible(); }); await test.step('步骤3: 验证必要Cookie默认勾选且禁用', async () => { const necessaryCheckbox = page.locator('input[type="checkbox"]').first(); expect(await necessaryCheckbox.isChecked()).toBe(true); expect(await necessaryCheckbox.isDisabled()).toBe(true); }); await test.step('步骤4: 保存偏好后横幅消失', async () => { const saveButton = page.locator('button:has-text("保存偏好")'); await saveButton.click(); await page.waitForTimeout(500); const cookieBanner = page.locator('text=我们使用 Cookie'); await expect(cookieBanner).not.toBeVisible(); }); }); test('UJ-007: 点击"仅必要"接受必要Cookie', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); const necessaryButton = page.locator('button:has-text("仅必要")'); await necessaryButton.click(); await page.waitForTimeout(500); const cookieBanner = page.locator('text=我们使用 Cookie'); await expect(cookieBanner).not.toBeVisible(); }); test('UJ-008: 点击"接受所有"接受全部Cookie', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); const acceptAllButton = page.locator('button:has-text("接受所有")'); await acceptAllButton.click(); await page.waitForTimeout(500); const cookieBanner = page.locator('text=我们使用 Cookie'); await expect(cookieBanner).not.toBeVisible(); }); }); test.describe('用户旅程:联系表单验证', () => { test('UJ-009: 联系表单字段验证', async ({ page }) => { await page.goto('/contact'); await page.waitForLoadState('networkidle'); await test.step('步骤1: 空表单提交显示验证错误', async () => { await page.click('[data-testid="submit-button"]'); await page.waitForTimeout(500); const errorMessages = page.locator('[data-testid="name-error"], .text-destructive'); const count = await errorMessages.count(); expect(count).toBeGreaterThan(0); }); await test.step('步骤2: 无效手机号验证', async () => { await page.fill('[data-testid="phone-input"]', '12345678901'); await page.locator('[data-testid="phone-input"]').blur(); await page.waitForTimeout(300); }); await test.step('步骤3: 无效邮箱验证', async () => { await page.fill('[data-testid="email-input"]', 'invalid-email'); await page.locator('[data-testid="email-input"]').blur(); await page.waitForTimeout(300); }); await test.step('步骤4: 填写正确信息后可提交', async () => { await page.fill('[data-testid="name-input"]', '测试用户'); await page.fill('[data-testid="phone-input"]', '13800138000'); await page.fill('[data-testid="email-input"]', 'test@example.com'); await page.fill('[data-testid="subject-input"]', '产品咨询'); await page.fill('[data-testid="message-input"]', '我想了解贵公司的产品详情,请提供更多信息。'); await expect(page.locator('[data-testid="submit-button"]')).toBeEnabled(); }); }); }); test.describe('用户旅程:404页面与错误处理', () => { test('UJ-010: 访问不存在的页面显示404', async ({ page }) => { await page.goto('/nonexistent-page'); await page.waitForLoadState('networkidle'); await expect(page.locator('text=404')).toBeVisible(); await expect(page.locator('text=页面未找到')).toBeVisible(); await expect(page.locator('a:has-text("返回首页")')).toBeVisible(); }); test('UJ-011: 404页面导航功能正常', async ({ page }) => { await page.goto('/nonexistent-page'); await page.waitForLoadState('networkidle'); await page.locator('a:has-text("返回首页")').click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\//); }); }); test.describe('用户旅程:页脚导航', () => { test('UJ-012: 通过页脚链接导航到各页面', async ({ page }) => { const footerLinks = [ { text: '隐私政策', url: /\/privacy/ }, { text: '服务条款', url: /\/terms/ }, ]; for (const link of footerLinks) { await test.step(`点击页脚"${link.text}"链接`, async () => { await page.goto('/'); await page.waitForLoadState('networkidle'); await page.locator(`footer a:has-text("${link.text}")`).first().click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(link.url); }); } }); }); test.describe('用户旅程:面包屑导航', () => { test('UJ-013: 产品详情页面包屑导航', async ({ page }) => { await page.goto('/products/erp'); await page.waitForLoadState('networkidle'); await test.step('步骤1: 面包屑显示正确路径', async () => { const breadcrumb = page.locator('nav[aria-label="breadcrumb"]'); await expect(breadcrumb).toBeVisible(); await expect(breadcrumb.locator('text=返回首页')).toBeVisible(); }); await test.step('步骤2: 点击面包屑返回首页', async () => { await page.locator('nav[aria-label="breadcrumb"] a:has-text("返回首页")').click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/\//); }); }); }); test.describe('用户旅程:页面标题与SEO一致性', () => { const pagesWithTitle = [ { name: '产品列表', url: '/products', expectedTitle: '产品 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '服务列表', url: '/services', expectedTitle: '服务 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '解决方案', url: '/solutions', expectedTitle: '解决方案 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '关于我们', url: '/about', expectedTitle: '关于我们 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '联系我们', url: '/contact', expectedTitle: '联系我们 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '新闻动态', url: '/news', expectedTitle: '新闻动态 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '隐私政策', url: '/privacy', expectedTitle: '隐私政策 - 睿新致远 | 四川睿新致远科技有限公司' }, { name: '服务条款', url: '/terms', expectedTitle: '服务条款 - 睿新致远 | 四川睿新致远科技有限公司' }, ]; test('UJ-014: 所有页面标题无重复公司名', async ({ page }) => { for (const pageInfo of pagesWithTitle) { await page.goto(pageInfo.url); await page.waitForLoadState('networkidle'); const title = await page.title(); const companyNameCount = (title.match(/四川睿新致远科技有限公司/g) || []).length; expect(companyNameCount, `${pageInfo.name}页面标题中公司名出现${companyNameCount}次,应不超过1次`).toBeLessThanOrEqual(1); } }); test('UJ-015: 页面标题使用简体品牌名(非繁体)', async ({ page }) => { for (const pageInfo of pagesWithTitle) { await page.goto(pageInfo.url); await page.waitForLoadState('networkidle'); const title = await page.title(); expect(title, `${pageInfo.name}页面标题包含繁体字"遠"`).not.toContain('睿新致遠'); } }); }); test.describe('用户旅程:新闻筛选完整流程', () => { test('UJ-016: 新闻分类筛选→查看详情→返回列表', async ({ page }) => { await test.step('步骤1: 访问新闻列表页', async () => { await page.goto('/news'); await page.waitForLoadState('networkidle'); await expect(page.locator('h1', { hasText: '新闻动态' })).toBeVisible(); }); await test.step('步骤2: 验证初始显示全部新闻', async () => { const allNews = page.locator('a[href*="/news/"]'); const count = await allNews.count(); expect(count).toBeGreaterThanOrEqual(2); }); await test.step('步骤3: 点击"公司新闻"筛选', async () => { const companyNewsBtn = page.locator('button:has-text("公司新闻")'); await companyNewsBtn.click(); await page.waitForTimeout(500); const filteredNews = page.locator('a[href*="/news/"]'); const count = await filteredNews.count(); expect(count).toBe(1); const text = await filteredNews.first().textContent(); expect(text).toContain('公司新闻'); }); await test.step('步骤4: 切换到"产品发布"筛选', async () => { const productNewsBtn = page.locator('button:has-text("产品发布")'); await productNewsBtn.click(); await page.waitForTimeout(500); const filteredNews = page.locator('a[href*="/news/"]'); const count = await filteredNews.count(); expect(count).toBe(1); const text = await filteredNews.first().textContent(); expect(text).toContain('产品发布'); }); await test.step('步骤5: 点击"全部"恢复全部新闻', async () => { const allBtn = page.locator('button:has-text("全部")'); await allBtn.click(); await page.waitForTimeout(500); const allNews = page.locator('a[href*="/news/"]'); const count = await allNews.count(); expect(count).toBeGreaterThanOrEqual(2); }); await test.step('步骤6: 搜索功能筛选', async () => { const searchInput = page.locator('input[aria-label="搜索新闻"]'); await searchInput.fill('数字化转型'); await page.waitForTimeout(500); const filteredNews = page.locator('a[href*="/news/"]'); const count = await filteredNews.count(); expect(count).toBeGreaterThanOrEqual(1); }); }); }); test.describe('用户旅程:品牌视觉一致性', () => { test('UJ-017: Hero区域品牌标题使用青柳隷書字体展示繁体品牌名', async ({ page }) => { await page.goto('/'); await page.waitForLoadState('networkidle'); const brandElement = page.locator('.font-brand').first(); if (await brandElement.isVisible()) { const text = await brandElement.textContent(); expect(text).toContain('睿新致遠'); } }); test('UJ-018: 页面元数据使用简体品牌名', async ({ page }) => { await page.goto('/about'); await page.waitForLoadState('networkidle'); const title = await page.title(); expect(title).toContain('睿新致远'); expect(title).not.toContain('睿新致遠'); }); });