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 { FileEntity } from '@d8d/file-module'; import disabledPersonRoutes from '../../src/routes/disabled-person.routes'; import { DisabledPerson } from '../../src/entities/disabled-person.entity'; import { DisabledBankCard } from '../../src/entities/disabled-bank-card.entity'; import { DisabledPhoto } from '../../src/entities/disabled-photo.entity'; import { DisabledRemark } from '../../src/entities/disabled-remark.entity'; import { DisabledVisit } from '../../src/entities/disabled-visit.entity'; // 设置集成测试钩子 - 包含所有相关实体 setupIntegrationDatabaseHooksWithEntities([ UserEntity, Role, FileEntity, DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit ]) describe('残疾人管理API集成测试', () => { let client: ReturnType>; let testToken: string; let testUser: UserEntity; let testFile: FileEntity; beforeEach(async () => { // 创建测试客户端 client = testClient(disabledPersonRoutes); // 获取数据源 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); // 创建测试文件(用于照片集成测试) const fileRepository = dataSource.getRepository(FileEntity); testFile = fileRepository.create({ filename: 'test_photo.jpg', originalFilename: 'test_photo.jpg', mimeType: 'image/jpeg', size: 1024, bucket: 'd8dai', key: `test/${Date.now()}/photo.jpg`, uploaderId: testUser.id }); await fileRepository.save(testFile); // 生成测试用户的token testToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{name:'user'}] }); }); describe('POST /createDisabledPerson', () => { it('应该成功创建残疾人基本信息', async () => { const createData = { name: '张三', gender: '男', idCard: '110101199001011234', disabilityId: 'D123456789', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市东城区', phone: '13800138000', province: '北京市', city: '北京市' }; const response = await client.createDisabledPerson.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); console.debug('创建残疾人响应状态:', response.status); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.name).toBe(createData.name); expect(data.idCard).toBe(createData.idCard); expect(data.disabilityId).toBe(createData.disabilityId); } }); it('应该验证身份证号唯一性', async () => { // 先创建一个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const existingPerson = disabledPersonRepository.create({ name: '李四', gender: '女', idCard: '110101199001011235', disabilityId: 'D123456788', disabilityType: '视力残疾', disabilityLevel: '二级', idAddress: '北京市西城区', phone: '13900139000', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(existingPerson); // 尝试创建相同身份证号的残疾人 const createData = { name: '王五', gender: '男', idCard: '110101199001011235', // 重复的身份证号 disabilityId: 'D123456777', disabilityType: '听力残疾', disabilityLevel: '三级', idAddress: '北京市朝阳区', phone: '13700137000', province: '北京市', city: '北京市' }; const response = await client.createDisabledPerson.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该验证必填字段', async () => { const createData = { name: '', // 空字符串,应该验证失败 gender: '男', idCard: '110101199001011236', disabilityId: 'D123456776', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市海淀区', phone: '13600136000', province: '北京市', city: '北京市' }; const response = await client.createDisabledPerson.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); }); describe('POST /deleteDisabledPerson', () => { it('应该成功删除残疾人', async () => { // 先创建一个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person = disabledPersonRepository.create({ name: '测试删除人员', gender: '男', idCard: '110101199001011237', disabilityId: 'D123456775', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市石景山区', phone: '13500135000', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); const deleteData = { id: person.id }; const response = await client.deleteDisabledPerson.$post({ json: deleteData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.success).toBe(true); // 验证残疾人已被删除 const deletedPerson = await disabledPersonRepository.findOne({ where: { id: person.id } }); expect(deletedPerson).toBeNull(); } }); it('应该处理不存在的残疾人ID', async () => { const deleteData = { id: 99999 // 不存在的ID }; const response = await client.deleteDisabledPerson.$post({ json: deleteData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('POST /updateDisabledPerson', () => { it('应该成功更新残疾人信息', async () => { // 先创建一个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person = disabledPersonRepository.create({ name: '原始姓名', gender: '男', idCard: '110101199001011238', disabilityId: 'D123456774', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市通州区', phone: '13400134000', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); const updateData = { id: person.id, name: '更新后的姓名', gender: '女', phone: '13300133000' }; const response = await client.updateDisabledPerson.$post({ json: updateData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.name).toBe(updateData.name); expect(data.gender).toBe(updateData.gender); expect(data.phone).toBe(updateData.phone); } }); it('应该验证身份证号唯一性(更新时)', async () => { // 创建两个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person1 = disabledPersonRepository.create({ name: '人员A', gender: '男', idCard: '110101199001011239', disabilityId: 'D123456773', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市顺义区', phone: '13200132000', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person1); const person2 = disabledPersonRepository.create({ name: '人员B', gender: '女', idCard: '110101199001011240', disabilityId: 'D123456772', disabilityType: '视力残疾', disabilityLevel: '二级', idAddress: '北京市大兴区', phone: '13100131000', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person2); // 尝试将人员2的身份证号改为人员1的身份证号 const updateData = { id: person2.id, idCard: '110101199001011239' // 重复的身份证号 }; const response = await client.updateDisabledPerson.$post({ json: updateData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该处理不存在的残疾人', async () => { const updateData = { id: 99999, // 不存在的ID name: '新姓名' }; const response = await client.updateDisabledPerson.$post({ json: updateData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('GET /getAllDisabledPersons', () => { it('应该成功获取残疾人列表(分页)', async () => { // 创建一些测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); for (let i = 1; i <= 5; i++) { const person = disabledPersonRepository.create({ name: `残疾人${i}`, gender: i % 2 === 0 ? '女' : '男', idCard: `1101011990010112${40 + i}`, disabilityId: `D1234567${70 + i}`, disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: `北京市测试区${i}`, phone: `138001380${i}`, province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); } const response = await client.getAllDisabledPersons.$get({ query: { skip: 0, take: 10 } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(5); expect(data.total).toBe(5); expect(data.data[0].name).toBe('残疾人5'); // 按ID降序排列 } }); it('应该处理分页参数', async () => { // 创建更多测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); for (let i = 1; i <= 15; i++) { const person = disabledPersonRepository.create({ name: `分页人员${i}`, gender: i % 2 === 0 ? '女' : '男', idCard: `1101011990010113${i}`, disabilityId: `D1234568${i}`, disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: `北京市分页区${i}`, phone: `138001381${i}`, province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); } const response = await client.getAllDisabledPersons.$get({ query: { skip: 5, take: 5 } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.data).toHaveLength(5); expect(data.total).toBe(15); } }); }); describe('GET /searchDisabledPersons', () => { it('应该成功按姓名搜索残疾人', async () => { // 创建测试数据 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person1 = disabledPersonRepository.create({ name: '张三', gender: '男', idCard: '110101199001011241', disabilityId: 'D123456771', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市昌平区', phone: '13000130001', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person1); const person2 = disabledPersonRepository.create({ name: '李四', gender: '女', idCard: '110101199001011242', disabilityId: 'D123456770', disabilityType: '视力残疾', disabilityLevel: '二级', idAddress: '北京市平谷区', phone: '13000130002', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person2); const response = await client.searchDisabledPersons.$get({ query: { name: '张三', skip: 0, take: 10 } }, { 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].name).toBe('张三'); } }); it('应该验证搜索关键词不能为空', async () => { const response = await client.searchDisabledPersons.$get({ query: { name: '', // 空关键词 skip: 0, take: 10 } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); }); describe('GET /getDisabledPerson/{id}', () => { it('应该成功获取单个残疾人详情', async () => { // 先创建一个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person = disabledPersonRepository.create({ name: '测试人员详情', gender: '男', idCard: '110101199001011243', disabilityId: 'D123456769', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市怀柔区', phone: '13000130003', province: '北京市', city: '北京市', canDirectContact: 1, isMarried: 1, education: '本科' }); await disabledPersonRepository.save(person); const response = await client.getDisabledPerson[':id'].$get({ param: { id: person.id } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data?.name).toBe('测试人员详情'); expect(data?.education).toBe('本科'); expect(data?.canDirectContact).toBe(1); } }); it('应该处理不存在的残疾人ID', async () => { const response = await client.getDisabledPerson[':id'].$get({ param: { id: 99999 // 不存在的ID } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); // 返回200,但数据为null if (response.status === 200) { const data = await response.json(); expect(data).toBeNull(); } }); }); describe('GET /getDisabledPersonByIdCard', () => { it('应该成功根据身份证号查询残疾人', async () => { // 先创建一个残疾人 const dataSource = await IntegrationTestDatabase.getDataSource(); const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person = disabledPersonRepository.create({ name: '身份证查询测试', gender: '女', idCard: '110101199001011244', disabilityId: 'D123456768', disabilityType: '听力残疾', disabilityLevel: '三级', idAddress: '北京市密云区', phone: '13000130004', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); const response = await client.getDisabledPersonByIdCard.$get({ query: { idCard: '110101199001011244' } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data?.name).toBe('身份证查询测试'); expect(data?.idCard).toBe('110101199001011244'); } }); it('应该处理不存在的身份证号', async () => { const response = await client.getDisabledPersonByIdCard.$get({ query: { idCard: '999999999999999999' // 不存在的身份证号 } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); // 返回200,但数据为null if (response.status === 200) { const data = await response.json(); expect(data).toBeNull(); } }); }); describe('POST /createAggregatedDisabledPerson', () => { it('应该成功创建聚合残疾人信息(包含所有关联数据)', async () => { const createData = { disabledPerson: { name: '聚合创建测试', gender: '男', idCard: '110101199001011245', disabilityId: 'D123456767', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市延庆区', phone: '13000130005', province: '北京市', city: '北京市' }, bankCards: [ { bankName: '中国工商银行', cardNumber: '6222021234567890123', cardholderName: '聚合创建测试' } ], photos: [ { photoType: '身份证照片', fileId: testFile.id // 使用测试文件ID } ], remarks: [ { remarkType: '家庭情况', remarkContent: '家庭经济困难,需要帮助' } ], visits: [ { visitDate: '2025-12-02T10:00:00Z', visitContent: '初次回访,了解基本情况', visitor: '工作人员A' } ] }; const response = await client.createAggregatedDisabledPerson.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.disabledPerson.name).toBe('聚合创建测试'); expect(data.bankCards).toHaveLength(1); expect(data.photos).toHaveLength(1); expect(data.remarks).toHaveLength(1); expect(data.visits).toHaveLength(1); // 验证文件集成 expect(data.photos[0].fileId).toBe(testFile.id); } }); it('应该验证文件ID的有效性', async () => { const createData = { disabledPerson: { name: '文件验证测试', gender: '女', idCard: '110101199001011246', disabilityId: 'D123456766', disabilityType: '视力残疾', disabilityLevel: '二级', idAddress: '北京市房山区', phone: '13000130006', province: '北京市', city: '北京市' }, photos: [ { photoType: '身份证照片', fileId: 99999 // 不存在的文件ID } ] }; const response = await client.createAggregatedDisabledPerson.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); // 应该返回400,因为文件ID无效 }); }); describe('GET /getAggregatedDisabledPerson/{personId}', () => { it('应该成功获取聚合残疾人信息', async () => { // 先创建一个完整的残疾人数据(包含所有关联数据) const dataSource = await IntegrationTestDatabase.getDataSource(); // 创建残疾人 const disabledPersonRepository = dataSource.getRepository(DisabledPerson); const person = disabledPersonRepository.create({ name: '聚合查询测试', gender: '男', idCard: '110101199001011247', disabilityId: 'D123456765', disabilityType: '肢体残疾', disabilityLevel: '一级', idAddress: '北京市门头沟区', phone: '13000130007', province: '北京市', city: '北京市' }); await disabledPersonRepository.save(person); // 创建银行卡 const bankCardRepository = dataSource.getRepository(DisabledBankCard); const bankCard = bankCardRepository.create({ personId: person.id, bankName: '中国建设银行', cardNumber: '6227001234567890123', cardholderName: '聚合查询测试' }); await bankCardRepository.save(bankCard); // 创建照片(使用测试文件) const photoRepository = dataSource.getRepository(DisabledPhoto); const photo = photoRepository.create({ personId: person.id, photoType: '身份证照片', fileId: testFile.id }); await photoRepository.save(photo); // 创建备注 const remarkRepository = dataSource.getRepository(DisabledRemark); const remark = remarkRepository.create({ personId: person.id, remarkType: '工作情况', remarkContent: '目前无工作,需要就业帮助' }); await remarkRepository.save(remark); // 创建回访记录 const visitRepository = dataSource.getRepository(DisabledVisit); const visit = visitRepository.create({ personId: person.id, visitDate: new Date('2025-12-01T14:30:00Z'), visitContent: '了解就业需求', visitor: '工作人员B' }); await visitRepository.save(visit); const response = await client.getAggregatedDisabledPerson[':personId'].$get({ param: { personId: person.id } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.disabledPerson.name).toBe('聚合查询测试'); expect(data.bankCards).toHaveLength(1); expect(data.photos).toHaveLength(1); expect(data.remarks).toHaveLength(1); expect(data.visits).toHaveLength(1); // 验证文件数据完整性 expect(data.photos[0].fileId).toBe(testFile.id); } }); it('应该处理不存在的残疾人ID', async () => { const response = await client.getAggregatedDisabledPerson[':personId'].$get({ param: { personId: 99999 // 不存在的ID } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(404); }); }); describe('认证测试', () => { it('应该验证所有端点需要认证', async () => { // 测试没有token的情况 const response = await client.createDisabledPerson.$post({ json: { name: '测试人员' } }); expect(response.status).toBe(401); }); it('应该验证无效token', async () => { const response = await client.createDisabledPerson.$post({ json: { name: '测试人员' } }, { headers: { 'Authorization': 'Bearer invalid_token' } }); expect(response.status).toBe(401); }); }); });