import { describe, it, expect, vi, beforeEach } from 'vitest' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { Provider } from 'react-redux' import { MemoryRouter, Routes, Route } from 'react-router-dom' import { configureStore } from '@reduxjs/toolkit' import authReducer from '../store/slices/authSlice' import tabsReducer from '../store/slices/tabsSlice' import UserListPage from '../pages/usr/UserListPage' vi.mock('../api/usr', () => ({ getStaffs: vi.fn().mockResolvedValue([]), getPermissionGroups: vi.fn().mockResolvedValue([]), createUser: vi.fn(), getUserList: vi.fn().mockResolvedValue({ total: 0, page: 1, pageSize: 20, list: [] }), updateUser: vi.fn().mockResolvedValue({ userId: 'u1', username: 'alice', updatedAt: '2026-05-08T10:00:00' }), })) vi.mock('../api/request', () => ({ default: { get: vi.fn(), post: vi.fn(), put: vi.fn() }, })) function makeStore(userType: string) { const store = configureStore({ reducer: { auth: authReducer, tabs: tabsReducer } }) store.dispatch({ type: 'auth/setCredentials', payload: { accessToken: 'test-token', refreshToken: 'test-refresh', userInfo: { userId: 'u1', username: 'admin', userType, language: '中文', brandId: 'b1' } }, }) return store } const sampleRow = { sId: 'u1', sUsername: 'alice', sUserCode: 'UC001', sUserType: '普通用户', sLanguage: '中文', bCanEditDoc: 0, bIsDisabled: 0, tLastLoginDate: null, sCreatorUsername: 'admin', tCreateDate: '2026-01-01T00:00:00', sStaffName: '张三', sDepartment: '研发部', } function renderPage(userType: string, extraRoutes = false) { const store = makeStore(userType) return render( {extraRoutes ? ( } /> NewUserPage} /> DetailPage} /> ) : ( )} ) } describe('UserListPage', () => { beforeEach(() => { vi.clearAllMocks() }) it('superAdmin_seesNewButton', () => { renderPage('超级管理员') expect(screen.getByRole('button', { name: /新\s*增/ })).toBeInTheDocument() }) it('normalUser_doesNotSeeNewButton', () => { renderPage('普通用户') expect(screen.queryByRole('button', { name: /新\s*增/ })).not.toBeInTheDocument() }) it('clickNewButton_navigatesToNewPage', async () => { renderPage('超级管理员', true) await userEvent.click(screen.getByRole('button', { name: /新\s*增/ })) await waitFor(() => expect(screen.getByText('NewUserPage')).toBeInTheDocument()) }) it('initialLoad_rendersTableRows', async () => { const { getUserList } = await import('../api/usr') vi.mocked(getUserList).mockResolvedValueOnce({ total: 1, page: 1, pageSize: 20, list: [sampleRow] }) renderPage('超级管理员') await waitFor(() => expect(screen.getByText('alice')).toBeInTheDocument()) expect(screen.getByText('张三')).toBeInTheDocument() }) it('searchButton_callsGetUserList', async () => { const { getUserList } = await import('../api/usr') renderPage('超级管理员') await userEvent.click(screen.getByRole('button', { name: /搜\s*索|搜索/ })) await waitFor(() => expect(vi.mocked(getUserList)).toHaveBeenCalledTimes(2)) }) it('doubleClickRow_navigatesToDetailPage', async () => { const { getUserList } = await import('../api/usr') vi.mocked(getUserList).mockResolvedValueOnce({ total: 1, page: 1, pageSize: 20, list: [sampleRow] }) renderPage('超级管理员', true) await waitFor(() => expect(screen.getByText('alice')).toBeInTheDocument()) await userEvent.dblClick(screen.getByText('alice').closest('tr')!) await waitFor(() => expect(screen.getByText('DetailPage')).toBeInTheDocument()) }) })