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 UserDetailPage from '../pages/usr/UserDetailPage'
vi.mock('../api/usr', () => ({
getStaffs: vi.fn().mockResolvedValue([{ sId: 's1', sStaffName: '张三' }]),
getPermissionGroups: vi.fn().mockResolvedValue([{ sId: 'pg1', sGroupCode: 'usr:create', sGroupName: '新增用户', sCategory: '用户管理' }]),
createUser: vi.fn().mockResolvedValue({ userId: 'u2', userCode: 'UC002', username: 'bob' }),
updateUser: vi.fn().mockResolvedValue({ userId: 'u1', username: 'alice', updatedAt: '2026-05-08T10:00:00' }),
getUserList: vi.fn().mockResolvedValue({ total: 0, page: 1, pageSize: 20, list: [] }),
}))
vi.mock('../api/request', () => ({
default: { get: vi.fn(), post: vi.fn(), put: vi.fn() },
}))
function makeStore() {
const store = configureStore({ reducer: { auth: authReducer, tabs: tabsReducer } })
store.dispatch({
type: 'auth/setCredentials',
payload: { accessToken: 'tok', refreshToken: 'ref', userInfo: { userId: 'u0', username: 'admin', userType: '超级管理员', language: '中文', brandId: 'b1' } },
})
return store
}
const rowData = {
sId: 'u1', sUsername: 'alice', sUserCode: 'UC001', sUserType: '普通用户',
sLanguage: '中文', bCanEditDoc: 0, bIsDisabled: 0, tLastLoginDate: null,
sCreatorUsername: 'admin', tCreateDate: '2026-01-01 00:00:00',
sStaffName: null, sDepartment: null,
}
function renderNew() {
return render(
} />
UserList} />
)
}
function renderEdit(state = rowData) {
return render(
} />
UserList} />
)
}
describe('UserDetailPage', () => {
beforeEach(() => { vi.clearAllMocks() })
it('newMode_showsSaveButton', () => {
renderNew()
expect(screen.getByRole('button', { name: /保存/ })).toBeInTheDocument()
})
it('newMode_showsPermissionGroupTab', async () => {
renderNew()
await waitFor(() => expect(screen.getByText('新增用户')).toBeInTheDocument())
})
it('editMode_showsUsernameReadonly', async () => {
renderEdit()
await waitFor(() => expect(screen.getByText('alice')).toBeInTheDocument())
})
it('editMode_noState_redirectsToList', async () => {
render(
} />
UserList} />
)
await waitFor(() => expect(screen.getByText('UserList')).toBeInTheDocument())
})
it('newMode_save_callsCreateUser', async () => {
const { createUser } = await import('../api/usr')
renderNew()
await userEvent.type(screen.getByPlaceholderText('请输入用户号'), 'UC002')
await userEvent.type(screen.getByPlaceholderText('请输入用户名'), 'bob')
await userEvent.click(screen.getByRole('button', { name: /保存/ }))
await waitFor(() => expect(vi.mocked(createUser)).toHaveBeenCalledWith(
expect.objectContaining({ userCode: 'UC002', username: 'bob' })
))
})
it('editMode_save_callsUpdateUser', async () => {
const { updateUser } = await import('../api/usr')
renderEdit()
await waitFor(() => expect(screen.getByText('alice')).toBeInTheDocument())
await userEvent.click(screen.getByRole('button', { name: /保存/ }))
await waitFor(() => expect(vi.mocked(updateUser)).toHaveBeenCalledWith(
'u1',
expect.objectContaining({ userType: '普通用户' })
))
})
it('permCheckbox_togglesSelection', async () => {
renderNew()
await waitFor(() => expect(screen.getByText('新增用户')).toBeInTheDocument())
const cb = screen.getByRole('checkbox')
expect(cb).not.toBeChecked()
await userEvent.click(cb)
expect(cb).toBeChecked()
await userEvent.click(cb)
expect(cb).not.toBeChecked()
})
it('cancelButton_navigatesToList', async () => {
renderNew()
await userEvent.click(screen.getByRole('button', { name: /取消/ }))
await waitFor(() => expect(screen.getByText('UserList')).toBeInTheDocument())
})
})