import { test, expect } from '@playwright/test'; import { LoginPage } from './pages/LoginPage'; import { DashboardPage } from './pages/DashboardPage'; import { TestHelper } from './utils/testHelper'; test.describe('认证异常场景测试', () => { let loginPage: LoginPage; let dashboardPage: DashboardPage; test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); dashboardPage = new DashboardPage(page); await loginPage.goto(); }); test.afterEach(async ({ page }) => { await TestHelper.clearAllStorage(page); }); test('登录失败 - 用户名为空', async ({ page }) => { await test.step('尝试使用空用户名登录', async () => { await loginPage.usernameInput.fill(''); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); }); await test.step('验证错误提示', async () => { await TestHelper.waitForElementVisible(page, '.el-form-item__error'); const errorMessage = await TestHelper.getElementText(page, '.el-form-item__error'); expect(errorMessage).toBeTruthy(); }); }); test('登录失败 - 密码为空', async ({ page }) => { await test.step('尝试使用空密码登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill(''); await loginPage.loginButton.click(); }); await test.step('验证错误提示', async () => { await TestHelper.waitForElementVisible(page, '.el-form-item__error'); const errorMessage = await TestHelper.getElementText(page, '.el-form-item__error'); expect(errorMessage).toBeTruthy(); }); }); test('登录失败 - 用户名和密码都为空', async ({ page }) => { await test.step('尝试使用空用户名和密码登录', async () => { await loginPage.usernameInput.fill(''); await loginPage.passwordInput.fill(''); await loginPage.loginButton.click(); }); await test.step('验证错误提示', async () => { const errorMessages = await page.locator('.el-form-item__error').all(); expect(errorMessages.length).toBeGreaterThan(0); }); }); test('登录失败 - 用户名不存在', async ({ page }) => { await test.step('尝试使用不存在的用户名登录', async () => { await loginPage.usernameInput.fill('nonexistentuser123456'); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); }); await test.step('验证错误消息', async () => { await TestHelper.waitForErrorMessage(page); const errorMessage = await TestHelper.getElementText(page, '.el-message__content'); expect(errorMessage).toContain('用户名或密码错误'); }); }); test('登录失败 - 密码错误', async ({ page }) => { await test.step('尝试使用错误的密码登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('wrongpassword'); await loginPage.loginButton.click(); }); await test.step('验证错误消息', async () => { await TestHelper.waitForErrorMessage(page); const errorMessage = await TestHelper.getElementText(page, '.el-message__content'); expect(errorMessage).toContain('用户名或密码错误'); }); }); test('登录失败 - 账户被锁定', async ({ page }) => { await test.step('连续多次登录失败', async () => { for (let i = 0; i < 5; i++) { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('wrongpassword'); await loginPage.loginButton.click(); await page.waitForTimeout(1000); await loginPage.usernameInput.fill(''); await loginPage.passwordInput.fill(''); } }); await test.step('验证账户锁定提示', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); await TestHelper.waitForErrorMessage(page); const errorMessage = await TestHelper.getElementText(page, '.el-message__content'); expect(errorMessage).toContain('账户已被锁定'); }); }); test('登录失败 - 账户被禁用', async ({ page, request }) => { await test.step('禁用admin账户', async () => { await request.put('http://localhost:8084/api/users/admin/status', { data: { status: '0' } }); }); await test.step('尝试使用被禁用的账户登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); }); await test.step('验证账户禁用提示', async () => { await TestHelper.waitForErrorMessage(page); const errorMessage = await TestHelper.getElementText(page, '.el-message__content'); expect(errorMessage).toContain('账户已被禁用'); }); await test.step('恢复admin账户状态', async () => { await request.put('http://localhost:8084/api/users/admin/status', { data: { status: '1' } }); }); }); test('登录失败 - Token过期', async ({ page }) => { await test.step('正常登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); await TestHelper.waitForUrl(page, /.*dashboard/); }); await test.step('设置过期的Token', async () => { await TestHelper.setLocalStorage(page, 'token', 'expired_token_123456'); await TestHelper.setLocalStorage(page, 'token_expires', '0'); }); await test.step('刷新页面验证Token过期', async () => { await page.reload(); await TestHelper.waitForPageLoad(page); }); await test.step('验证自动跳转到登录页面', async () => { await TestHelper.waitForUrl(page, /.*login/); await expect(page).toHaveURL(/.*login/); }); }); test('登录失败 - 无效的Token格式', async ({ page }) => { await test.step('设置无效的Token', async () => { await TestHelper.setLocalStorage(page, 'token', 'invalid_token_format'); }); await test.step('尝试访问需要认证的页面', async () => { await page.goto('/users'); await TestHelper.waitForPageLoad(page); }); await test.step('验证自动跳转到登录页面', async () => { await TestHelper.waitForUrl(page, /.*login/); await expect(page).toHaveURL(/.*login/); }); }); test('登出失败 - Token已失效', async ({ page }) => { await test.step('正常登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); await TestHelper.waitForUrl(page, /.*dashboard/); }); await test.step('清除Token', async () => { await TestHelper.clearLocalStorage(page); }); await test.step('尝试登出', async () => { const avatar = page.locator('.el-avatar'); if (await avatar.count() > 0) { await avatar.click(); await TestHelper.waitForElementVisible(page, '.el-dropdown-menu'); const logoutButton = page.locator('.el-dropdown-menu').getByText('退出登录'); if (await logoutButton.count() > 0) { await logoutButton.click(); } } }); await test.step('验证跳转到登录页面', async () => { await TestHelper.waitForUrl(page, /.*login/); await expect(page).toHaveURL(/.*login/); }); }); test('登录成功 - 记住我功能', async ({ page }) => { await test.step('启用记住我功能并登录', async () => { await loginPage.usernameInput.fill('admin'); await loginPage.passwordInput.fill('admin123'); const rememberMeCheckbox = page.locator('.remember-me-checkbox'); if (await rememberMeCheckbox.count() > 0) { await rememberMeCheckbox.check(); } await loginPage.loginButton.click(); await TestHelper.waitForUrl(page, /.*dashboard/); }); await test.step('验证Token持久化', async () => { const token = await TestHelper.getLocalStorage(page, 'token'); expect(token).toBeTruthy(); const rememberMe = await TestHelper.getLocalStorage(page, 'remember_me'); expect(rememberMe).toBe('true'); }); }); test('登录成功 - 自动填充上次登录用户名', async ({ page }) => { await test.step('首次登录', async () => { await loginPage.usernameInput.fill('testuser'); await loginPage.passwordInput.fill('testpassword'); await loginPage.loginButton.click(); await TestHelper.waitForUrl(page, /.*dashboard/); }); await test.step('登出', async () => { await loginPage.logout(); await TestHelper.waitForUrl(page, /.*login/); }); await test.step('验证自动填充上次登录用户名', async () => { const usernameInput = page.locator('input[placeholder*="用户名"]'); const usernameValue = await usernameInput.inputValue(); expect(usernameValue).toBe('testuser'); }); }); test('登录失败 - SQL注入攻击', async ({ page }) => { await test.step('尝试SQL注入攻击', async () => { const sqlInjection = "' OR '1'='1"; await loginPage.usernameInput.fill(sqlInjection); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); }); await test.step('验证登录失败', async () => { await TestHelper.waitForErrorMessage(page); const currentUrl = page.url(); expect(currentUrl).toContain('/login'); }); }); test('登录失败 - XSS攻击', async ({ page }) => { await test.step('尝试XSS攻击', async () => { const xssAttack = ''; await loginPage.usernameInput.fill(xssAttack); await loginPage.passwordInput.fill('admin123'); await loginPage.loginButton.click(); }); await test.step('验证XSS被过滤', async () => { await TestHelper.waitForErrorMessage(page); const currentUrl = page.url(); expect(currentUrl).toContain('/login'); const usernameInput = page.locator('input[placeholder*="用户名"]'); const usernameValue = await usernameInput.inputValue(); expect(usernameValue).not.toContain('