| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- import { describe, it, expect, vi, beforeEach } from 'vitest';
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
- import DisabledPersonSelector from '../../src/components/DisabledPersonSelector';
- import { disabilityClientManager } from '../../src/api/disabilityClient';
- import type { DisabledPersonData } from '../../src/api/types';
- // 完整的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 = {
- searchDisabledPersons: {
- $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
- data: [
- {
- id: 1,
- name: '张三',
- gender: '男',
- idCard: '110101199001011234',
- disabilityId: 'CJZ20240001',
- disabilityType: '视力残疾',
- disabilityLevel: '一级',
- idAddress: '北京市东城区',
- phone: '13800138000',
- province: '北京市',
- city: '北京市',
- district: '东城区',
- isInBlackList: 0,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- },
- {
- id: 2,
- name: '李四',
- gender: '女',
- idCard: '110101199001011235',
- disabilityId: 'CJZ20240002',
- disabilityType: '听力残疾',
- disabilityLevel: '二级',
- idAddress: '上海市黄浦区',
- phone: '13800138001',
- province: '上海市',
- city: '上海市',
- district: '黄浦区',
- isInBlackList: 1, // 黑名单人员
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- }
- ],
- total: 2
- })))
- },
- getAllDisabledPersons: {
- $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
- data: [
- {
- id: 3,
- name: '王五',
- gender: '男',
- idCard: '110101199001011236',
- disabilityId: 'CJZ20240003',
- disabilityType: '肢体残疾',
- disabilityLevel: '三级',
- idAddress: '广州市天河区',
- phone: '13800138002',
- province: '广东省',
- city: '广州市',
- district: '天河区',
- isInBlackList: 0,
- createTime: '2024-01-01T00:00:00Z',
- updateTime: '2024-01-01T00:00:00Z'
- }
- ],
- total: 1
- })))
- }
- };
- const mockClientManager = {
- get: vi.fn(() => mockDisabilityClient),
- init: vi.fn(() => mockDisabilityClient),
- reset: vi.fn(),
- getInstance: vi.fn(() => mockClientManager)
- };
- return {
- disabilityClientManager: mockClientManager,
- disabilityClient: mockDisabilityClient
- };
- });
- // Mock AreaSelect组件(与现有测试保持一致)
- vi.mock('@d8d/area-management-ui', () => ({
- AreaSelect: ({ onChange, value, disabled, 'data-testid': testId }: any) => (
- <div data-testid={testId || 'area-select'}>
- <select
- data-testid="area-province-select"
- onChange={(e) => onChange && onChange({ provinceId: e.target.value ? 1 : undefined })}
- value={value?.provinceId || ''}
- disabled={disabled}
- >
- <option value="">选择省份</option>
- <option value="1">北京市</option>
- </select>
- <select
- data-testid="area-city-select"
- onChange={(e) => onChange && onChange({ provinceId: 1, cityId: e.target.value ? 2 : undefined })}
- value={value?.cityId || ''}
- disabled={disabled}
- >
- <option value="">选择城市</option>
- <option value="2">北京市</option>
- </select>
- <select
- data-testid="area-district-select"
- onChange={(e) => onChange && onChange({ provinceId: 1, cityId: 2, districtId: e.target.value ? 3 : undefined })}
- value={value?.districtId || ''}
- disabled={disabled}
- >
- <option value="">选择区县</option>
- <option value="3">东城区</option>
- </select>
- </div>
- ),
- }));
- describe('DisabledPersonSelector', () => {
- let queryClient: QueryClient;
- let onOpenChange: ReturnType<typeof vi.fn>;
- let onSelect: ReturnType<typeof vi.fn>;
- beforeEach(() => {
- queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- });
- onOpenChange = vi.fn();
- onSelect = vi.fn();
- vi.clearAllMocks();
- });
- const renderComponent = (props = {}) => {
- return render(
- <QueryClientProvider client={queryClient}>
- <DisabledPersonSelector
- open={true}
- onOpenChange={onOpenChange}
- onSelect={onSelect}
- {...props}
- />
- </QueryClientProvider>
- );
- };
- it('应该渲染对话框和搜索区域', async () => {
- renderComponent();
- // 等待数据加载
- await waitFor(() => {
- expect(screen.getByText('选择残疾人')).toBeInTheDocument();
- });
- // 检查搜索字段
- expect(screen.getByTestId('search-name-input')).toBeInTheDocument();
- expect(screen.getByTestId('area-select')).toBeInTheDocument();
- expect(screen.getByText('搜索')).toBeInTheDocument();
- expect(screen.getByText('重置')).toBeInTheDocument();
- });
- it('应该显示残疾人列表', async () => {
- renderComponent();
- // 等待数据加载 - 应该调用 getAllDisabledPersons 因为没有搜索关键词
- await waitFor(() => {
- expect(disabilityClientManager.get().getAllDisabledPersons.$get).toHaveBeenCalled();
- });
- // 检查表格数据
- await waitFor(() => {
- expect(screen.getByText('王五')).toBeInTheDocument();
- });
- });
- it('应该处理搜索功能', async () => {
- renderComponent();
- // 输入搜索关键词
- const searchInput = screen.getByTestId('search-name-input');
- fireEvent.change(searchInput, { target: { value: '张三' } });
- // 点击搜索按钮
- const searchButton = screen.getByText('搜索');
- fireEvent.click(searchButton);
- // 验证搜索API被调用
- await waitFor(() => {
- expect(disabilityClientManager.get().searchDisabledPersons.$get).toHaveBeenCalledWith({
- query: {
- keyword: '张三',
- skip: 0,
- take: 10
- }
- });
- });
- });
- it('应该处理重置搜索', async () => {
- renderComponent();
- // 等待组件渲染
- await waitFor(() => {
- expect(screen.getByTestId('search-name-input')).toBeInTheDocument();
- });
- // 输入搜索关键词
- const searchInput = screen.getByTestId('search-name-input');
- fireEvent.change(searchInput, { target: { value: '张三' } });
- // 点击重置按钮
- const resetButton = screen.getByText('重置');
- fireEvent.click(resetButton);
- // 验证搜索输入被清空
- expect(searchInput).toHaveValue('');
- });
- it('应该处理单选模式', async () => {
- renderComponent({ mode: 'single' });
- // 等待数据加载
- await waitFor(() => {
- expect(disabilityClientManager.get().getAllDisabledPersons.$get).toHaveBeenCalled();
- });
- // 等待表格数据渲染
- await waitFor(() => {
- expect(screen.getByText('王五')).toBeInTheDocument();
- });
- // 点击表格行选择人员
- const firstRow = screen.getByText('王五').closest('tr');
- expect(firstRow).toBeInTheDocument();
- if (firstRow) {
- fireEvent.click(firstRow);
- }
- // 验证选择回调被调用
- expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({
- id: 3,
- name: '王五'
- }));
- expect(onOpenChange).toHaveBeenCalledWith(false);
- });
- it('应该处理多选模式', async () => {
- renderComponent({ mode: 'multiple' });
- // 等待数据加载
- await waitFor(() => {
- expect(disabilityClientManager.get().getAllDisabledPersons.$get).toHaveBeenCalled();
- });
- // 等待表格数据渲染
- await waitFor(() => {
- expect(screen.getByText('王五')).toBeInTheDocument();
- });
- // 应该显示多选相关的UI
- expect(screen.getByText('已选择 0 人')).toBeInTheDocument();
- });
- it('应该处理对话框关闭', async () => {
- renderComponent();
- await waitFor(() => {
- expect(screen.getByText('取消')).toBeInTheDocument();
- });
- // 点击取消按钮
- const cancelButton = screen.getByText('取消');
- fireEvent.click(cancelButton);
- expect(onOpenChange).toHaveBeenCalledWith(false);
- });
- });
|