/** * 登录流程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/') }) })