|
@@ -0,0 +1,800 @@
|
|
|
|
|
+import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
|
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
|
|
|
+import userEvent from '@testing-library/user-event';
|
|
|
|
|
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
|
|
|
+import OrderManagement from '../../src/components/OrderManagement';
|
|
|
|
|
+import { orderClientManager } from '../../src/api/orderClient';
|
|
|
|
|
+import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
|
|
|
|
|
+
|
|
|
|
|
+// Mock 区域选择器组件
|
|
|
|
|
+vi.mock('@d8d/area-management-ui', () => ({
|
|
|
|
|
+ AreaSelect: vi.fn(({ value, onChange }) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div data-testid="area-select-mock">
|
|
|
|
|
+ <select
|
|
|
|
|
+ data-testid="area-select-province"
|
|
|
|
|
+ value={value?.provinceId || ''}
|
|
|
|
|
+ onChange={(e) => onChange && onChange({ provinceId: e.target.value ? parseInt(e.target.value) : undefined, cityId: undefined, districtId: undefined })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <option value="">选择省份</option>
|
|
|
|
|
+ <option value="1">省份1</option>
|
|
|
|
|
+ <option value="2">省份2</option>
|
|
|
|
|
+ </select>
|
|
|
|
|
+ <select
|
|
|
|
|
+ data-testid="area-select-city"
|
|
|
|
|
+ value={value?.cityId || ''}
|
|
|
|
|
+ onChange={(e) => onChange && onChange({ ...value, cityId: e.target.value ? parseInt(e.target.value) : undefined, districtId: undefined })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <option value="">选择城市</option>
|
|
|
|
|
+ <option value="3">城市1</option>
|
|
|
|
|
+ <option value="4">城市2</option>
|
|
|
|
|
+ </select>
|
|
|
|
|
+ <select
|
|
|
|
|
+ data-testid="area-select-district"
|
|
|
|
|
+ value={value?.districtId || ''}
|
|
|
|
|
+ onChange={(e) => onChange && onChange({ ...value, districtId: e.target.value ? parseInt(e.target.value) : undefined })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <option value="">选择区县</option>
|
|
|
|
|
+ <option value="5">区县1</option>
|
|
|
|
|
+ <option value="6">区县2</option>
|
|
|
|
|
+ </select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ })
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+// Mock 文件选择器组件
|
|
|
|
|
+vi.mock('@d8d/file-management-ui', () => ({
|
|
|
|
|
+ FileSelector: vi.fn(({ value, onChange }) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div data-testid="file-selector-mock">
|
|
|
|
|
+ <input
|
|
|
|
|
+ type="file"
|
|
|
|
|
+ data-testid="file-input"
|
|
|
|
|
+ onChange={(e) => {
|
|
|
|
|
+ if (onChange && e.target.files?.[0]) {
|
|
|
|
|
+ onChange('mock-file-id-123');
|
|
|
|
|
+ }
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ {value && <div data-testid="selected-file">已选择文件: {value}</div>}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ })
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+// Mock 残疾人选择器组件
|
|
|
|
|
+vi.mock('@d8d/allin-disability-management-ui', () => ({
|
|
|
|
|
+ DisabledPersonSelector: vi.fn(({ open, onOpenChange, onSelect, mode, disabledIds }) => {
|
|
|
|
|
+ if (!open) return null;
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div data-testid="disabled-person-selector-mock">
|
|
|
|
|
+ <div>残疾人选择器模拟</div>
|
|
|
|
|
+ <button
|
|
|
|
|
+ data-testid="select-person-button"
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ const mockPerson = {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ name: '测试残疾人',
|
|
|
|
|
+ gender: '男',
|
|
|
|
|
+ disabilityId: 'D123456',
|
|
|
|
|
+ disabilityType: '肢体残疾',
|
|
|
|
|
+ disabilityLevel: '三级',
|
|
|
|
|
+ phone: '13800138000'
|
|
|
|
|
+ };
|
|
|
|
|
+ onSelect(mode === 'multiple' ? [mockPerson] : mockPerson);
|
|
|
|
|
+ onOpenChange(false);
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 选择测试人员
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ data-testid="close-selector-button"
|
|
|
|
|
+ onClick={() => onOpenChange(false)}
|
|
|
|
|
+ >
|
|
|
|
|
+ 关闭
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ })
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+// 完整的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
|
|
|
|
|
+let mockOrderClient: any;
|
|
|
|
|
+vi.mock('../../src/api/orderClient', async (importOriginal) => {
|
|
|
|
|
+ const actual = await importOriginal() as any;
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...actual,
|
|
|
|
|
+ orderClient: mockOrderClient,
|
|
|
|
|
+ orderClientManager: {
|
|
|
|
|
+ getInstance: vi.fn(() => ({
|
|
|
|
|
+ get: vi.fn(() => mockOrderClient),
|
|
|
|
|
+ reset: vi.fn(),
|
|
|
|
|
+ })),
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// Mock toast
|
|
|
|
|
+vi.mock('sonner', () => ({
|
|
|
|
|
+ toast: {
|
|
|
|
|
+ success: vi.fn(),
|
|
|
|
|
+ error: vi.fn(),
|
|
|
|
|
+ },
|
|
|
|
|
+}));
|
|
|
|
|
+
|
|
|
|
|
+describe('订单管理集成测试', () => {
|
|
|
|
|
+ let queryClient: QueryClient;
|
|
|
|
|
+
|
|
|
|
|
+ beforeEach(() => {
|
|
|
|
|
+ queryClient = new QueryClient({
|
|
|
|
|
+ defaultOptions: {
|
|
|
|
|
+ queries: {
|
|
|
|
|
+ retry: false,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ vi.clearAllMocks();
|
|
|
|
|
+
|
|
|
|
|
+ // 重新创建mockOrderClient
|
|
|
|
|
+ mockOrderClient = {
|
|
|
|
|
+ list: {
|
|
|
|
|
+ $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ data: [
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ orderName: '测试订单1',
|
|
|
|
|
+ platformId: 1,
|
|
|
|
|
+ companyId: 1,
|
|
|
|
|
+ channelId: 1,
|
|
|
|
|
+ expectedStartDate: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ expectedEndDate: '2024-12-31T00:00:00Z',
|
|
|
|
|
+ orderStatus: OrderStatus.DRAFT,
|
|
|
|
|
+ workStatus: WorkStatus.NOT_WORKING,
|
|
|
|
|
+ provinceId: 1,
|
|
|
|
|
+ cityId: 2,
|
|
|
|
|
+ districtId: 3,
|
|
|
|
|
+ address: '测试地址',
|
|
|
|
|
+ contactPerson: '张三',
|
|
|
|
|
+ contactPhone: '13800138001',
|
|
|
|
|
+ remark: '测试备注',
|
|
|
|
|
+ createTime: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-01-01T00:00:00Z'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ id: 2,
|
|
|
|
|
+ orderName: '测试订单2',
|
|
|
|
|
+ platformId: 2,
|
|
|
|
|
+ companyId: 2,
|
|
|
|
|
+ channelId: 2,
|
|
|
|
|
+ expectedStartDate: '2024-02-01T00:00:00Z',
|
|
|
|
|
+ expectedEndDate: '2024-12-31T00:00:00Z',
|
|
|
|
|
+ orderStatus: OrderStatus.CONFIRMED,
|
|
|
|
|
+ workStatus: WorkStatus.PRE_WORKING,
|
|
|
|
|
+ provinceId: 4,
|
|
|
|
|
+ cityId: 5,
|
|
|
|
|
+ districtId: 6,
|
|
|
|
|
+ address: '测试地址2',
|
|
|
|
|
+ contactPerson: '李四',
|
|
|
|
|
+ contactPhone: '13800138002',
|
|
|
|
|
+ remark: '测试备注2',
|
|
|
|
|
+ createTime: '2024-02-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-02-01T00:00:00Z'
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ total: 2
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ create: {
|
|
|
|
|
+ $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ id: 3,
|
|
|
|
|
+ orderName: '新订单',
|
|
|
|
|
+ platformId: 3,
|
|
|
|
|
+ companyId: 3,
|
|
|
|
|
+ channelId: 3,
|
|
|
|
|
+ expectedStartDate: '2024-03-01T00:00:00Z',
|
|
|
|
|
+ expectedEndDate: '2024-12-31T00:00:00Z',
|
|
|
|
|
+ orderStatus: OrderStatus.DRAFT,
|
|
|
|
|
+ workStatus: WorkStatus.NOT_WORKING,
|
|
|
|
|
+ provinceId: 7,
|
|
|
|
|
+ cityId: 8,
|
|
|
|
|
+ districtId: 9,
|
|
|
|
|
+ address: '新地址',
|
|
|
|
|
+ contactPerson: '王五',
|
|
|
|
|
+ contactPhone: '13800138003',
|
|
|
|
|
+ remark: '新备注',
|
|
|
|
|
+ createTime: '2024-03-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-03-01T00:00:00Z'
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ update: {
|
|
|
|
|
+ ':id': {
|
|
|
|
|
+ $put: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ orderName: '更新后的订单',
|
|
|
|
|
+ platformId: 1,
|
|
|
|
|
+ companyId: 1,
|
|
|
|
|
+ channelId: 1,
|
|
|
|
|
+ expectedStartDate: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ expectedEndDate: '2024-12-31T00:00:00Z',
|
|
|
|
|
+ orderStatus: OrderStatus.CONFIRMED,
|
|
|
|
|
+ workStatus: WorkStatus.PRE_WORKING,
|
|
|
|
|
+ provinceId: 1,
|
|
|
|
|
+ cityId: 2,
|
|
|
|
|
+ districtId: 3,
|
|
|
|
|
+ address: '更新后的地址',
|
|
|
|
|
+ contactPerson: '张三',
|
|
|
|
|
+ contactPhone: '13800138001',
|
|
|
|
|
+ remark: '更新后的备注',
|
|
|
|
|
+ createTime: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-03-01T00:00:00Z'
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ delete: {
|
|
|
|
|
+ ':id': {
|
|
|
|
|
+ $delete: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ detail: {
|
|
|
|
|
+ ':id': {
|
|
|
|
|
+ $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ orderName: '测试订单1',
|
|
|
|
|
+ platformId: 1,
|
|
|
|
|
+ companyId: 1,
|
|
|
|
|
+ channelId: 1,
|
|
|
|
|
+ expectedStartDate: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ expectedEndDate: '2024-12-31T00:00:00Z',
|
|
|
|
|
+ orderStatus: OrderStatus.DRAFT,
|
|
|
|
|
+ workStatus: WorkStatus.NOT_WORKING,
|
|
|
|
|
+ provinceId: 1,
|
|
|
|
|
+ cityId: 2,
|
|
|
|
|
+ districtId: 3,
|
|
|
|
|
+ address: '测试地址',
|
|
|
|
|
+ contactPerson: '张三',
|
|
|
|
|
+ contactPhone: '13800138001',
|
|
|
|
|
+ remark: '测试备注',
|
|
|
|
|
+ createTime: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-01-01T00:00:00Z'
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ activate: {
|
|
|
|
|
+ ':orderId': {
|
|
|
|
|
+ $post: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ close: {
|
|
|
|
|
+ ':orderId': {
|
|
|
|
|
+ $post: vi.fn(() => Promise.resolve(createMockResponse(200, { success: true }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':orderId': {
|
|
|
|
|
+ persons: {
|
|
|
|
|
+ batch: {
|
|
|
|
|
+ $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: '批量添加人员成功',
|
|
|
|
|
+ addedCount: 2
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ assets: {
|
|
|
|
|
+ create: {
|
|
|
|
|
+ $post: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ orderId: 1,
|
|
|
|
|
+ personId: 1,
|
|
|
|
|
+ assetType: 'ID_CARD',
|
|
|
|
|
+ assetFileType: 'IMAGE',
|
|
|
|
|
+ fileId: 1,
|
|
|
|
|
+ relatedTime: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ createTime: '2024-01-01T00:00:00Z',
|
|
|
|
|
+ updateTime: '2024-01-01T00:00:00Z'
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ query: {
|
|
|
|
|
+ $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ data: [],
|
|
|
|
|
+ total: 0
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ delete: {
|
|
|
|
|
+ ':id': {
|
|
|
|
|
+ $delete: vi.fn(() => Promise.resolve(createMockResponse(200, {
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: '删除成功'
|
|
|
|
|
+ }))),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const renderOrderManagement = () => {
|
|
|
|
|
+ return render(
|
|
|
|
|
+ <QueryClientProvider client={queryClient}>
|
|
|
|
|
+ <OrderManagement />
|
|
|
|
|
+ </QueryClientProvider>
|
|
|
|
|
+ );
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ describe('CRUD流程测试', () => {
|
|
|
|
|
+ it('应该成功加载订单列表', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText('测试订单1')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByText('测试订单2')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证表格渲染
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-row-2')).toBeInTheDocument();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证状态徽章
|
|
|
|
|
+ expect(screen.getByText('草稿')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByText('已确认')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByText('未就业')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByText('待就业')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该成功创建订单', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 点击创建订单按钮
|
|
|
|
|
+ const createButton = screen.getByTestId('create-order-button');
|
|
|
|
|
+ fireEvent.click(createButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证订单表单模态框打开
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 这里可以添加表单填写和提交的测试
|
|
|
|
|
+ // 由于表单组件比较复杂,这里只验证模态框能正常打开
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该成功编辑订单', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 调试:打印所有test ID
|
|
|
|
|
+ const allElements = screen.getAllByTestId(/.*/);
|
|
|
|
|
+ console.debug('所有test ID:', allElements.map(el => el.getAttribute('data-testid')));
|
|
|
|
|
+
|
|
|
|
|
+ // 先点击下拉菜单触发器,然后点击编辑按钮
|
|
|
|
|
+ const menuTrigger = screen.getByTestId('order-menu-trigger-1');
|
|
|
|
|
+ expect(menuTrigger).toBeInTheDocument();
|
|
|
|
|
+
|
|
|
|
|
+ // 使用userEvent.click代替fireEvent.click,更好地模拟用户交互
|
|
|
|
|
+ await userEvent.click(menuTrigger);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待下拉菜单打开,然后点击编辑按钮
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ // 检查下拉菜单内容是否渲染 - 使用更精确的选择器
|
|
|
|
|
+ // 下拉菜单中的"操作"是DropdownMenuLabel,而表格中的"操作"是表头
|
|
|
|
|
+ // 我们可以检查下拉菜单中的特定元素
|
|
|
|
|
+ const editButton = screen.getByTestId('edit-order-button-1');
|
|
|
|
|
+ expect(editButton).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const editButton = screen.getByTestId('edit-order-button-1');
|
|
|
|
|
+ await userEvent.click(editButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证编辑表单模态框打开
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText('编辑订单')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该成功删除订单', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 先点击下拉菜单触发器,然后点击删除按钮
|
|
|
|
|
+ const menuTrigger = screen.getByTestId('order-menu-trigger-1');
|
|
|
|
|
+ expect(menuTrigger).toBeInTheDocument();
|
|
|
|
|
+ await userEvent.click(menuTrigger);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待下拉菜单打开,然后点击删除按钮
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const deleteButton = screen.getByTestId('delete-order-button-1');
|
|
|
|
|
+ expect(deleteButton).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const deleteButton = screen.getByTestId('delete-order-button-1');
|
|
|
|
|
+ await userEvent.click(deleteButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证删除确认对话框显示
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('delete-confirm-dialog-title')).toHaveTextContent('删除订单');
|
|
|
|
|
+ expect(screen.getByTestId('delete-confirm-dialog-description')).toHaveTextContent('确定要删除这个订单吗?此操作不可撤销。');
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击确认按钮
|
|
|
|
|
+ const confirmButton = screen.getByTestId('delete-confirm-dialog-confirm');
|
|
|
|
|
+ await userEvent.click(confirmButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(mockOrderClient.delete[':id'].$delete).toHaveBeenCalledWith({
|
|
|
|
|
+ param: { id: 1 },
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该成功激活订单', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 先打开下拉菜单,然后点击激活按钮(只有草稿状态的订单才有激活按钮)
|
|
|
|
|
+ const menuTrigger = screen.getByTestId('order-menu-trigger-1');
|
|
|
|
|
+ expect(menuTrigger).toBeInTheDocument();
|
|
|
|
|
+ await userEvent.click(menuTrigger);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待下拉菜单打开,然后点击激活按钮
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const activateButton = screen.getByTestId('activate-order-button-1');
|
|
|
|
|
+ expect(activateButton).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const activateButton = screen.getByTestId('activate-order-button-1');
|
|
|
|
|
+ await userEvent.click(activateButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证激活确认对话框显示
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('activate-confirm-dialog')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('activate-confirm-dialog-title')).toHaveTextContent('激活订单');
|
|
|
|
|
+ expect(screen.getByTestId('activate-confirm-dialog-description')).toHaveTextContent('确定要激活这个订单吗?订单激活后将进入进行中状态。');
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击确认按钮
|
|
|
|
|
+ const confirmButton = screen.getByTestId('activate-confirm-dialog-confirm');
|
|
|
|
|
+ await userEvent.click(confirmButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(mockOrderClient.activate[':orderId'].$post).toHaveBeenCalledWith({
|
|
|
|
|
+ param: { orderId: 1 },
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该成功关闭订单', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-2')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 先打开下拉菜单,然后点击关闭按钮(只有已确认或进行中的订单有关闭按钮)
|
|
|
|
|
+ const menuTrigger = screen.getByTestId('order-menu-trigger-2');
|
|
|
|
|
+ expect(menuTrigger).toBeInTheDocument();
|
|
|
|
|
+ await userEvent.click(menuTrigger);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待下拉菜单打开,然后点击关闭按钮
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const closeButton = screen.getByTestId('close-order-button-2');
|
|
|
|
|
+ expect(closeButton).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const closeButton = screen.getByTestId('close-order-button-2');
|
|
|
|
|
+ await userEvent.click(closeButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证关闭确认对话框显示
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('close-confirm-dialog')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('close-confirm-dialog-title')).toHaveTextContent('关闭订单');
|
|
|
|
|
+ expect(screen.getByTestId('close-confirm-dialog-description')).toHaveTextContent('确定要关闭这个订单吗?订单关闭后将无法再添加人员或资产。');
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击确认按钮
|
|
|
|
|
+ const confirmButton = screen.getByTestId('close-confirm-dialog-confirm');
|
|
|
|
|
+ await userEvent.click(confirmButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(mockOrderClient.close[':orderId'].$post).toHaveBeenCalledWith({
|
|
|
|
|
+ param: { orderId: 2 },
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该可以取消删除操作', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 先点击下拉菜单触发器,然后点击删除按钮
|
|
|
|
|
+ const menuTrigger = screen.getByTestId('order-menu-trigger-1');
|
|
|
|
|
+ expect(menuTrigger).toBeInTheDocument();
|
|
|
|
|
+ await userEvent.click(menuTrigger);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待下拉菜单打开,然后点击删除按钮
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const deleteButton = screen.getByTestId('delete-order-button-1');
|
|
|
|
|
+ expect(deleteButton).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const deleteButton = screen.getByTestId('delete-order-button-1');
|
|
|
|
|
+ await userEvent.click(deleteButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证删除确认对话框显示
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击取消按钮
|
|
|
|
|
+ const cancelButton = screen.getByTestId('delete-confirm-dialog-cancel');
|
|
|
|
|
+ await userEvent.click(cancelButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对话框关闭
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.queryByTestId('delete-confirm-dialog')).not.toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API没有被调用
|
|
|
|
|
+ expect(mockOrderClient.delete[':id'].$delete).not.toHaveBeenCalled();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('文件上传集成测试', () => {
|
|
|
|
|
+ it('应该成功打开资产关联模态框', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击添加资产按钮
|
|
|
|
|
+ const addAssetButton = screen.getByTestId('add-asset-button-1');
|
|
|
|
|
+ fireEvent.click(addAssetButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证资产关联模态框打开
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText('添加资产关联')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证文件选择器组件存在
|
|
|
|
|
+ expect(screen.getByTestId('file-selector')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('区域选择器集成测试', () => {
|
|
|
|
|
+ it('应该成功打开订单表单并显示区域选择器', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 点击创建订单按钮
|
|
|
|
|
+ const createButton = screen.getByTestId('create-order-button');
|
|
|
|
|
+ fireEvent.click(createButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证订单表单模态框打开
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证区域选择器组件存在
|
|
|
|
|
+ expect(screen.getByTestId('area-select')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('枚举常量集成测试', () => {
|
|
|
|
|
+ it('应该正确显示订单状态枚举', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载 - 验证表格中的订单状态Badge
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ // 使用更精确的选择器,避免与Select选项冲突
|
|
|
|
|
+ const orderRow = screen.getByTestId('order-row-1');
|
|
|
|
|
+ expect(orderRow).toBeInTheDocument();
|
|
|
|
|
+ // 验证表格中有订单状态显示
|
|
|
|
|
+ expect(screen.getByText('测试订单1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证订单状态筛选器
|
|
|
|
|
+ const statusFilter = screen.getByTestId('filter-order-status-select');
|
|
|
|
|
+ expect(statusFilter).toBeInTheDocument();
|
|
|
|
|
+
|
|
|
|
|
+ // 点击筛选器查看选项
|
|
|
|
|
+ fireEvent.click(statusFilter);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证枚举选项存在
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ // 使用test ID验证枚举选项
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-all')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-draft')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-confirmed')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-in-progress')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-completed')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('order-status-option-cancelled')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该正确显示工作状态枚举', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载 - 验证表格中的工作状态Badge
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ // 使用更精确的选择器,避免与Select选项冲突
|
|
|
|
|
+ const orderRow = screen.getByTestId('order-row-1');
|
|
|
|
|
+ expect(orderRow).toBeInTheDocument();
|
|
|
|
|
+ // 验证表格中有工作状态显示
|
|
|
|
|
+ expect(screen.getByText('测试订单1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 验证工作状态筛选器
|
|
|
|
|
+ const workStatusFilter = screen.getByTestId('filter-work-status-select');
|
|
|
|
|
+ expect(workStatusFilter).toBeInTheDocument();
|
|
|
|
|
+
|
|
|
|
|
+ // 点击筛选器查看选项
|
|
|
|
|
+ fireEvent.click(workStatusFilter);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证枚举选项存在
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ // 使用test ID验证枚举选项
|
|
|
|
|
+ expect(screen.getByTestId('work-status-option-all')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('work-status-option-not-working')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('work-status-option-pre-working')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('work-status-option-working')).toBeInTheDocument();
|
|
|
|
|
+ expect(screen.getByTestId('work-status-option-resigned')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('人员管理测试', () => {
|
|
|
|
|
+ it('应该成功打开人员选择器', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击添加人员按钮
|
|
|
|
|
+ const addPersonsButton = screen.getByTestId('add-persons-button-1');
|
|
|
|
|
+ fireEvent.click(addPersonsButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证人员选择器模态框打开
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText('批量添加人员到订单')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('搜索和筛选测试', () => {
|
|
|
|
|
+ it('应该支持按订单名称搜索', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('search-order-name-input')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 输入搜索关键词
|
|
|
|
|
+ const searchInput = screen.getByTestId('search-order-name-input');
|
|
|
|
|
+ fireEvent.change(searchInput, { target: { value: '测试订单1' } });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击搜索按钮
|
|
|
|
|
+ const searchButton = screen.getByTestId('search-button');
|
|
|
|
|
+ fireEvent.click(searchButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ // 实际测试中应该验证API调用参数
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该支持按订单状态筛选', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('filter-order-status-select')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 选择订单状态
|
|
|
|
|
+ const statusFilter = screen.getByTestId('filter-order-status-select');
|
|
|
|
|
+ fireEvent.click(statusFilter);
|
|
|
|
|
+
|
|
|
|
|
+ // 选择"草稿"状态
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const draftOption = screen.getByText('草稿');
|
|
|
|
|
+ fireEvent.click(draftOption);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击搜索按钮
|
|
|
|
|
+ const searchButton = screen.getByTestId('search-button');
|
|
|
|
|
+ fireEvent.click(searchButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ // 实际测试中应该验证API调用参数
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该支持按工作状态筛选', async () => {
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 等待数据加载
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByTestId('filter-work-status-select')).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 选择工作状态
|
|
|
|
|
+ const workStatusFilter = screen.getByTestId('filter-work-status-select');
|
|
|
|
|
+ fireEvent.click(workStatusFilter);
|
|
|
|
|
+
|
|
|
|
|
+ // 选择"未就业"状态
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ const notWorkingOption = screen.getByText('未就业');
|
|
|
|
|
+ fireEvent.click(notWorkingOption);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 点击搜索按钮
|
|
|
|
|
+ const searchButton = screen.getByTestId('search-button');
|
|
|
|
|
+ fireEvent.click(searchButton);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证API调用
|
|
|
|
|
+ // 实际测试中应该验证API调用参数
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('错误处理测试', () => {
|
|
|
|
|
+ it('应该处理API错误', async () => {
|
|
|
|
|
+ // Mock API错误
|
|
|
|
|
+ const mockOrderClient = orderClientManager.getInstance().get();
|
|
|
|
|
+ mockOrderClient.list.$get.mockImplementationOnce(() =>
|
|
|
|
|
+ Promise.resolve(createMockResponse(500, {
|
|
|
|
|
+ code: 500,
|
|
|
|
|
+ message: '服务器错误'
|
|
|
|
|
+ }))
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ renderOrderManagement();
|
|
|
|
|
+
|
|
|
|
|
+ // 验证错误处理
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText(/加载失败/)).toBeInTheDocument();
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+});
|