fix: 修复前端登录体验和API调用问题
- 修复路由守卫:未登录时直接跳转,不显示提示信息 - 修复API拦截器:401错误直接跳转,无需确认 - 移除不必要的ElMessageBox确认框 - 优化Token过期处理逻辑 - 修复文件管理API引入路径和URL前缀 - 修复调拨/回收管理API端点不匹配问题 - 修复通知管理API方法不匹配问题 - 统一系统配置API路径为单数形式 影响文件: - src/router/index.ts - src/api/request.ts - src/api/file.ts - src/api/index.ts 测试状态: - 前端构建通过 - 所有API路径已验证 - 登录流程测试通过 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
364
tests/e2e/assets.spec.ts
Normal file
364
tests/e2e/assets.spec.ts
Normal file
@@ -0,0 +1,364 @@
|
||||
/**
|
||||
* 资产管理E2E测试
|
||||
*
|
||||
* 测试内容:
|
||||
* - 资产列表查看
|
||||
* - 创建资产
|
||||
* - 编辑资产
|
||||
* - 删除资产
|
||||
* - 资产搜索
|
||||
* - 资产分配
|
||||
* - 批量导入
|
||||
* - 扫码查询
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('资产管理E2E测试', () => {
|
||||
// 在每个测试前登录
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
})
|
||||
|
||||
test('应该显示资产列表', async ({ page }) => {
|
||||
// 导航到资产列表页
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 等待列表加载
|
||||
await expect(page.locator('.asset-list')).toBeVisible()
|
||||
await expect(page.locator('.el-table')).toBeVisible()
|
||||
|
||||
// 验证统计数据
|
||||
await expect(page.locator('.asset-statistics')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该搜索资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 输入搜索关键词
|
||||
await page.fill('input[placeholder="搜索资产编码/名称/型号"]', '联想')
|
||||
await page.click('button:has-text("搜索")')
|
||||
|
||||
// 等待搜索结果
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// 验证搜索结果
|
||||
const tableRows = await page.locator('.el-table__body-wrapper .el-table__row').count()
|
||||
expect(tableRows).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
test('应该创建新资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 点击创建按钮
|
||||
await page.click('button:has-text("新增资产")')
|
||||
|
||||
// 等待对话框打开
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 填写表单
|
||||
await page.selectOption('select[name="deviceType"]', '1')
|
||||
await page.fill('input[name="assetName"]', '测试资产-E2E')
|
||||
await page.fill('input[name="model"]', '测试型号')
|
||||
await page.fill('input[name="serialNumber"]', 'SN-E2E-001')
|
||||
await page.selectOption('select[name="organization"]', '1')
|
||||
await page.fill('input[name="location"]', '测试位置')
|
||||
|
||||
// 如果有动态字段
|
||||
await page.fill('input[name="cpu"]', 'Intel i5-10400')
|
||||
await page.selectOption('select[name="memory"]', '16')
|
||||
|
||||
// 提交表单
|
||||
await page.click('button:has-text("确定")')
|
||||
|
||||
// 等待成功提示
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
await expect(page.locator('.el-message--success')).toContainText('创建成功')
|
||||
|
||||
// 验证新资产出现在列表中
|
||||
await expect(page.locator('text=测试资产-E2E')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该编辑资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 点击第一行的编辑按钮
|
||||
await page.click('.el-table__row:first-child .edit-button')
|
||||
|
||||
// 等待编辑对话框
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 修改资产名称
|
||||
await page.fill('input[name="assetName"]', '更新后的资产名称')
|
||||
|
||||
// 提交修改
|
||||
await page.click('button:has-text("确定")')
|
||||
|
||||
// 等待成功提示
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
|
||||
// 验证修改已生效
|
||||
await expect(page.locator('text=更新后的资产名称')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该删除资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 获取初始行数
|
||||
const initialRows = await page.locator('.el-table__body-wrapper .el-table__row').count()
|
||||
|
||||
// 点击第一行的删除按钮
|
||||
await page.click('.el-table__row:first-child .delete-button')
|
||||
|
||||
// 确认删除
|
||||
await page.click('.el-message-box__btns button:has-text("确定")')
|
||||
|
||||
// 等待成功提示
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
|
||||
// 验证行数减少
|
||||
const finalRows = await page.locator('.el-table__body-wrapper .el-table__row').count()
|
||||
expect(finalRows).toBe(initialRows - 1)
|
||||
})
|
||||
|
||||
test('应该支持分页', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 等待列表加载
|
||||
await expect(page.locator('.el-table')).toBeVisible()
|
||||
|
||||
// 点击下一页
|
||||
await page.click('.el-pagination .btn-next')
|
||||
|
||||
// 等待加载
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// 验证页码改变
|
||||
const currentPage = await page.locator('.el-pager .number.active').textContent()
|
||||
expect(parseInt(currentPage || '0')).toBeGreaterThan(1)
|
||||
})
|
||||
|
||||
test('应该按状态筛选', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 选择状态筛选
|
||||
await page.click('.el-select:has-text="资产状态")')
|
||||
await page.click('text=使用中')
|
||||
|
||||
// 等待筛选结果
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// 验证筛选结果
|
||||
const statusCells = await page.locator('.el-table__body .el-table__cell:last-child').allTextContents()
|
||||
statusCells.forEach(status => {
|
||||
expect(status).toContain('使用中')
|
||||
})
|
||||
})
|
||||
|
||||
test('应该按设备类型筛选', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 选择设备类型筛选
|
||||
await page.click('.el-select:has-text="设备类型")')
|
||||
await page.click('text=计算机')
|
||||
|
||||
// 等待筛选结果
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// 验证筛选标签已显示
|
||||
await expect(page.locator('.filter-tag:has-text("计算机")')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该查看资产详情', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 点击第一行查看详情
|
||||
await page.click('.el-table__row:first-child .detail-button')
|
||||
|
||||
// 等待详情对话框
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 验证详情信息
|
||||
await expect(page.locator('.asset-detail')).toBeVisible()
|
||||
await expect(page.locator('.asset-detail .asset-code')).toBeVisible()
|
||||
await expect(page.locator('.asset-detail .status-history')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该批量导入资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 点击批量导入按钮
|
||||
await page.click('button:has-text("批量导入")')
|
||||
|
||||
// 等待上传对话框
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 选择文件
|
||||
const fileInput = page.locator('input[type="file"]')
|
||||
await fileInput.setInputFiles('tests/fixtures/test_assets.xlsx')
|
||||
|
||||
// 点击上传
|
||||
await page.click('button:has-text("确定")')
|
||||
|
||||
// 等待上传完成
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// 验证成功提示
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该导出资产', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 设置下载处理
|
||||
const downloadPromise = page.waitForEvent('download')
|
||||
|
||||
// 点击导出按钮
|
||||
await page.click('button:has-text("导出")')
|
||||
|
||||
// 等待下载开始
|
||||
const download = await downloadPromise
|
||||
|
||||
// 验证下载文件
|
||||
expect(download.suggestedFilename()).toMatch(/资产.*\.xlsx/)
|
||||
})
|
||||
|
||||
test('应该刷新列表', async ({ page }) => {
|
||||
await page.click('text=资产管理')
|
||||
await page.click('text=资产列表')
|
||||
|
||||
// 等待列表加载
|
||||
await expect(page.locator('.el-table')).toBeVisible()
|
||||
|
||||
// 点击刷新按钮
|
||||
await page.click('button:has-text("刷新")')
|
||||
|
||||
// 验证loading状态
|
||||
await expect(page.locator('.loading')).toBeVisible()
|
||||
|
||||
// 等待刷新完成
|
||||
await page.waitForSelector('.loading', { state: 'hidden' })
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('资产分配流程测试', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
})
|
||||
|
||||
test('应该创建资产分配单', async ({ page }) => {
|
||||
await page.click('text=资产分配')
|
||||
await page.click('text=分配列表')
|
||||
|
||||
// 点击创建分配单
|
||||
await page.click('button:has-text("新建分配单")')
|
||||
|
||||
// 等待对话框
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 选择目标网点
|
||||
await page.click('select[name="targetOrganization"]')
|
||||
await page.click('text=天河网点')
|
||||
|
||||
// 选择要分配的资产
|
||||
await page.click('.asset-selector button:has-text("选择资产")')
|
||||
|
||||
// 勾选资产
|
||||
await page.check('.asset-list .el-checkbox:first-child')
|
||||
|
||||
// 确认选择
|
||||
await page.click('button:has-text("确定")')
|
||||
|
||||
// 填写备注
|
||||
await page.fill('textarea[name="remark"]', '业务需要分配')
|
||||
|
||||
// 提交分配单
|
||||
await page.click('button:has-text("提交")')
|
||||
|
||||
// 验证成功
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该审批分配单', async ({ page }) => {
|
||||
await page.click('text=资产分配')
|
||||
await page.click('text=待审批')
|
||||
|
||||
// 点击第一条记录的审批按钮
|
||||
await page.click('.allocation-item:first-child .approve-button')
|
||||
|
||||
// 等待审批对话框
|
||||
await expect(page.locator('.el-dialog')).toBeVisible()
|
||||
|
||||
// 选择审批结果
|
||||
await page.click('input[value="approved"]')
|
||||
|
||||
// 填写审批意见
|
||||
await page.fill('textarea[name="approvalRemark"]', '同意分配')
|
||||
|
||||
// 提交审批
|
||||
await page.click('button:has-text("确定")')
|
||||
|
||||
// 验证成功
|
||||
await expect(page.locator('.el-message--success')).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('扫码查询测试', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
})
|
||||
|
||||
test('应该扫码查询资产', async ({ page }) => {
|
||||
// 导航到扫码页面
|
||||
await page.click('text=扫码查询')
|
||||
|
||||
// 等待摄像头权限请求
|
||||
// 在测试环境中我们模拟扫码
|
||||
|
||||
// 手动输入资产编码模拟扫码结果
|
||||
await page.click('button:has-text("手动输入")')
|
||||
await page.fill('input[name="assetCode"]', 'ASSET-20250124-0001')
|
||||
await page.click('button:has-text("查询")')
|
||||
|
||||
// 验证资产详情显示
|
||||
await expect(page.locator('.asset-detail')).toBeVisible()
|
||||
await expect(page.locator('text=ASSET-20250124-0001')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该处理不存在的资产编码', async ({ page }) => {
|
||||
await page.click('text=扫码查询')
|
||||
await page.click('button:has-text("手动输入")')
|
||||
await page.fill('input[name="assetCode"]', 'INVALID-CODE')
|
||||
await page.click('button:has-text("查询")')
|
||||
|
||||
// 验证错误提示
|
||||
await expect(page.locator('.el-message--error')).toBeVisible()
|
||||
await expect(page.locator('.el-message--error')).toContainText('资产不存在')
|
||||
})
|
||||
})
|
||||
29
tests/e2e/global-setup.ts
Normal file
29
tests/e2e/global-setup.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Playwright E2E测试 - 全局设置
|
||||
*
|
||||
* 在所有测试运行前执行
|
||||
*/
|
||||
|
||||
import { FullConfig } from '@playwright/test'
|
||||
|
||||
async function globalSetup(config: FullConfig) {
|
||||
console.log('🚀 开始E2E测试全局设置...')
|
||||
|
||||
// 可以在这里进行测试前的准备工作:
|
||||
// 1. 启动测试数据库
|
||||
// 2. 运行数据库迁移
|
||||
// 3. 准备测试数据
|
||||
// 4. 启动后端服务
|
||||
// 5. 启动前端服务(通常由playwright.config.ts配置)
|
||||
|
||||
const baseURL = config.projects?.[0]?.use?.baseURL || 'http://localhost:5173'
|
||||
|
||||
console.log(`📝 测试基础URL: ${baseURL}`)
|
||||
|
||||
// 等待服务启动
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
|
||||
console.log('✅ E2E测试全局设置完成!')
|
||||
}
|
||||
|
||||
export default globalSetup
|
||||
26
tests/e2e/global-teardown.ts
Normal file
26
tests/e2e/global-teardown.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Playwright E2E测试 - 全局清理
|
||||
*
|
||||
* 在所有测试运行后执行
|
||||
*/
|
||||
|
||||
import { FullConfig } from '@playwright/test'
|
||||
|
||||
async function globalTeardown(config: FullConfig) {
|
||||
console.log('🧹 开始E2E测试全局清理...')
|
||||
|
||||
// 可以在这里进行测试后的清理工作:
|
||||
// 1. 清理测试数据库
|
||||
// 2. 关闭测试服务
|
||||
// 3. 删除临时文件
|
||||
// 4. 归档测试报告
|
||||
|
||||
console.log('📊 生成测试报告摘要...')
|
||||
|
||||
// 这里可以添加报告汇总逻辑
|
||||
|
||||
console.log('✅ E2E测试全局清理完成!')
|
||||
console.log('📄 测试报告位于: test_reports/playwright-report/index.html')
|
||||
}
|
||||
|
||||
export default globalTeardown
|
||||
258
tests/e2e/login.spec.ts
Normal file
258
tests/e2e/login.spec.ts
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* 登录流程E2E测试
|
||||
*
|
||||
* 测试内容:
|
||||
* - 正常登录流程
|
||||
* - 错误密码处理
|
||||
* - 验证码验证
|
||||
* - Token过期处理
|
||||
* - 记住密码功能
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('登录流程测试', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('http://localhost:5173/login')
|
||||
})
|
||||
|
||||
test('应该成功登录并跳转到首页', async ({ page }) => {
|
||||
// 输入用户名和密码
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
|
||||
// 输入验证码 (假设测试环境验证码固定为1234)
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
|
||||
// 点击登录按钮
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 等待跳转
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
|
||||
// 验证URL已跳转到首页
|
||||
expect(page.url()).toBe('http://localhost:5173/')
|
||||
|
||||
// 验证显示了用户信息
|
||||
await expect(page.locator('.user-info')).toBeVisible()
|
||||
await expect(page.locator('.user-info')).toContainText('admin')
|
||||
})
|
||||
|
||||
test('应该显示用户名或密码错误', async ({ page }) => {
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'WrongPassword')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 等待错误消息显示
|
||||
await expect(page.locator('.el-message--error')).toBeVisible()
|
||||
await expect(page.locator('.el-message--error')).toContainText('用户名或密码错误')
|
||||
})
|
||||
|
||||
test('应该验证必填字段', async ({ page }) => {
|
||||
// 不填写任何字段直接提交
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 验证表单验证错误
|
||||
await expect(page.locator('input[name="username"] + .el-form-item__error')).toBeVisible()
|
||||
await expect(page.locator('input[name="password"] + .el-form-item__error')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该验证用户名格式', async ({ page }) => {
|
||||
// 输入无效用户名
|
||||
await page.fill('input[name="username"]', 'ab') // 太短
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 应该显示用户名格式错误
|
||||
await expect(page.locator('.el-form-item__error')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该验证密码强度', async ({ page }) => {
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'weak') // 弱密码
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 应该显示密码强度错误
|
||||
await expect(page.locator('.el-form-item__error')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该刷新验证码', async ({ page }) => {
|
||||
const captchaImage = page.locator('.captcha-image img')
|
||||
|
||||
// 获取初始验证码图片URL
|
||||
const initialSrc = await captchaImage.getAttribute('src')
|
||||
|
||||
// 点击刷新验证码
|
||||
await page.click('.refresh-captcha')
|
||||
|
||||
// 等待图片重新加载
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// 验证验证码已更新
|
||||
const newSrc = await captchaImage.getAttribute('src')
|
||||
expect(newSrc).not.toBe(initialSrc)
|
||||
})
|
||||
|
||||
test('应该支持记住密码功能', async ({ page }) => {
|
||||
// 勾选记住密码
|
||||
await page.check('input[name="remember"]')
|
||||
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
|
||||
// 验证localStorage中保存了用户信息
|
||||
const rememberedUser = await page.evaluate(() => {
|
||||
return localStorage.getItem('rememberedUser')
|
||||
})
|
||||
|
||||
expect(rememberedUser).toBeTruthy()
|
||||
|
||||
// 退出登录
|
||||
await page.click('.logout-button')
|
||||
|
||||
// 返回登录页
|
||||
await page.goto('http://localhost:5173/login')
|
||||
|
||||
// 验证用户名已填充
|
||||
const username = await page.inputValue('input[name="username"]')
|
||||
expect(username).toBe('admin')
|
||||
})
|
||||
|
||||
test('应该处理验证码错误', async ({ page }) => {
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '9999') // 错误验证码
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 应该显示验证码错误
|
||||
await expect(page.locator('.el-message--error')).toBeVisible()
|
||||
await expect(page.locator('.el-message--error')).toContainText('验证码错误')
|
||||
})
|
||||
|
||||
test('应该限制登录尝试次数', async ({ page }) => {
|
||||
// 尝试多次错误登录
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'WrongPassword')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.waitForTimeout(500)
|
||||
}
|
||||
|
||||
// 第6次应该被锁定
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.el-message--error')).toBeVisible()
|
||||
await expect(page.locator('.el-message--error')).toContainText('账户已锁定')
|
||||
})
|
||||
|
||||
test('应该支持回车键登录', async ({ page }) => {
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
|
||||
// 在密码框按回车
|
||||
await page.press('input[name="password"]', 'Enter')
|
||||
|
||||
// 应该提交登录
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
expect(page.url()).toBe('http://localhost:5173/')
|
||||
})
|
||||
|
||||
test('应该处理网络错误', async ({ page, context }) => {
|
||||
// 模拟网络断开
|
||||
await context.setOffline(true)
|
||||
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// 应该显示网络错误
|
||||
await expect(page.locator('.el-message--error')).toBeVisible()
|
||||
await expect(page.locator('.el-message--error')).toContainText('网络错误')
|
||||
|
||||
// 恢复网络
|
||||
await context.setOffline(false)
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Token过期处理', () => {
|
||||
test('应该在Token过期时自动刷新', async ({ page }) => {
|
||||
// 登录
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
|
||||
// 模拟Token过期(通过设置过期Token)
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('token', 'expired_token')
|
||||
localStorage.setItem('refreshToken', 'valid_refresh_token')
|
||||
})
|
||||
|
||||
// 刷新页面
|
||||
await page.reload()
|
||||
|
||||
// 应该自动刷新Token并正常显示
|
||||
await expect(page.locator('.user-info')).toBeVisible()
|
||||
})
|
||||
|
||||
test('应该在刷新Token失败时跳转登录页', async ({ page }) => {
|
||||
await page.goto('http://localhost:5173/')
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('token', 'expired_token')
|
||||
localStorage.setItem('refreshToken', 'expired_refresh_token')
|
||||
})
|
||||
|
||||
// 刷新页面
|
||||
await page.reload()
|
||||
|
||||
// 应该跳转到登录页
|
||||
await page.waitForURL('http://localhost:5173/login')
|
||||
expect(page.url()).toBe('http://localhost:5173/login')
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('跨浏览器测试', () => {
|
||||
test('应该在Chrome中正常工作', async ({ page, browserName }) => {
|
||||
test.skip(browserName !== 'chromium')
|
||||
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
expect(page.url()).toBe('http://localhost:5173/')
|
||||
})
|
||||
|
||||
test('应该在Firefox中正常工作', async ({ page, browserName }) => {
|
||||
test.skip(browserName !== 'firefox')
|
||||
|
||||
await page.goto('http://localhost:5173/login')
|
||||
await page.fill('input[name="username"]', 'admin')
|
||||
await page.fill('input[name="password"]', 'Admin123')
|
||||
await page.fill('input[name="captcha"]', '1234')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.waitForURL('http://localhost:5173/')
|
||||
expect(page.url()).toBe('http://localhost:5173/')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user