import { test, expect } from '@playwright/test'; const mockLoginSuccess = { code: 200, message: '登录成功' }; const mockLoginFailure = { code: 401, message: '账号或密码错误' }; const mockTasks = { code: 200, data: { records: [] } }; const mockFeed = { code: 200, data: [] }; test.describe('Login page', () => { test.beforeEach(async ({ page }) => { await page.goto('/login'); await page.waitForSelector('.login-page', { timeout: 10_000 }); }); test('renders the login form with title and inputs', async ({ page }) => { await expect(page.locator('h2')).toContainText('账号登录'); await expect(page.locator('.login-form')).toBeVisible(); // Element Plus inputs const inputs = page.locator('.el-input'); await expect(inputs).toHaveCount(2); await expect(page.locator('.submit-btn')).toBeVisible(); }); test('shows validation errors when fields are empty', async ({ page }) => { await page.locator('.submit-btn').click(); // Element Plus validation shows error messages await expect(page.locator('.el-form-item__error').first()).toBeVisible({ timeout: 5000 }); }); test('shows error on invalid credentials', async ({ page }) => { await page.route('**/api/login**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockLoginFailure), }), ); await page.route('**/api/tasks**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockTasks) }), ); await page.route('**/api/review/feed**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockFeed) }), ); // Fill in inputs using Element Plus el-input inner input const usernameInput = page.locator('.el-form-item').filter({ hasText: '账号' }).locator('input'); const passwordInput = page.locator('.el-form-item').filter({ hasText: '密码' }).locator('input'); await usernameInput.fill('wronguser'); await passwordInput.fill('wrongpass'); await page.locator('.submit-btn').click(); // Element Plus error message appears in a popup await expect(page.locator('.el-message--error')).toBeVisible({ timeout: 5000 }); }); test('successful login navigates to /welcome', async ({ page }) => { await page.route('**/api/login**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockLoginSuccess), }), ); await page.route('**/api/tasks**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockTasks) }), ); await page.route('**/api/review/feed**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockFeed) }), ); const usernameInput = page.locator('.el-form-item').filter({ hasText: '账号' }).locator('input'); const passwordInput = page.locator('.el-form-item').filter({ hasText: '密码' }).locator('input'); await usernameInput.fill('admin'); await passwordInput.fill('password123'); await page.locator('.submit-btn').click(); await expect(page).toHaveURL(/\/welcome/, { timeout: 10_000 }); const isLoggedIn = await page.evaluate(() => localStorage.getItem('isLoggedIn')); expect(isLoggedIn).toBe('true'); }); });