初始化
Some checks failed
CI/CD Pipeline / 测试 (18.x) (push) Has been cancelled
CI/CD Pipeline / 测试 (20.x) (push) Has been cancelled
CI/CD Pipeline / 安全检查 (push) Has been cancelled
CI/CD Pipeline / 部署 (push) Has been cancelled
CI/CD Pipeline / 通知 (push) Has been cancelled

This commit is contained in:
2025-11-03 19:47:36 +08:00
parent 7a04b85667
commit f25b0307db
454 changed files with 37064 additions and 4544 deletions

View File

@@ -0,0 +1,72 @@
const { chromium } = require('@playwright/test')
async function globalSetup(config) {
console.log('🚀 开始全局设置...')
// 获取浏览器实例
const browser = await chromium.launch()
const context = await browser.newContext()
const page = await context.newPage()
try {
// 设置测试数据
await setupTestData(page)
// 设置用户认证
await setupAuthentication(page)
// 设置测试环境变量
await setupEnvironmentVariables()
console.log('✅ 全局设置完成')
} catch (error) {
console.error('❌ 全局设置失败:', error)
throw error
} finally {
await context.close()
await browser.close()
}
}
async function setupTestData(page) {
console.log('📊 设置测试数据...')
// 这里可以设置测试数据,例如:
// 1. 创建测试用户
// 2. 准备测试产品数据
// 3. 设置测试类别等
// 示例通过API设置测试数据
// await page.goto('/api/test/setup')
// await page.waitForResponse(response => response.status() === 200)
}
async function setupAuthentication(page) {
console.log('🔐 设置用户认证...')
// 这里可以设置测试用户认证,例如:
// 1. 创建测试用户
// 2. 登录测试用户
// 3. 保存认证令牌
// 示例通过API登录
// await page.goto('/api/auth/login')
// await page.fill('[data-testid="username"]', 'testuser')
// await page.fill('[data-testid="password"]', 'testpassword')
// await page.click('[data-testid="login-button"]')
// await page.waitForResponse(response => response.status() === 200)
// 保存认证状态
// await context.storageState({ path: 'test-auth-state.json' })
}
async function setupEnvironmentVariables() {
console.log('🌍 设置环境变量...')
// 设置测试环境变量
process.env.TEST_MODE = 'true'
process.env.API_BASE_URL = 'http://localhost:7001/api'
process.env.TEST_TIMEOUT = '30000'
}
module.exports = globalSetup

View File

@@ -0,0 +1,120 @@
const { chromium } = require('@playwright/test')
async function globalTeardown(config) {
console.log('🧹 开始全局清理...')
// 获取浏览器实例
const browser = await chromium.launch()
const context = await browser.newContext()
const page = await context.newPage()
try {
// 清理测试数据
await cleanupTestData(page)
// 清理用户认证
await cleanupAuthentication()
// 清理环境变量
await cleanupEnvironmentVariables()
// 清理测试文件
await cleanupTestFiles()
console.log('✅ 全局清理完成')
} catch (error) {
console.error('❌ 全局清理失败:', error)
throw error
} finally {
await context.close()
await browser.close()
}
}
async function cleanupTestData(page) {
console.log('📊 清理测试数据...')
// 这里可以清理测试数据,例如:
// 1. 删除测试用户
// 2. 清理测试产品数据
// 3. 重置测试类别等
// 示例通过API清理测试数据
// await page.goto('/api/test/cleanup')
// await page.waitForResponse(response => response.status() === 200)
}
async function cleanupAuthentication() {
console.log('🔐 清理用户认证...')
// 这里可以清理用户认证,例如:
// 1. 删除测试用户
// 2. 清理认证令牌
// 示例:删除认证状态文件
// const fs = require('fs')
// if (fs.existsSync('test-auth-state.json')) {
// fs.unlinkSync('test-auth-state.json')
// }
}
async function cleanupEnvironmentVariables() {
console.log('🌍 清理环境变量...')
// 清理测试环境变量
delete process.env.TEST_MODE
delete process.env.API_BASE_URL
delete process.env.TEST_TIMEOUT
}
async function cleanupTestFiles() {
console.log('📁 清理测试文件...')
// 清理测试生成的文件
const fs = require('fs')
const path = require('path')
// 清理测试报告目录
const reportDirs = ['test-results', 'playwright-report']
reportDirs.forEach(dir => {
const dirPath = path.resolve(process.cwd(), dir)
if (fs.existsSync(dirPath)) {
// 保留目录,但清理其中的文件
const files = fs.readdirSync(dirPath)
files.forEach(file => {
const filePath = path.join(dirPath, file)
const stat = fs.statSync(filePath)
if (stat.isDirectory()) {
// 递归删除子目录
deleteFolderRecursive(filePath)
} else {
// 删除文件
fs.unlinkSync(filePath)
}
})
}
})
}
// 递归删除文件夹
function deleteFolderRecursive(folderPath) {
const fs = require('fs')
const path = require('path')
if (fs.existsSync(folderPath)) {
fs.readdirSync(folderPath).forEach(file => {
const curPath = path.join(folderPath, file)
if (fs.lstatSync(curPath).isDirectory()) {
// 递归删除子目录
deleteFolderRecursive(curPath)
} else {
// 删除文件
fs.unlinkSync(curPath)
}
})
fs.rmdirSync(folderPath)
}
}
module.exports = globalTeardown

