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:
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