import { test, expect, type Page } from '@playwright/test'; // 桩用户列表响应工厂 function usersBody(records: unknown[], total: number, pageNum = 1, pageSize = 10) { return JSON.stringify({ code: 0, message: 'success', data: { records, total, pageNum, pageSize }, }); } function makeUser(id: number, name: string, over: Record = {}) { return { id, sUserName: name, 员工名: null, sUserNo: `U00${id}`, 部门: '技术部', sUserType: '普通用户', sLanguage: '中文', iIsVoid: 0, tLastLoginDate: null, sCreator: 'admin', tCreateDate: '2024-01-01T00:00:00', ...over, }; } // 桩登录 / 版本下拉(沿用 shell.spec.ts 模式)。用户列表由各用例单独桩。 async function stubAuth(page: Page) { await page.route('**/api/usr/companies', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ code: 0, message: 'success', data: [{ id: 1, sCompanyName: '甲公司', sVersion: '标准版' }], }), }); }); await page.route('**/api/usr/login', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ code: 0, message: 'success', data: { token: 'tk-e2e', user: { id: 1, sUserName: '朱子纯', sUserType: '超级管理员', sLanguage: '中文' }, }, }), }); }); } async function login(page: Page) { await page.goto('/login'); await page.getByPlaceholder('请输入你的用户名').fill('admin'); await page.getByPlaceholder('请输入你的密码').fill('secret'); await expect(page.getByText('甲公司(标准版)')).toBeVisible(); await page.getByRole('button', { name: /登\s*录/ }).click(); await expect(page).toHaveURL(/\/$/); } async function gotoUserList(page: Page) { await page.getByRole('button', { name: '用户列表' }).click(); await expect(page).toHaveURL(/\/usr\/users$/); } test.describe('用户列表关键旅程', () => { test('enter user list renders rows', async ({ page }) => { await stubAuth(page); await page.route('**/api/usr/users**', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([makeUser(1, '李雷'), makeUser(2, '韩梅梅')], 2), }); }); await login(page); await gotoUserList(page); await expect(page.getByText('李雷')).toBeVisible(); await expect(page.getByText('共 2 条记录')).toBeVisible(); }); test('empty result shows 暂无匹配的用户', async ({ page }) => { await stubAuth(page); await page.route('**/api/usr/users**', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([], 0), }); }); await login(page); await gotoUserList(page); await expect(page.getByText('暂无匹配的用户')).toBeVisible(); }); test('search by value triggers query', async ({ page }) => { await stubAuth(page); await page.route('**/api/usr/users**', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([makeUser(3, '王搜索')], 1), }); }); await login(page); await gotoUserList(page); const input = page.getByTestId('filter-query-value').locator('input'); await input.fill('王'); const reqPromise = page.waitForRequest((req) => req.url().includes('/api/usr/users') && req.url().includes('queryValue'), ); await page.getByTestId('btn-search').click(); const req = await reqPromise; expect(decodeURIComponent(req.url())).toContain('queryValue=王'); await expect(page.getByText('王搜索')).toBeVisible(); }); test('pagination next page refetches with pageNum=2', async ({ page }) => { await stubAuth(page); await page.route('**/api/usr/users**', async (route) => { const url = route.request().url(); const pageNum = url.includes('pageNum=2') ? 2 : 1; await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([makeUser(pageNum, `行${pageNum}`)], 30, pageNum, 10), }); }); await login(page); await gotoUserList(page); await expect(page.getByText('行1')).toBeVisible(); const reqPromise = page.waitForRequest((req) => req.url().includes('/api/usr/users') && req.url().includes('pageNum=2'), ); await page.getByTitle('下一页').click(); await reqPromise; await expect(page.getByText('行2')).toBeVisible(); }); test('double click row navigates to user detail', async ({ page }) => { await stubAuth(page); await page.route('**/api/usr/users**', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([makeUser(88, '详情用户')], 1), }); }); await login(page); await gotoUserList(page); await page.getByText('详情用户').dblclick(); await expect(page).toHaveURL(/\/usr\/users\/88$/); }); test('error response shows retry then recovers', async ({ page }) => { await stubAuth(page); let fail = true; await page.route('**/api/usr/users**', async (route) => { if (fail) { await route.fulfill({ status: 500, contentType: 'application/json', body: '{}' }); } else { await route.fulfill({ status: 200, contentType: 'application/json', body: usersBody([makeUser(1, '恢复用户')], 1), }); } }); await login(page); await gotoUserList(page); await expect(page.getByText('加载失败,点击重试')).toBeVisible(); fail = false; await page.getByTestId('userlist-error').getByRole('button', { name: '点击重试' }).click(); await expect(page.getByText('恢复用户')).toBeVisible(); }); });