View File

@@ -0,0 +1,315 @@
import { test, expect, chromium } from '@playwright/test'
test.describe('用户旅程测试', () => {
let browser
let context
let page
test.beforeAll(async () => {
// 启动浏览器
browser = await chromium.launch()
})
test.afterAll(async () => {
// 关闭浏览器
await browser.close()
})
test.beforeEach(async () => {
// 创建新的浏览器上下文和页面
context = await browser.newContext()
page = await context.newPage()
// 设置视口大小
await page.setViewportSize({ width: 1280, height: 720 })
})
test.afterEach(async () => {
// 关闭浏览器上下文
await context.close()
})
test('用户应该能够浏览首页并选择产品类别', async () => {
// 访问首页
await page.goto('/')
// 检查页面标题
await expect(page).toHaveTitle(/硬件性能排行榜/)
// 检查应用标题
await expect(page.locator('.header__title')).toContainText('硬件性能排行榜')
// 等待类别卡片加载
await page.waitForSelector('.category-card')
// 检查类别卡片数量
const categoryCards = await page.locator('.category-card').count()
expect(categoryCards).toBeGreaterThan(0)
// 点击第一个类别卡片
await page.locator('.category-card').first().click()
// 检查是否跳转到类别排名页面
await expect(page).toHaveURL(/\/category\/\d+/)
// 检查页面标题是否更新为类别名称
const categoryName = await page.locator('.page-title').textContent()
expect(categoryName).toBeTruthy()
})
test('用户应该能够浏览产品排名列表', async () => {
// 直接访问类别排名页面
await page.goto('/category/1')
// 等待产品列表加载
await page.waitForSelector('.product-card')
// 检查产品卡片数量
const productCards = await page.locator('.product-card').count()
expect(productCards).toBeGreaterThan(0)
// 检查排名显示
const firstProductRank = await page.locator('.product-card').first().locator('.product-rank').textContent()
expect(firstProductRank).toContain('#1')
// 点击第一个产品卡片
await page.locator('.product-card').first().click()
// 检查是否跳转到产品详情页面
await expect(page).toHaveURL(/\/product\/\d+/)
// 检查产品详情页面内容
await expect(page.locator('.product-detail')).toBeVisible()
await expect(page.locator('.product-name')).toBeVisible()
await expect(page.locator('.product-specs')).toBeVisible()
})
test('用户应该能够使用搜索功能查找产品', async () => {
// 访问类别排名页面
await page.goto('/category/1')
// 等待搜索框加载
await page.waitForSelector('.search-input')
// 输入搜索关键词
await page.fill('.search-input', 'Intel')
// 点击搜索按钮
await page.click('.search-button')
// 等待搜索结果加载
await page.waitForSelector('.product-card')
// 检查搜索结果
const productCards = await page.locator('.product-card').count()
expect(productCards).toBeGreaterThan(0)
// 检查搜索结果是否包含搜索关键词
const firstProductName = await page.locator('.product-card').first().locator('.product-name').textContent()
expect(firstProductName.toLowerCase()).toContain('intel'.toLowerCase())
})
test('用户应该能够使用筛选功能过滤产品', async () => {
// 访问类别排名页面
await page.goto('/category/1')
// 等待筛选器加载
await page.waitForSelector('.product-filter')
// 选择品牌筛选
await page.selectOption('.brand-filter', 'Intel')
// 设置性能分数范围
await page.fill('.min-score-input', '5000')
await page.fill('.max-score-input', '10000')
// 点击应用筛选按钮
await page.click('.apply-filter-button')
// 等待筛选结果加载
await page.waitForSelector('.product-card')
// 检查筛选结果
const productCards = await page.locator('.product-card').count()
expect(productCards).toBeGreaterThan(0)
// 检查第一个产品的品牌
const firstProductBrand = await page.locator('.product-card').first().locator('.product-brand').textContent()
expect(firstProductBrand).toContain('Intel')
})
test('用户应该能够使用排序功能对产品进行排序', async () => {
// 访问类别排名页面
await page.goto('/category/1')
// 等待排序选择器加载
await page.waitForSelector('.sort-select')
// 选择按性能分数降序排序
await page.selectOption('.sort-select', 'score-desc')
// 等待排序结果加载
await page.waitForSelector('.product-card')
// 检查第一个产品的性能分数是否最高
const firstProductScore = await page.locator('.product-card').first().locator('.product-score').textContent()
const secondProductScore = await page.locator('.product-card').nth(1).locator('.product-score').textContent()
// 提取数字部分进行比较
const firstScore = parseInt(firstProductScore.replace(/[^0-9]/g, ''))
const secondScore = parseInt(secondProductScore.replace(/[^0-9]/g, ''))
expect(firstScore).toBeGreaterThanOrEqual(secondScore)
})
test('用户应该能够选择产品进行对比', async () => {
// 访问类别排名页面
await page.goto('/category/1')
// 等待产品列表加载
await page.waitForSelector('.product-card')
// 选择第一个产品的复选框
await page.check('.product-card').first().locator('.compare-checkbox')
// 选择第二个产品的复选框
await page.check('.product-card').nth(1).locator('.compare-checkbox')
// 点击对比按钮
await page.click('.compare-button')
// 检查是否跳转到产品对比页面
await expect(page).toHaveURL(/\/compare/)
// 检查对比页面内容
await expect(page.locator('.comparison-table')).toBeVisible()
await expect(page.locator('.comparison-chart')).toBeVisible()
})
test('用户应该能够查看性能监控页面', async () => {
// 访问性能监控页面
await page.goto('/monitor')
// 等待页面加载
await page.waitForSelector('.monitor-dashboard')
// 检查性能指标卡片
await expect(page.locator('.metric-card')).toBeVisible()
// 检查性能图表
await expect(page.locator('.performance-chart')).toBeVisible()
// 检查系统状态
await expect(page.locator('.system-status')).toBeVisible()
})
test('用户应该能够在移动设备上正常使用应用', async () => {
// 设置移动设备视口
await page.setViewportSize({ width: 375, height: 667 })
// 访问首页
await page.goto('/')
// 检查移动端菜单按钮
await expect(page.locator('.header__mobile-menu')).toBeVisible()
// 点击移动端菜单按钮
await page.click('.header__mobile-menu')
// 检查移动端菜单是否展开
await expect(page.locator('.mobile-menu')).toBeVisible()
// 点击类别卡片
await page.click('.category-card').first()
// 检查是否跳转到类别排名页面
await expect(page).toHaveURL(/\/category\/\d+/)
// 检查移动端产品列表布局
await expect(page.locator('.product-card')).toBeVisible()
// 检查移动端筛选器
await expect(page.locator('.mobile-filter')).toBeVisible()
})
test('用户应该能够处理网络错误', async () => {
// 模拟网络错误
await page.route('**/api/**', route => route.abort())
// 访问首页
await page.goto('/')
// 等待错误提示
await page.waitForSelector('.error-message')
// 检查错误提示内容
await expect(page.locator('.error-message')).toContainText('网络错误')
// 点击重试按钮
await page.click('.retry-button')
// 恢复网络连接
await page.unroute('**/api/**')
// 检查页面是否恢复正常
await page.waitForSelector('.category-card')
await expect(page.locator('.category-card')).toBeVisible()
})
test('用户应该能够使用页面导航', async () => {
// 访问首页
await page.goto('/')
// 点击导航栏中的性能监控链接
await page.click('[data-testid="monitor-button"]')
// 检查是否跳转到性能监控页面
await expect(page).toHaveURL('/monitor')
// 点击浏览器后退按钮
await page.goBack()
// 检查是否返回到首页
await expect(page).toHaveURL('/')
// 点击浏览器前进按钮
await page.goForward()
// 检查是否前进到性能监控页面
await expect(page).toHaveURL('/monitor')
})
test('用户应该能够使用分页功能浏览更多产品', async () => {
// 访问类别排名页面
await page.goto('/category/1')
// 等待产品列表和分页组件加载
await page.waitForSelector('.product-card')
await page.waitForSelector('.pagination')
// 记录第一页的产品
const firstPageProducts = await page.locator('.product-card').allTextContents()
// 点击下一页按钮
await page.click('.pagination-next')
// 等待新页面加载
await page.waitForSelector('.product-card')
// 记录第二页的产品
const secondPageProducts = await page.locator('.product-card').allTextContents()
// 检查两页的产品是否不同
expect(firstPageProducts).not.toEqual(secondPageProducts)
// 点击上一页按钮
await page.click('.pagination-prev')
// 等待页面加载
await page.waitForSelector('.product-card')
// 检查是否返回到第一页
const backToFirstPageProducts = await page.locator('.product-card').allTextContents()
expect(backToFirstPageProducts).toEqual(firstPageProducts)
})
})