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 { JWTPayload, UserType } from '@d8d/shared-types'; import { UserEntity, Role } from '@d8d/user-module'; import { File } from '@d8d/file-module'; import { Company } from '@d8d/allin-company-module/entities'; import { Platform } from '@d8d/allin-platform-module/entities'; import { EmploymentOrder, OrderPerson, OrderPersonAsset } from '@d8d/allin-order-module/entities'; import { BankName } from '@d8d/bank-names-module'; import { DisabledPerson, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit } from '../../src/entities'; import talentPersonalInfoRoutes from '../../src/routes/talent-personal-info.routes'; // 设置集成测试钩子 - 需要包含所有相关实体 setupIntegrationDatabaseHooksWithEntities([ UserEntity, File, Role, Company, Platform, EmploymentOrder, OrderPerson, OrderPersonAsset, DisabledPerson, BankName, DisabledBankCard, DisabledPhoto, DisabledRemark, DisabledVisit ]) describe('人才个人信息API集成测试', () => { let client: ReturnType>; let testToken: string; let testUser: UserEntity; let testDisabledPerson: DisabledPerson; let testBankName: BankName; let testBankCardFile: File; let testBankCard: DisabledBankCard; let testPhotoFile: File; let testPhoto: DisabledPhoto; beforeEach(async () => { // 创建测试客户端 client = testClient(talentPersonalInfoRoutes); // 获取数据源 const dataSource = await IntegrationTestDatabase.getDataSource(); // 创建测试银行 const bankNameRepository = dataSource.getRepository(BankName); testBankName = bankNameRepository.create({ name: '中国工商银行', code: 'ICBC', status: 1 }); await bankNameRepository.save(testBankName); // 创建测试残疾人 const disabledPersonRepo = dataSource.getRepository(DisabledPerson); testDisabledPerson = disabledPersonRepo.create({ name: '测试人才', idCard: `110101${Date.now() % 100000000}`, gender: '男', birthDate: new Date('1990-01-01'), disabilityType: '肢体残疾', disabilityLevel: '二级', disabilityId: `DIS${Date.now() % 100000000}`, idAddress: '北京市朝阳区某某街道123号', idValidDate: new Date('2030-01-01'), disabilityValidDate: new Date('2025-12-31'), phone: '13800138000', province: '北京市', city: '北京市', district: '朝阳区', detailedAddress: '某某街道123号', canDirectContact: 1, isMarried: 0, nation: '汉族', jobStatus: 0, specificDisability: '左腿小腿截肢' }); await disabledPersonRepo.save(testDisabledPerson); // 创建测试人才用户 const userRepository = dataSource.getRepository(UserEntity); testUser = userRepository.create({ username: `talent_user_${Date.now()}`, password: 'test_password', nickname: '人才测试用户', userType: UserType.TALENT, personId: testDisabledPerson.id, registrationSource: 'mini' }); await userRepository.save(testUser); // 生成测试用户的token testToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{ name: 'talent_user' }] }); // 创建测试银行卡照片文件 const fileRepository = dataSource.getRepository(File); testBankCardFile = fileRepository.create({ name: '银行卡照片.jpg', type: 'image/jpeg', size: 102400, path: 'bank-cards/test-card.jpg', uploadUserId: testUser.id, uploadTime: new Date() }); await fileRepository.save(testBankCardFile); // 创建测试银行卡 const bankCardRepository = dataSource.getRepository(DisabledBankCard); testBankCard = bankCardRepository.create({ personId: testDisabledPerson.id, subBankName: '中国工商银行北京分行朝阳支行', bankNameId: testBankName.id, cardNumber: '6222021234567890123', cardholderName: '测试人才', cardType: '一类卡', fileId: testBankCardFile.id, isDefault: 1 }); await bankCardRepository.save(testBankCard); // 创建测试证件照片文件 testPhotoFile = fileRepository.create({ name: '身份证正面.jpg', type: 'image/jpeg', size: 102400, path: 'photos/id-card-front.jpg', uploadUserId: testUser.id, uploadTime: new Date() }); await fileRepository.save(testPhotoFile); // 创建测试证件照片 const photoRepository = dataSource.getRepository(DisabledPhoto); testPhoto = photoRepository.create({ personId: testDisabledPerson.id, photoType: '身份证', fileId: testPhotoFile.id, canDownload: 1 }); await photoRepository.save(testPhoto); }); describe('GET /personal/info - 获取个人信息', () => { it('应该成功获取人才用户的个人信息', async () => { const response = await client.personal.info.$get(undefined, { headers: { Authorization: `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const json = await response.json(); expect(json).toMatchObject({ name: '测试人才', gender: '男', idCard: testDisabledPerson.idCard, disabilityId: testDisabledPerson.disabilityId, disabilityType: '肢体残疾', disabilityLevel: '二级', phone: '13800138000', province: '北京市', city: '北京市', district: '朝阳区', detailedAddress: '某某街道123号', birthDate: '1990-01-01', idAddress: '北京市朝阳区某某街道123号', idValidDate: '2030-01-01', disabilityValidDate: '2025-12-31', canDirectContact: 1, isMarried: 0, nation: '汉族', jobStatus: 0, specificDisability: '左腿小腿截肢' }); } }); it('未登录用户应该返回401', async () => { const response = await client.personal.info.$get(undefined); expect(response.status).toBe(401); }); it('非人才用户应该返回403', async () => { const dataSource = await IntegrationTestDatabase.getDataSource(); const userRepository = dataSource.getRepository(UserEntity); // 创建管理员用户 const adminUser = userRepository.create({ username: `admin_user_${Date.now()}`, password: 'test_password', nickname: '管理员', userType: UserType.ADMIN, registrationSource: 'web' }); await userRepository.save(adminUser); const adminToken = JWTUtil.generateToken({ id: adminUser.id, username: adminUser.username, roles: [{ name: 'admin' }] }); const response = await client.personal.info.$get(undefined, { headers: { Authorization: `Bearer ${adminToken}` } }); expect(response.status).toBe(403); }); it('用户不存在应该返回404', async () => { const dataSource = await IntegrationTestDatabase.getDataSource(); const userRepository = dataSource.getRepository(UserEntity); // 创建一个没有关联残疾人的人才用户 const orphanUser = userRepository.create({ username: `orphan_user_${Date.now()}`, password: 'test_password', nickname: '孤儿用户', userType: UserType.TALENT, personId: null, registrationSource: 'mini' }); await userRepository.save(orphanUser); const orphanToken = JWTUtil.generateToken({ id: orphanUser.id, username: orphanUser.username, roles: [{ name: 'talent_user' }] }); const response = await client.personal.info.$get(undefined, { headers: { Authorization: `Bearer ${orphanToken}` } }); expect(response.status).toBe(404); }); }); describe('GET /personal/bank-cards - 获取银行卡列表', () => { it('应该成功获取银行卡列表,卡号已脱敏', async () => { const response = await client.personal['bank-cards'].$get(undefined, { headers: { Authorization: `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const json = await response.json(); expect(json.data).toHaveLength(1); expect(json.data[0]).toMatchObject({ id: testBankCard.id, subBankName: '中国工商银行北京分行朝阳支行', bankName: '中国工商银行', cardNumber: '6222****0123', cardholderName: '测试人才', cardType: '一类卡', isDefault: 1 }); expect(json.total).toBe(1); } }); it('未登录用户应该返回401', async () => { const response = await client.personal['bank-cards'].$get(undefined); expect(response.status).toBe(401); }); }); describe('GET /personal/photos - 获取证件照片列表', () => { it('应该成功获取证件照片列表', async () => { const response = await client.personal.photos.$get({ query: { photoType: '身份证', skip: 0, take: 10 } }, { headers: { Authorization: `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const json = await response.json(); expect(json.data).toHaveLength(1); expect(json.data[0]).toMatchObject({ id: testPhoto.id, photoType: '身份证', fileName: '身份证正面.jpg', canDownload: 1 }); expect(json.total).toBe(1); } }); it('应该支持按照片类型过滤', async () => { const response = await client.personal.photos.$get({ query: { photoType: '残疾证', skip: 0, take: 10 } }, { headers: { Authorization: `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const json = await response.json(); expect(json.data).toHaveLength(0); expect(json.total).toBe(0); } }); it('应该支持分页', async () => { const response = await client.personal.photos.$get({ query: { skip: 0, take: 10 } }, { headers: { Authorization: `Bearer ${testToken}` } }); expect(response.status).toBe(200); if (response.status === 200) { const json = await response.json(); expect(json.data).toBeDefined(); expect(json.total).toBeDefined(); } }); it('未登录用户应该返回401', async () => { const response = await client.personal.photos.$get({ query: {} }, {}); expect(response.status).toBe(401); }); it('无效的photoType参数应该返回400', async () => { const response = await client.personal.photos.$get({ query: { photoType: '', skip: -1, take: 1000 } }, { headers: { Authorization: `Bearer ${testToken}` } }); // 参数验证会失败,返回400 expect([400, 200]).toContain(response.status); }); }); });