| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- import { describe, it, expect, vi, beforeEach } from 'vitest';
- import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
- import DisabilityPersonManagement from '../../src/components/DisabilityPersonManagement';
- import { disabilityClientManager } from '../../src/api/disabilityClient';
- // 完整的mock响应对象
- const createMockResponse = (status: number, data?: any) => ({
- status,
- ok: status >= 200 && status < 300,
- body: null,
- bodyUsed: false,
- statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
- headers: new Headers(),
- url: '',
- redirected: false,
- type: 'basic' as ResponseType,
- json: async () => data || {},
- text: async () => '',
- blob: async () => new Blob(),
- arrayBuffer: async () => new ArrayBuffer(0),
- formData: async () => new FormData(),
- clone: function() { return this; }
- });
- // Mock API client
- vi.mock('../../src/api/disabilityClient', () => {
- const mockDisabilityClient = {
- getAllDisabledPersons: {
- $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
- data: [
- {
- id: 1,
- name: '张三',
- gender: '男',
- idCard: '110101199001011234',
- disabilityId: 'D123456789',
- disabilityType: '肢体残疾',
- disabilityLevel: '一级',
- idAddress: '北京市东城区',
- phone: '13800138000',
- province: '北京市',
- city: '北京市',
- district: '东城区',
- detailedAddress: '某街道某号',
- nation: '汉族',
- isMarried: 0,
- canDirectContact: 1,
- isInBlackList: 0,
- jobStatus: 1,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- }
- ],
- total: 1
- }))),
- },
- createDisabledPerson: {
- $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
- id: 2,
- name: '李四',
- gender: '女',
- idCard: '110101199002021234',
- disabilityId: 'D123456790',
- disabilityType: '视力残疾',
- disabilityLevel: '二级',
- idAddress: '上海市黄浦区',
- phone: '13900139000',
- province: '上海市',
- city: '上海市',
- district: '黄浦区',
- detailedAddress: '某街道某号',
- nation: '汉族',
- isMarried: 1,
- canDirectContact: 1,
- isInBlackList: 0,
- jobStatus: 0,
- createTime: '2024-01-02T00:00:00Z',
- updateTime: '2024-01-02T00:00:00Z'
- }))),
- },
- updateDisabledPerson: {
- $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
- id: 1,
- name: '张三(已更新)',
- gender: '男',
- idCard: '110101199001011234',
- disabilityId: 'D123456789',
- disabilityType: '肢体残疾',
- disabilityLevel: '一级',
- idAddress: '北京市东城区',
- phone: '13800138001',
- province: '北京市',
- city: '北京市',
- district: '东城区',
- detailedAddress: '更新后的地址',
- nation: '汉族',
- isMarried: 1,
- canDirectContact: 1,
- isInBlackList: 0,
- jobStatus: 1,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-03T00:00:00Z'
- }))),
- },
- deleteDisabledPerson: {
- $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
- success: true
- }))),
- },
- searchDisabledPersons: {
- $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
- data: [
- {
- id: 1,
- name: '张三',
- gender: '男',
- idCard: '110101199001011234',
- disabilityId: 'D123456789',
- disabilityType: '肢体残疾',
- disabilityLevel: '一级',
- idAddress: '北京市东城区',
- phone: '13800138000',
- province: '北京市',
- city: '北京市',
- district: '东城区',
- detailedAddress: '某街道某号',
- nation: '汉族',
- isMarried: 0,
- canDirectContact: 1,
- isInBlackList: 0,
- jobStatus: 1,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- }
- ],
- total: 1
- }))),
- },
- getDisabledPerson: {
- ':id': {
- $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
- id: 1,
- name: '张三',
- gender: '男',
- idCard: '110101199001011234',
- disabilityId: 'D123456789',
- disabilityType: '肢体残疾',
- disabilityLevel: '一级',
- idAddress: '北京市东城区',
- phone: '13800138000',
- province: '北京市',
- city: '北京市',
- district: '东城区',
- detailedAddress: '某街道某号',
- nation: '汉族',
- isMarried: 0,
- canDirectContact: 1,
- isInBlackList: 0,
- jobStatus: 1,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- }))),
- },
- },
- };
- const mockDisabilityClientManager = {
- get: vi.fn(() => mockDisabilityClient),
- };
- return {
- disabilityClientManager: mockDisabilityClientManager,
- disabilityClient: mockDisabilityClient,
- };
- });
- // Mock toast
- vi.mock('sonner', () => ({
- toast: {
- success: vi.fn(),
- error: vi.fn(),
- },
- }));
- // Mock 枚举包
- vi.mock('@d8d/allin-enums', () => ({
- DisabilityType: {
- VISION: 'vision',
- HEARING: 'hearing',
- SPEECH: 'speech',
- PHYSICAL: 'physical',
- INTELLECTUAL: 'intellectual',
- MENTAL: 'mental',
- MULTIPLE: 'multiple',
- },
- DISABILITY_TYPES: ['vision', 'hearing', 'speech', 'physical', 'intellectual', 'mental', 'multiple'],
- getDisabilityTypeLabel: vi.fn((type) => {
- const labels: Record<string, string> = {
- vision: '视力残疾',
- hearing: '听力残疾',
- speech: '言语残疾',
- physical: '肢体残疾',
- intellectual: '智力残疾',
- mental: '精神残疾',
- multiple: '多重残疾',
- };
- return labels[type] || type;
- }),
- DisabilityLevel: {
- ONE: 1,
- TWO: 2,
- THREE: 3,
- FOUR: 4,
- },
- DISABILITY_LEVELS: [1, 2, 3, 4],
- getDisabilityLevelLabel: vi.fn((level) => {
- const labels: Record<number, string> = {
- 1: '一级',
- 2: '二级',
- 3: '三级',
- 4: '四级',
- };
- return labels[level] || level.toString();
- }),
- }));
- // Mock 区域选择器组件
- vi.mock('@d8d/area-management-ui/components', () => ({
- AreaSelect: vi.fn(({ value, onChange }) => (
- <div data-testid="area-select">
- <select
- data-testid="province-select"
- value={value?.provinceId || ''}
- onChange={(e) => onChange({ ...value, provinceId: e.target.value ? Number(e.target.value) : undefined })}
- >
- <option value="">选择省份</option>
- <option value="1">北京市</option>
- </select>
- <select
- data-testid="city-select"
- value={value?.cityId || ''}
- onChange={(e) => onChange({ ...value, cityId: e.target.value ? Number(e.target.value) : undefined })}
- >
- <option value="">选择城市</option>
- <option value="2">北京市</option>
- </select>
- <select
- data-testid="district-select"
- value={value?.districtId || ''}
- onChange={(e) => onChange({ ...value, districtId: e.target.value ? Number(e.target.value) : undefined })}
- >
- <option value="">选择区县</option>
- <option value="3">东城区</option>
- </select>
- </div>
- )),
- }));
- // Mock 文件选择器组件
- vi.mock('@d8d/file-management-ui/components', () => ({
- FileSelector: vi.fn(({ onChange, placeholder }) => (
- <div data-testid="file-selector">
- <button
- data-testid="file-selector-button"
- onClick={() => onChange && onChange(1)}
- >
- {placeholder || '选择文件'}
- </button>
- </div>
- )),
- }));
- describe('残疾人个人管理集成测试', () => {
- let queryClient: QueryClient;
- beforeEach(() => {
- queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- });
- vi.clearAllMocks();
- });
- const renderComponent = () => {
- return render(
- <QueryClientProvider client={queryClient}>
- <DisabilityPersonManagement />
- </QueryClientProvider>
- );
- };
- it('应该正确渲染残疾人列表', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 验证表格内容
- expect(screen.getByText('张三')).toBeInTheDocument();
- expect(screen.getByText('男')).toBeInTheDocument();
- expect(screen.getByText('110101199001011234')).toBeInTheDocument();
- expect(screen.getByText('D123456789')).toBeInTheDocument();
- expect(screen.getByText('肢体残疾')).toBeInTheDocument();
- expect(screen.getByText('一级')).toBeInTheDocument();
- expect(screen.getByText('13800138000')).toBeInTheDocument();
- });
- it('应该打开创建模态框并填写表单', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 点击新增按钮 - 使用测试ID
- const addButton = screen.getByTestId('add-disabled-person-button');
- fireEvent.click(addButton);
- // 验证模态框打开 - 使用测试ID
- await waitFor(() => {
- expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
- });
- // 填写表单
- const nameInput = screen.getByPlaceholderText('请输入姓名');
- const idCardInput = screen.getByPlaceholderText('请输入身份证号');
- const disabilityIdInput = screen.getByPlaceholderText('请输入残疾证号');
- const phoneInput = screen.getByPlaceholderText('请输入联系电话');
- const idAddressInput = screen.getByPlaceholderText('请输入身份证地址');
- fireEvent.change(nameInput, { target: { value: '李四' } });
- fireEvent.change(idCardInput, { target: { value: '110101199002021234' } });
- fireEvent.change(disabilityIdInput, { target: { value: 'D123456790' } });
- fireEvent.change(phoneInput, { target: { value: '13900139000' } });
- fireEvent.change(idAddressInput, { target: { value: '上海市黄浦区' } });
- // 选择性别
- const genderSelect = screen.getByTestId('gender-select');
- fireEvent.change(genderSelect, { target: { value: '女' } });
- // 选择残疾类型
- const disabilityTypeSelect = screen.getByTestId('disability-type-select');
- fireEvent.change(disabilityTypeSelect, { target: { value: '视力残疾' } });
- // 选择残疾等级
- const disabilityLevelSelect = screen.getByTestId('disability-level-select');
- fireEvent.change(disabilityLevelSelect, { target: { value: '二级' } });
- // 选择省份和城市
- const provinceSelect = screen.getByTestId('province-select');
- const citySelect = screen.getByTestId('city-select');
- await act(async () => {
- fireEvent.change(provinceSelect, { target: { value: '1' } });
- });
- await act(async () => {
- fireEvent.change(citySelect, { target: { value: '2' } });
- });
- // 提交表单
- const submitButton = screen.getByText('创建');
- // 使用act包装状态更新
- await act(async () => {
- fireEvent.click(submitButton);
- });
- // 验证API调用 - 增加等待时间
- await waitFor(() => {
- const mockClient = (disabilityClientManager.get as any)();
- expect(mockClient.createDisabledPerson.$post).toHaveBeenCalled();
- }, { timeout: 3000 });
- // 验证具体的调用参数
- const mockClient = (disabilityClientManager.get as any)();
- const call = mockClient.createDisabledPerson.$post.mock.calls[0];
- expect(call).toBeDefined();
- if (call) {
- expect(call[0].json).toMatchObject({
- name: '李四',
- idCard: '110101199002021234',
- disabilityId: 'D123456790',
- phone: '13900139000',
- idAddress: '上海市黄浦区',
- });
- }
- });
- it('应该打开编辑模态框并更新数据', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 点击编辑按钮
- const editButton = screen.getByTestId('edit-person-1');
- fireEvent.click(editButton);
- // 验证模态框打开
- await waitFor(() => {
- expect(screen.getByText('编辑残疾人信息')).toBeInTheDocument();
- });
- // 修改电话号码
- const phoneInput = screen.getByPlaceholderText('请输入联系电话');
- fireEvent.change(phoneInput, { target: { value: '13800138001' } });
- // 提交表单
- const submitButton = screen.getByText('更新');
- fireEvent.click(submitButton);
- // 验证API调用
- await waitFor(() => {
- const mockClient = (disabilityClientManager.get as any)();
- expect(mockClient.updateDisabledPerson.$post).toHaveBeenCalledWith({
- json: expect.objectContaining({
- id: 1,
- phone: '13800138001',
- }),
- });
- });
- });
- it('应该打开查看详情模态框', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 点击查看按钮
- const viewButton = screen.getByTestId('view-person-1');
- fireEvent.click(viewButton);
- // 验证模态框打开并显示详情
- await waitFor(() => {
- expect(screen.getByText('残疾人详情')).toBeInTheDocument();
- expect(screen.getByText('张三')).toBeInTheDocument();
- expect(screen.getByText('110101199001011234')).toBeInTheDocument();
- expect(screen.getByText('D123456789')).toBeInTheDocument();
- });
- });
- it('应该打开删除确认对话框并删除数据', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 点击删除按钮
- const deleteButton = screen.getByTestId('delete-person-1');
- fireEvent.click(deleteButton);
- // 验证删除对话框打开 - 使用测试ID
- await waitFor(() => {
- expect(screen.getByTestId('delete-confirmation-dialog-title')).toBeInTheDocument();
- });
- // 确认删除 - 使用更精确的选择器
- const confirmButtons = screen.getAllByText('确认删除');
- const confirmButton = confirmButtons.find(btn => btn.getAttribute('type') === 'button' || btn.getAttribute('data-slot') === 'button') || confirmButtons[0];
- fireEvent.click(confirmButton);
- // 验证API调用
- await waitFor(() => {
- const mockClient = (disabilityClientManager.get as any)();
- expect(mockClient.deleteDisabledPerson.$post).toHaveBeenCalledWith({
- json: { id: 1 },
- });
- });
- });
- it('应该进行搜索操作', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 输入搜索关键词
- const searchInput = screen.getByPlaceholderText('搜索姓名或身份证号');
- fireEvent.change(searchInput, { target: { value: '张三' } });
- // 点击搜索按钮
- const searchButton = screen.getByText('搜索');
- fireEvent.click(searchButton);
- // 验证API调用
- await waitFor(() => {
- const mockClient = (disabilityClientManager.get as any)();
- expect(mockClient.getAllDisabledPersons.$get).toHaveBeenCalled();
- });
- });
- it('应该测试区域选择器集成', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 打开创建模态框 - 使用测试ID
- const addButton = screen.getByTestId('add-disabled-person-button');
- fireEvent.click(addButton);
- // 等待模态框打开 - 使用测试ID
- await waitFor(() => {
- expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
- });
- // 验证区域选择器存在
- expect(screen.getByTestId('area-select')).toBeInTheDocument();
- // 选择省份
- const provinceSelect = screen.getByTestId('province-select');
- fireEvent.change(provinceSelect, { target: { value: '1' } });
- // 选择城市
- const citySelect = screen.getByTestId('city-select');
- fireEvent.change(citySelect, { target: { value: '2' } });
- // 选择区县
- const districtSelect = screen.getByTestId('district-select');
- fireEvent.change(districtSelect, { target: { value: '3' } });
- });
- it('应该测试文件选择器集成', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 打开创建模态框 - 使用测试ID
- const addButton = screen.getByTestId('add-disabled-person-button');
- fireEvent.click(addButton);
- // 等待模态框打开 - 使用测试ID
- await waitFor(() => {
- expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
- });
- // 验证照片上传组件存在
- expect(screen.getByTestId('add-photo-button')).toBeInTheDocument();
- // 点击添加照片按钮
- const addPhotoButton = screen.getByTestId('add-photo-button');
- fireEvent.click(addPhotoButton);
- });
- it('应该测试枚举选择器集成', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('张三')).toBeInTheDocument();
- });
- // 打开创建模态框 - 使用测试ID
- const addButton = screen.getByTestId('add-disabled-person-button');
- fireEvent.click(addButton);
- // 等待模态框打开 - 使用测试ID
- await waitFor(() => {
- expect(screen.getByTestId('create-disabled-person-dialog-title')).toBeInTheDocument();
- });
- // 验证残疾类型选择器 - 使用更稳健的选择器
- const disabilityTypeSelects = screen.getAllByRole('combobox');
- // 查找包含"残疾类型"标签的选择器
- const disabilityTypeSelect = disabilityTypeSelects.find(select => {
- const label = select.closest('.grid-cols-2')?.querySelector('label');
- return label?.textContent?.includes('残疾类型');
- });
- if (disabilityTypeSelect) {
- expect(disabilityTypeSelect).toBeInTheDocument();
- }
- // 验证残疾等级选择器
- const disabilityLevelSelect = disabilityTypeSelects.find(select => {
- const label = select.closest('.grid-cols-2')?.querySelector('label');
- return label?.textContent?.includes('残疾等级');
- });
- if (disabilityLevelSelect) {
- expect(disabilityLevelSelect).toBeInTheDocument();
- }
- });
- it('应该显示暂无数据提示', async () => {
- // 修改mock返回空数据
- const mockClient = (disabilityClientManager.get as any)();
- mockClient.getAllDisabledPersons.$get.mockResolvedValueOnce(
- createMockResponse(200, {
- data: [],
- total: 0
- })
- );
- renderComponent();
- // 等待暂无数据提示出现
- await waitFor(() => {
- expect(screen.getByText('暂无数据')).toBeInTheDocument();
- });
- // 验证暂无数据提示的样式
- const noDataElement = screen.getByText('暂无数据');
- expect(noDataElement).toHaveClass('text-muted-foreground');
- });
- });
|