import { describe, it, expect, beforeEach } from 'vitest'; import { testClient } from 'hono/testing'; import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util'; import { JWTUtil } from '@d8d/shared-utils'; import { UserEntity, Role } from '@d8d/user-module'; import { File } from '@d8d/file-module'; import orderRoutes from '../../src/routes/order.routes'; import { EmploymentOrder } from '../../src/entities/employment-order.entity'; import { OrderPerson } from '../../src/entities/order-person.entity'; import { OrderPersonAsset, AssetType, AssetFileType } from '../../src/entities/order-person-asset.entity'; import { OrderStatus, WorkStatus } from '@d8d/allin-enums'; // 设置集成测试钩子 setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, EmploymentOrder, OrderPerson, OrderPersonAsset]) describe('订单管理API集成测试', () => { let client: ReturnType>; let testToken: string; let testUser: UserEntity; let testFile: File; beforeEach(async () => { // 创建测试客户端 client = testClient(orderRoutes); // 获取数据源 const dataSource = await IntegrationTestDatabase.getDataSource(); // 创建测试用户 const userRepository = dataSource.getRepository(UserEntity); testUser = userRepository.create({ username: `test_user_${Date.now()}`, password: 'test_password', nickname: '测试用户', registrationSource: 'web' }); await userRepository.save(testUser); // 生成测试用户的token testToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{name:'user'}] }); // 创建测试文件 const fileRepository = dataSource.getRepository(File); testFile = fileRepository.create({ name: 'test_file.pdf', type: 'application/pdf', size: 1024, path: `test/${Date.now()}_test_file.pdf`, uploadUserId: testUser.id, uploadTime: new Date(), createdAt: new Date(), updatedAt: new Date() }); await fileRepository.save(testFile); }); describe('POST /order/create', () => { it('应该成功创建订单', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }; const response = await client.create.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 200) { const error = await response.json(); console.debug('创建订单失败:', JSON.stringify(error, null, 2)); } expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBeDefined(); expect(data.orderName).toBe('测试订单'); expect(data.orderStatus).toBe(OrderStatus.DRAFT); expect(data.workStatus).toBe(WorkStatus.NOT_WORKING); } }); it('应该验证订单状态枚举值', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: 'invalid_status', // 无效的状态 workStatus: WorkStatus.NOT_WORKING }; const response = await client.create.$post({ json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值 }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该验证工作状态枚举值', async () => { const createData = { orderName: '测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date().toISOString(), orderStatus: OrderStatus.DRAFT, workStatus: 'invalid_status' // 无效的状态 }; const response = await client.create.$post({ json: createData as any // 使用any绕过类型检查,因为这里故意测试无效的枚举值 }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); }); describe('GET /order/list', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '测试订单1', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); const testOrder2 = new EmploymentOrder({ orderName: '测试订单2', platformId: 2, companyId: 2, channelId: 2, expectedStartDate: new Date(), orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING }); await orderRepository.save(testOrder2); }); it('应该返回所有订单列表', async () => { const response = await client.list.$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); expect(data.data).toHaveLength(2); expect(data.total).toBe(2); } }); it('应该支持按订单名称搜索', async () => { const response = await client.list.$get({ query: { orderName: '测试订单1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].orderName).toBe('测试订单1'); } }); it('应该支持按订单状态过滤', async () => { const response = await client.list.$get({ query: { orderStatus: OrderStatus.CONFIRMED } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].orderStatus).toBe(OrderStatus.CONFIRMED); } }); it('应该支持分页查询', async () => { const response = await client.list.$get({ query: { page: '1', limit: '1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.total).toBe(2); } }); }); describe('GET /order/detail/:id', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '测试订单详情', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); }); it('应该返回指定ID的订单详情', async () => { const response = await client.detail[':id'].$get({ param: { id: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data?.id).toBe(testOrder.id); expect(data?.orderName).toBe('测试订单详情'); expect(data?.orderStatus).toBe(OrderStatus.DRAFT); } }); it('应该处理不存在的订单ID', async () => { const response = await client.detail[':id'].$get({ param: { id: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/activate/:orderId', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '待激活订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING }); await orderRepository.save(testOrder); }); it('应该成功激活草稿状态的订单', async () => { const response = await client.activate[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证订单状态已更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const updatedOrder = await orderRepository.findOne({ where: { id: testOrder.id } }); expect(updatedOrder?.orderStatus).toBe(OrderStatus.CONFIRMED); expect(updatedOrder?.actualStartDate).toBeDefined(); } }); it('应该处理非草稿状态的订单激活', async () => { // 更新订单状态为已确认 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.CONFIRMED }); const response = await client.activate[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const response = await client.activate[':orderId'].$post({ param: { orderId: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/close/:orderId', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '待关闭订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), actualStartDate: new Date(), orderStatus: OrderStatus.CONFIRMED, workStatus: WorkStatus.PRE_WORKING, }); await orderRepository.save(testOrder); }); it('应该成功关闭已确认状态的订单', async () => { const response = await client.close[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证订单状态已更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const updatedOrder = await orderRepository.findOne({ where: { id: testOrder.id } }); expect(updatedOrder?.orderStatus).toBe(OrderStatus.COMPLETED); expect(updatedOrder?.actualEndDate).toBeDefined(); } }); it('应该处理非已确认或进行中状态的订单关闭', async () => { // 更新订单状态为草稿 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.DRAFT }); const response = await client.close[':orderId'].$post({ param: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const response = await client.close[':orderId'].$post({ param: { orderId: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/:orderId/persons/batch', () => { let testOrder: EmploymentOrder; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); testOrder = new EmploymentOrder({ orderName: '批量添加人员测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); }); it('应该成功批量添加人员到订单', async () => { const batchData = { persons: [ { personId: 1001, joinDate: new Date().toISOString(), salaryDetail: 5000.00 }, { personId: 1002, joinDate: new Date().toISOString(), salaryDetail: 6000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.addedCount).toBe(2); // 验证人员已添加到订单 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderPersonRepository = dataSource.getRepository(OrderPerson); const orderPersons = await orderPersonRepository.find({ where: { orderId: testOrder.id } }); expect(orderPersons).toHaveLength(2); } }); it('应该处理重复的人员添加', async () => { // 先添加一个人员 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderPersonRepository = dataSource.getRepository(OrderPerson); const existingPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: 1001, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(existingPerson); const batchData = { persons: [ { personId: 1001, // 已存在的人员 joinDate: new Date().toISOString(), salaryDetail: 5000.00 }, { personId: 1002, // 新人员 joinDate: new Date().toISOString(), salaryDetail: 6000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); expect(data.addedCount).toBe(1); // 只添加了一个新人员 } }); it('应该处理已结束或已取消的订单', async () => { // 更新订单状态为已完成 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); await orderRepository.update(testOrder.id, { orderStatus: OrderStatus.COMPLETED }); const batchData = { persons: [ { personId: 1001, joinDate: new Date().toISOString(), salaryDetail: 5000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: testOrder.id.toString() }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的订单ID', async () => { const batchData = { persons: [ { personId: 1001, joinDate: new Date().toISOString(), salaryDetail: 5000.00 } ] }; const response = await client[':orderId'].persons.batch.$post({ param: { orderId: '999999' }, json: batchData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /order/assets/create', () => { let testOrder: EmploymentOrder; let testOrderPerson: OrderPerson; beforeEach(async () => { // 创建测试订单数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); testOrder = new EmploymentOrder({ orderName: '资产测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: 1001, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); }); it('应该成功创建订单人员资产', async () => { const assetData = { orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 200) { const error = await response.json(); console.debug('创建订单人员资产失败:', JSON.stringify(error, null, 2)); } expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBeDefined(); expect(data.orderId).toBe(testOrder.id); expect(data.personId).toBe(testOrderPerson.personId); expect(data.assetType).toBe(AssetType.DISABILITY_CERT); expect(data.fileId).toBe(testFile.id); } }); it('应该处理不存在的文件ID', async () => { const assetData = { orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: 999999, // 不存在的文件ID relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理人员不在订单中的情况', async () => { const assetData = { orderId: testOrder.id, personId: 999999, // 不在订单中的人员 assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date().toISOString() }; const response = await client.assets.create.$post({ json: assetData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('GET /order/assets/query', () => { let testOrder: EmploymentOrder; let testOrderPerson: OrderPerson; let testAsset: OrderPersonAsset; beforeEach(async () => { // 创建测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); const assetRepository = dataSource.getRepository(OrderPersonAsset); testOrder = new EmploymentOrder({ orderName: '资产查询测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: 1001, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); testAsset = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset); // 创建第二个资产 const testAsset2 = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.OTHER, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset2); }); it('应该查询所有订单人员资产', async () => { const response = await client.assets.query.$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(data).toHaveProperty('total'); expect(data.data).toHaveLength(2); expect(data.total).toBe(2); } }); it('应该支持按订单ID查询', async () => { const response = await client.assets.query.$get({ query: { orderId: testOrder.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(2); expect(data.data[0].orderId).toBe(testOrder.id); } }); it('应该支持按人员ID查询', async () => { const response = await client.assets.query.$get({ query: { personId: testOrderPerson.personId.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(2); expect(data.data[0].personId).toBe(testOrderPerson.personId); } }); it('应该支持按资产类型查询', async () => { const response = await client.assets.query.$get({ query: { assetType: AssetType.DISABILITY_CERT } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.data[0].assetType).toBe('身份证'); } }); it('应该支持分页查询', async () => { const response = await client.assets.query.$get({ query: { page: '1', limit: '1' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(1); expect(data.total).toBe(2); } }); }); describe('DELETE /order/assets/delete/:id', () => { let testAsset: OrderPersonAsset; beforeEach(async () => { // 创建测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(EmploymentOrder); const orderPersonRepository = dataSource.getRepository(OrderPerson); const assetRepository = dataSource.getRepository(OrderPersonAsset); const testOrder = new EmploymentOrder({ orderName: '资产删除测试订单', platformId: 1, companyId: 1, channelId: 1, expectedStartDate: new Date(), orderStatus: OrderStatus.DRAFT, workStatus: WorkStatus.NOT_WORKING, }); await orderRepository.save(testOrder); const testOrderPerson = orderPersonRepository.create({ orderId: testOrder.id, personId: 1001, joinDate: new Date(), workStatus: WorkStatus.NOT_WORKING, salaryDetail: 5000.00 }); await orderPersonRepository.save(testOrderPerson); testAsset = new OrderPersonAsset({ orderId: testOrder.id, personId: testOrderPerson.personId, assetType: AssetType.DISABILITY_CERT, assetFileType: AssetFileType.IMAGE, fileId: testFile.id, relatedTime: new Date() }); await assetRepository.save(testAsset); }); it('应该成功删除订单人员资产', async () => { const response = await client.assets.delete[':id'].$delete({ param: { id: testAsset.id.toString() } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证资产已删除 const dataSource = await IntegrationTestDatabase.getDataSource(); const assetRepository = dataSource.getRepository(OrderPersonAsset); const deletedAsset = await assetRepository.findOne({ where: { id: testAsset.id } }); expect(deletedAsset).toBeNull(); } }); it('应该处理不存在的资产ID', async () => { const response = await client.assets.delete[':id'].$delete({ param: { id: '999999' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('认证测试', () => { it('应该要求认证', async () => { const response = await client.list.$get({ query: {} // 不提供Authorization header }); expect(response.status).toBe(401); }); it('应该验证无效token', async () => { const response = await client.list.$get({ query: {} }, { headers: { 'Authorization': 'Bearer invalid_token' } }); expect(response.status).toBe(401); }); }); });