disability.integration.test.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. import { describe, it, expect, beforeEach } from 'vitest';
  2. import { testClient } from 'hono/testing';
  3. import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
  4. import { JWTUtil } from '@d8d/shared-utils';
  5. import { UserEntity, Role } from '@d8d/user-module';
  6. import { File } from '@d8d/file-module';
  7. import disabledPersonRoutes from '../../src/routes/disabled-person.routes';
  8. import { DisabledPerson } from '../../src/entities/disabled-person.entity';
  9. import { DisabledBankCard } from '../../src/entities/disabled-bank-card.entity';
  10. import { DisabledPhoto } from '../../src/entities/disabled-photo.entity';
  11. import { DisabledRemark } from '../../src/entities/disabled-remark.entity';
  12. import { DisabledVisit } from '../../src/entities/disabled-visit.entity';
  13. // 设置集成测试钩子 - 包含所有相关实体
  14. setupIntegrationDatabaseHooksWithEntities([
  15. UserEntity,
  16. Role,
  17. File,
  18. DisabledPerson,
  19. DisabledBankCard,
  20. DisabledPhoto,
  21. DisabledRemark,
  22. DisabledVisit
  23. ])
  24. describe('残疾人管理API集成测试', () => {
  25. let client: ReturnType<typeof testClient<typeof disabledPersonRoutes>>;
  26. let testToken: string;
  27. let testUser: UserEntity;
  28. let testFile: File;
  29. beforeEach(async () => {
  30. // 创建测试客户端
  31. client = testClient(disabledPersonRoutes);
  32. // 获取数据源
  33. const dataSource = await IntegrationTestDatabase.getDataSource();
  34. // 创建测试用户
  35. const userRepository = dataSource.getRepository(UserEntity);
  36. testUser = userRepository.create({
  37. username: `test_user_${Date.now()}`,
  38. password: 'test_password',
  39. nickname: '测试用户',
  40. registrationSource: 'web'
  41. });
  42. await userRepository.save(testUser);
  43. // 创建测试文件(用于照片集成测试)
  44. const fileRepository = dataSource.getRepository(File);
  45. testFile = fileRepository.create({
  46. name: 'test_photo.jpg',
  47. path: 'test_photo.jpg',
  48. type: 'image/jpeg',
  49. size: 1024,
  50. uploadUserId: testUser.id,
  51. uploadTime: new Date()
  52. });
  53. await fileRepository.save(testFile);
  54. // 生成测试用户的token
  55. testToken = JWTUtil.generateToken({
  56. id: testUser.id,
  57. username: testUser.username,
  58. roles: [{name:'user'}]
  59. });
  60. });
  61. describe('POST /createDisabledPerson', () => {
  62. it('应该成功创建残疾人基本信息', async () => {
  63. const createData = {
  64. name: '张三',
  65. gender: '男',
  66. idCard: '110101199001011234',
  67. disabilityId: 'D123456789',
  68. disabilityType: '肢体残疾',
  69. disabilityLevel: '一级',
  70. idAddress: '北京市东城区',
  71. phone: '13800138000',
  72. province: '北京市',
  73. city: '北京市',
  74. // 新增字段
  75. canDirectContact: 1,
  76. isInBlackList: 0,
  77. jobStatus: 1,
  78. specificDisability: '左眼视力0.1,右眼视力0.2,需要助听器',
  79. // 日期字段
  80. idValidDate: new Date('2030-12-31'),
  81. disabilityValidDate: new Date('2030-12-31')
  82. };
  83. const response = await client.createDisabledPerson.$post({
  84. json: createData
  85. }, {
  86. headers: {
  87. 'Authorization': `Bearer ${testToken}`
  88. }
  89. });
  90. expect(response.status).toBe(200);
  91. if (response.status === 200) {
  92. const data = await response.json();
  93. expect(data.name).toBe(createData.name);
  94. expect(data.idCard).toBe(createData.idCard);
  95. expect(data.disabilityId).toBe(createData.disabilityId);
  96. // 验证新增字段
  97. expect(data.canDirectContact).toBe(createData.canDirectContact);
  98. expect(data.isInBlackList).toBe(createData.isInBlackList);
  99. expect(data.jobStatus).toBe(createData.jobStatus);
  100. expect(data.specificDisability).toBe(createData.specificDisability);
  101. // 验证日期字段
  102. expect(data.idValidDate).toBeDefined();
  103. expect(data.disabilityValidDate).toBeDefined();
  104. if (data.idValidDate) {
  105. expect(new Date(data.idValidDate).toISOString().split('T')[0]).toBe('2030-12-31');
  106. }
  107. if (data.disabilityValidDate) {
  108. expect(new Date(data.disabilityValidDate).toISOString().split('T')[0]).toBe('2030-12-31');
  109. }
  110. }
  111. });
  112. it('应该验证身份证号唯一性', async () => {
  113. // 先创建一个残疾人
  114. const dataSource = await IntegrationTestDatabase.getDataSource();
  115. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  116. const existingPerson = disabledPersonRepository.create({
  117. name: '李四',
  118. gender: '女',
  119. idCard: '110101199001011235',
  120. disabilityId: 'D123456788',
  121. disabilityType: '视力残疾',
  122. disabilityLevel: '二级',
  123. idAddress: '北京市西城区',
  124. phone: '13900139000',
  125. province: '北京市',
  126. city: '北京市',
  127. // 新增字段
  128. canDirectContact: 0,
  129. isInBlackList: 0,
  130. jobStatus: 2,
  131. // 日期字段
  132. idValidDate: new Date('2035-05-15'),
  133. disabilityValidDate: new Date('2035-05-15')
  134. });
  135. await disabledPersonRepository.save(existingPerson);
  136. // 尝试创建相同身份证号的残疾人
  137. const createData = {
  138. name: '王五',
  139. gender: '男',
  140. idCard: '110101199001011235', // 重复的身份证号
  141. disabilityId: 'D123456777',
  142. disabilityType: '听力残疾',
  143. disabilityLevel: '三级',
  144. idAddress: '北京市朝阳区',
  145. phone: '13700137000',
  146. province: '北京市',
  147. city: '北京市',
  148. // 新增字段
  149. canDirectContact: 1,
  150. isInBlackList: 1,
  151. jobStatus: 3,
  152. // 日期字段
  153. idValidDate: new Date('2043-08-20'),
  154. disabilityValidDate: new Date('2043-08-20')
  155. };
  156. const response = await client.createDisabledPerson.$post({
  157. json: createData
  158. }, {
  159. headers: {
  160. 'Authorization': `Bearer ${testToken}`
  161. }
  162. });
  163. expect(response.status).toBe(400);
  164. });
  165. it('应该验证必填字段', async () => {
  166. const createData = {
  167. name: '', // 空字符串,应该验证失败
  168. gender: '男',
  169. idCard: '110101199001011236',
  170. disabilityId: 'D123456776',
  171. disabilityType: '肢体残疾',
  172. disabilityLevel: '一级',
  173. idAddress: '北京市海淀区',
  174. phone: '13600136000',
  175. province: '北京市',
  176. city: '北京市',
  177. // 新增字段(可选字段,不影响必填验证)
  178. canDirectContact: 1,
  179. isInBlackList: 0,
  180. jobStatus: 1,
  181. // 日期字段(可选字段,不影响必填验证)
  182. idValidDate: new Date('2028-03-10'),
  183. disabilityValidDate: new Date('2028-03-10')
  184. };
  185. const response = await client.createDisabledPerson.$post({
  186. json: createData
  187. }, {
  188. headers: {
  189. 'Authorization': `Bearer ${testToken}`
  190. }
  191. });
  192. expect(response.status).toBe(400);
  193. });
  194. it('应该验证具体残疾部位和情况字段为空值', async () => {
  195. const createData = {
  196. name: '空值测试',
  197. gender: '男',
  198. idCard: '110101199001011236',
  199. disabilityId: 'D123456776',
  200. disabilityType: '肢体残疾',
  201. disabilityLevel: '一级',
  202. idAddress: '北京市海淀区',
  203. phone: '13600136000',
  204. province: '北京市',
  205. city: '北京市',
  206. canDirectContact: 1,
  207. isInBlackList: 0,
  208. jobStatus: 1,
  209. // specificDisability 字段不提供,测试空值
  210. idValidDate: new Date('2028-03-10'),
  211. disabilityValidDate: new Date('2028-03-10')
  212. };
  213. const response = await client.createDisabledPerson.$post({
  214. json: createData
  215. }, {
  216. headers: {
  217. 'Authorization': `Bearer ${testToken}`
  218. }
  219. });
  220. expect(response.status).toBe(200);
  221. if (response.status === 200) {
  222. const data = await response.json();
  223. expect(data.name).toBe(createData.name);
  224. expect(data.specificDisability).toBeNull(); // 应该为null,因为数据库字段nullable: true
  225. }
  226. });
  227. it('应该验证具体残疾部位和情况字段为有效值', async () => {
  228. const createData = {
  229. name: '有效值测试',
  230. gender: '女',
  231. idCard: '110101199001011237',
  232. disabilityId: 'D123456775',
  233. disabilityType: '视力残疾',
  234. disabilityLevel: '二级',
  235. idAddress: '北京市朝阳区',
  236. phone: '13700137000',
  237. province: '北京市',
  238. city: '北京市',
  239. canDirectContact: 0,
  240. isInBlackList: 0,
  241. jobStatus: 0,
  242. specificDisability: '双眼视力均为0.05,需要导盲犬辅助',
  243. idValidDate: new Date('2030-06-15'),
  244. disabilityValidDate: new Date('2030-06-15')
  245. };
  246. const response = await client.createDisabledPerson.$post({
  247. json: createData
  248. }, {
  249. headers: {
  250. 'Authorization': `Bearer ${testToken}`
  251. }
  252. });
  253. expect(response.status).toBe(200);
  254. if (response.status === 200) {
  255. const data = await response.json();
  256. expect(data.name).toBe(createData.name);
  257. expect(data.specificDisability).toBe(createData.specificDisability);
  258. }
  259. });
  260. it('应该验证具体残疾部位和情况字段边界值(500字符)', async () => {
  261. // 生成500字符的字符串
  262. const maxLengthText = 'A'.repeat(500);
  263. const createData = {
  264. name: '边界值测试',
  265. gender: '男',
  266. idCard: '110101199001011238',
  267. disabilityId: 'D123456774',
  268. disabilityType: '听力残疾',
  269. disabilityLevel: '三级',
  270. idAddress: '北京市丰台区',
  271. phone: '13800138001',
  272. province: '北京市',
  273. city: '北京市',
  274. canDirectContact: 1,
  275. isInBlackList: 0,
  276. jobStatus: 1,
  277. specificDisability: maxLengthText,
  278. idValidDate: new Date('2032-08-20'),
  279. disabilityValidDate: new Date('2032-08-20')
  280. };
  281. const response = await client.createDisabledPerson.$post({
  282. json: createData
  283. }, {
  284. headers: {
  285. 'Authorization': `Bearer ${testToken}`
  286. }
  287. });
  288. expect(response.status).toBe(200);
  289. if (response.status === 200) {
  290. const data = await response.json();
  291. expect(data.name).toBe(createData.name);
  292. expect(data.specificDisability).toBe(createData.specificDisability);
  293. expect(data.specificDisability.length).toBe(500);
  294. }
  295. });
  296. it('应该验证具体残疾部位和情况字段超过500字符限制', async () => {
  297. // 生成501字符的字符串
  298. const tooLongText = 'A'.repeat(501);
  299. const createData = {
  300. name: '超长测试',
  301. gender: '女',
  302. idCard: '110101199001011239',
  303. disabilityId: 'D123456773',
  304. disabilityType: '言语残疾',
  305. disabilityLevel: '四级',
  306. idAddress: '北京市石景山区',
  307. phone: '13900139001',
  308. province: '北京市',
  309. city: '北京市',
  310. canDirectContact: 0,
  311. isInBlackList: 0,
  312. jobStatus: 0,
  313. specificDisability: tooLongText,
  314. idValidDate: new Date('2034-12-31'),
  315. disabilityValidDate: new Date('2034-12-31')
  316. };
  317. const response = await client.createDisabledPerson.$post({
  318. json: createData
  319. }, {
  320. headers: {
  321. 'Authorization': `Bearer ${testToken}`
  322. }
  323. });
  324. expect(response.status).toBe(400); // 应该返回400,因为超过长度限制
  325. });
  326. });
  327. describe('POST /deleteDisabledPerson', () => {
  328. it('应该成功删除残疾人', async () => {
  329. // 先创建一个残疾人
  330. const dataSource = await IntegrationTestDatabase.getDataSource();
  331. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  332. const person = disabledPersonRepository.create({
  333. name: '测试删除人员',
  334. gender: '男',
  335. idCard: '110101199001011237',
  336. disabilityId: 'D123456775',
  337. disabilityType: '肢体残疾',
  338. disabilityLevel: '一级',
  339. idAddress: '北京市石景山区',
  340. phone: '13500135000',
  341. province: '北京市',
  342. city: '北京市'
  343. });
  344. await disabledPersonRepository.save(person);
  345. const deleteData = {
  346. id: person.id
  347. };
  348. const response = await client.deleteDisabledPerson.$post({
  349. json: deleteData
  350. }, {
  351. headers: {
  352. 'Authorization': `Bearer ${testToken}`
  353. }
  354. });
  355. expect(response.status).toBe(200);
  356. if (response.status === 200) {
  357. const data = await response.json();
  358. expect(data.success).toBe(true);
  359. // 验证残疾人已被删除
  360. const deletedPerson = await disabledPersonRepository.findOne({ where: { id: person.id } });
  361. expect(deletedPerson).toBeNull();
  362. }
  363. });
  364. it('应该处理不存在的残疾人ID', async () => {
  365. const deleteData = {
  366. id: 99999 // 不存在的ID
  367. };
  368. const response = await client.deleteDisabledPerson.$post({
  369. json: deleteData
  370. }, {
  371. headers: {
  372. 'Authorization': `Bearer ${testToken}`
  373. }
  374. });
  375. expect(response.status).toBe(404);
  376. });
  377. });
  378. describe('POST /updateDisabledPerson', () => {
  379. it('应该成功更新残疾人信息', async () => {
  380. // 先创建一个残疾人
  381. const dataSource = await IntegrationTestDatabase.getDataSource();
  382. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  383. const person = disabledPersonRepository.create({
  384. name: '原始姓名',
  385. gender: '男',
  386. idCard: '110101199001011238',
  387. disabilityId: 'D123456774',
  388. disabilityType: '肢体残疾',
  389. disabilityLevel: '一级',
  390. idAddress: '北京市通州区',
  391. phone: '13400134000',
  392. province: '北京市',
  393. city: '北京市',
  394. // 新增字段初始值
  395. canDirectContact: 1,
  396. isInBlackList: 0,
  397. jobStatus: 1,
  398. // 日期字段初始值
  399. idValidDate: new Date('2023-01-01'),
  400. disabilityValidDate: new Date('2023-01-01')
  401. });
  402. await disabledPersonRepository.save(person);
  403. const updateData = {
  404. id: person.id,
  405. name: '更新后的姓名',
  406. gender: '女',
  407. phone: '13300133000',
  408. // 更新新增字段
  409. canDirectContact: 0,
  410. isInBlackList: 1,
  411. jobStatus: 1,
  412. // 更新日期字段
  413. idValidDate: new Date('2033-01-01'), // 更新有效期
  414. disabilityValidDate: new Date('2033-01-01') // 更新有效期
  415. };
  416. const response = await client.updateDisabledPerson.$post({
  417. json: updateData
  418. }, {
  419. headers: {
  420. 'Authorization': `Bearer ${testToken}`
  421. }
  422. });
  423. expect(response.status).toBe(200);
  424. if (response.status === 200) {
  425. const data = await response.json();
  426. expect(data.name).toBe(updateData.name);
  427. expect(data.gender).toBe(updateData.gender);
  428. expect(data.phone).toBe(updateData.phone);
  429. // 验证新增字段已更新
  430. expect(data.canDirectContact).toBe(updateData.canDirectContact);
  431. expect(data.isInBlackList).toBe(updateData.isInBlackList);
  432. expect(data.jobStatus).toBe(updateData.jobStatus);
  433. // 验证日期字段
  434. expect(data.idValidDate).toBeDefined();
  435. expect(data.disabilityValidDate).toBeDefined();
  436. if (data.idValidDate) {
  437. expect(new Date(data.idValidDate).toISOString().split('T')[0]).toBe('2033-01-01');
  438. }
  439. if (data.disabilityValidDate) {
  440. expect(new Date(data.disabilityValidDate).toISOString().split('T')[0]).toBe('2033-01-01');
  441. }
  442. }
  443. });
  444. it('应该验证身份证号唯一性(更新时)', async () => {
  445. // 创建两个残疾人
  446. const dataSource = await IntegrationTestDatabase.getDataSource();
  447. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  448. const person1 = disabledPersonRepository.create({
  449. name: '人员A',
  450. gender: '男',
  451. idCard: '110101199001011239',
  452. disabilityId: 'D123456773',
  453. disabilityType: '肢体残疾',
  454. disabilityLevel: '一级',
  455. idAddress: '北京市顺义区',
  456. phone: '13200132000',
  457. province: '北京市',
  458. city: '北京市',
  459. // 新增字段
  460. canDirectContact: 1,
  461. isInBlackList: 0,
  462. jobStatus: 1,
  463. // 日期字段
  464. idValidDate: new Date('2028-06-15'),
  465. disabilityValidDate: new Date('2028-06-15')
  466. });
  467. await disabledPersonRepository.save(person1);
  468. const person2 = disabledPersonRepository.create({
  469. name: '人员B',
  470. gender: '女',
  471. idCard: '110101199001011240',
  472. disabilityId: 'D123456772',
  473. disabilityType: '视力残疾',
  474. disabilityLevel: '二级',
  475. idAddress: '北京市大兴区',
  476. phone: '13100131000',
  477. province: '北京市',
  478. city: '北京市',
  479. // 新增字段
  480. canDirectContact: 0,
  481. isInBlackList: 1,
  482. jobStatus: 2,
  483. // 日期字段
  484. idValidDate: new Date('2034-09-20'),
  485. disabilityValidDate: new Date('2034-09-20')
  486. });
  487. await disabledPersonRepository.save(person2);
  488. // 尝试将人员2的身份证号改为人员1的身份证号
  489. const updateData = {
  490. id: person2.id,
  491. idCard: '110101199001011239' // 重复的身份证号
  492. };
  493. const response = await client.updateDisabledPerson.$post({
  494. json: updateData
  495. }, {
  496. headers: {
  497. 'Authorization': `Bearer ${testToken}`
  498. }
  499. });
  500. expect(response.status).toBe(400);
  501. });
  502. it('应该处理不存在的残疾人', async () => {
  503. const updateData = {
  504. id: 99999, // 不存在的ID
  505. name: '新姓名'
  506. };
  507. const response = await client.updateDisabledPerson.$post({
  508. json: updateData
  509. }, {
  510. headers: {
  511. 'Authorization': `Bearer ${testToken}`
  512. }
  513. });
  514. expect(response.status).toBe(404);
  515. });
  516. });
  517. describe('GET /getAllDisabledPersons', () => {
  518. it('应该成功获取残疾人列表(分页)', async () => {
  519. // 创建一些测试数据
  520. const dataSource = await IntegrationTestDatabase.getDataSource();
  521. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  522. for (let i = 1; i <= 5; i++) {
  523. const person = disabledPersonRepository.create({
  524. name: `残疾人${i}`,
  525. gender: i % 2 === 0 ? '女' : '男',
  526. idCard: `1101011990010112${40 + i}`,
  527. disabilityId: `D1234567${70 + i}`,
  528. disabilityType: '肢体残疾',
  529. disabilityLevel: '一级',
  530. idAddress: `北京市测试区${i}`,
  531. phone: `138001380${i}`,
  532. province: '北京市',
  533. city: '北京市'
  534. });
  535. await disabledPersonRepository.save(person);
  536. }
  537. const response = await client.getAllDisabledPersons.$get({
  538. query: {
  539. skip: 0,
  540. take: 10
  541. }
  542. }, {
  543. headers: {
  544. 'Authorization': `Bearer ${testToken}`
  545. }
  546. });
  547. expect(response.status).toBe(200);
  548. if (response.status === 200) {
  549. const data = await response.json();
  550. expect(data.data).toHaveLength(5);
  551. expect(data.total).toBe(5);
  552. expect(data.data[0].name).toBe('残疾人5'); // 按ID降序排列
  553. }
  554. });
  555. it('应该处理分页参数', async () => {
  556. // 创建更多测试数据
  557. const dataSource = await IntegrationTestDatabase.getDataSource();
  558. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  559. for (let i = 1; i <= 15; i++) {
  560. const person = disabledPersonRepository.create({
  561. name: `分页人员${i}`,
  562. gender: i % 2 === 0 ? '女' : '男',
  563. idCard: `1101011990010113${i}`,
  564. disabilityId: `D1234568${i}`,
  565. disabilityType: '肢体残疾',
  566. disabilityLevel: '一级',
  567. idAddress: `北京市分页区${i}`,
  568. phone: `138001381${i}`,
  569. province: '北京市',
  570. city: '北京市'
  571. });
  572. await disabledPersonRepository.save(person);
  573. }
  574. const response = await client.getAllDisabledPersons.$get({
  575. query: {
  576. skip: 5,
  577. take: 5
  578. }
  579. }, {
  580. headers: {
  581. 'Authorization': `Bearer ${testToken}`
  582. }
  583. });
  584. expect(response.status).toBe(200);
  585. if (response.status === 200) {
  586. const data = await response.json();
  587. expect(data.data).toHaveLength(5);
  588. expect(data.total).toBe(15);
  589. }
  590. });
  591. });
  592. describe('GET /searchDisabledPersons', () => {
  593. it('应该成功按姓名搜索残疾人', async () => {
  594. // 创建测试数据
  595. const dataSource = await IntegrationTestDatabase.getDataSource();
  596. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  597. const person1 = disabledPersonRepository.create({
  598. name: '张三',
  599. gender: '男',
  600. idCard: '110101199001011241',
  601. disabilityId: 'D123456771',
  602. disabilityType: '肢体残疾',
  603. disabilityLevel: '一级',
  604. idAddress: '北京市昌平区',
  605. phone: '13000130001',
  606. province: '北京市',
  607. city: '北京市'
  608. });
  609. await disabledPersonRepository.save(person1);
  610. const person2 = disabledPersonRepository.create({
  611. name: '李四',
  612. gender: '女',
  613. idCard: '110101199001011242',
  614. disabilityId: 'D123456770',
  615. disabilityType: '视力残疾',
  616. disabilityLevel: '二级',
  617. idAddress: '北京市平谷区',
  618. phone: '13000130002',
  619. province: '北京市',
  620. city: '北京市'
  621. });
  622. await disabledPersonRepository.save(person2);
  623. const response = await client.searchDisabledPersons.$get({
  624. query: {
  625. keyword: '张三',
  626. skip: 0,
  627. take: 10
  628. }
  629. }, {
  630. headers: {
  631. 'Authorization': `Bearer ${testToken}`
  632. }
  633. });
  634. expect(response.status).toBe(200);
  635. if (response.status === 200) {
  636. const data = await response.json();
  637. expect(data.data).toHaveLength(1);
  638. expect(data.data[0].name).toBe('张三');
  639. }
  640. });
  641. it('应该验证搜索关键词不能为空', async () => {
  642. const response = await client.searchDisabledPersons.$get({
  643. query: {
  644. keyword: '', // 空关键词
  645. skip: 0,
  646. take: 10
  647. }
  648. }, {
  649. headers: {
  650. 'Authorization': `Bearer ${testToken}`
  651. }
  652. });
  653. expect(response.status).toBe(400);
  654. });
  655. });
  656. describe('GET /getDisabledPerson/{id}', () => {
  657. it('应该成功获取单个残疾人详情', async () => {
  658. // 先创建一个残疾人
  659. const dataSource = await IntegrationTestDatabase.getDataSource();
  660. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  661. const person = disabledPersonRepository.create({
  662. name: '测试人员详情',
  663. gender: '男',
  664. idCard: '110101199001011243',
  665. disabilityId: 'D123456769',
  666. disabilityType: '肢体残疾',
  667. disabilityLevel: '一级',
  668. idAddress: '北京市怀柔区',
  669. phone: '13000130003',
  670. province: '北京市',
  671. city: '北京市',
  672. canDirectContact: 1,
  673. isMarried: 1
  674. });
  675. await disabledPersonRepository.save(person);
  676. const response = await client.getDisabledPerson[':id'].$get({
  677. param: {
  678. id: person.id
  679. }
  680. }, {
  681. headers: {
  682. 'Authorization': `Bearer ${testToken}`
  683. }
  684. });
  685. expect(response.status).toBe(200);
  686. if (response.status === 200) {
  687. const data = await response.json();
  688. expect(data?.name).toBe('测试人员详情');
  689. expect(data?.canDirectContact).toBe(1);
  690. }
  691. });
  692. it('应该处理不存在的残疾人ID', async () => {
  693. const response = await client.getDisabledPerson[':id'].$get({
  694. param: {
  695. id: 99999 // 不存在的ID
  696. }
  697. }, {
  698. headers: {
  699. 'Authorization': `Bearer ${testToken}`
  700. }
  701. });
  702. expect(response.status).toBe(200); // 返回200,但数据为null
  703. if (response.status === 200) {
  704. const data = await response.json();
  705. expect(data).toBeNull();
  706. }
  707. });
  708. });
  709. describe('GET /getDisabledPersonByIdCard', () => {
  710. it('应该成功根据身份证号查询残疾人', async () => {
  711. // 先创建一个残疾人
  712. const dataSource = await IntegrationTestDatabase.getDataSource();
  713. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  714. const person = disabledPersonRepository.create({
  715. name: '身份证查询测试',
  716. gender: '女',
  717. idCard: '110101199001011244',
  718. disabilityId: 'D123456768',
  719. disabilityType: '听力残疾',
  720. disabilityLevel: '三级',
  721. idAddress: '北京市密云区',
  722. phone: '13000130004',
  723. province: '北京市',
  724. city: '北京市'
  725. });
  726. await disabledPersonRepository.save(person);
  727. const response = await client.findByIdCard[':idCard'].$get({
  728. param: {
  729. idCard: '110101199001011244'
  730. }
  731. }, {
  732. headers: {
  733. 'Authorization': `Bearer ${testToken}`
  734. }
  735. });
  736. expect(response.status).toBe(200);
  737. if (response.status === 200) {
  738. const data = await response.json();
  739. expect(data?.name).toBe('身份证查询测试');
  740. expect(data?.idCard).toBe('110101199001011244');
  741. }
  742. });
  743. it('应该处理不存在的身份证号', async () => {
  744. const response = await client.findByIdCard[':idCard'].$get({
  745. param: {
  746. idCard: '999999999999999999' // 不存在的身份证号
  747. }
  748. }, {
  749. headers: {
  750. 'Authorization': `Bearer ${testToken}`
  751. }
  752. });
  753. expect(response.status).toBe(200); // 返回200,但数据为null
  754. if (response.status === 200) {
  755. const data = await response.json();
  756. expect(data).toBeNull();
  757. }
  758. });
  759. });
  760. describe('POST /createAggregatedDisabledPerson', () => {
  761. it('应该成功创建聚合残疾人信息(包含所有关联数据)', async () => {
  762. const createData = {
  763. personInfo: {
  764. name: '聚合创建测试',
  765. gender: '男',
  766. idCard: '110101199001011245',
  767. disabilityId: 'D123456767',
  768. disabilityType: '肢体残疾',
  769. disabilityLevel: '一级',
  770. idAddress: '北京市延庆区',
  771. phone: '13000130005',
  772. province: '北京市',
  773. city: '北京市',
  774. // 新增字段
  775. canDirectContact: 1,
  776. isInBlackList: 0,
  777. jobStatus: 1,
  778. specificDisability: '左腿截肢,右腿行动不便,需要轮椅',
  779. // 日期字段
  780. idValidDate: new Date('2045-11-30'),
  781. disabilityValidDate: new Date('2045-11-30')
  782. },
  783. bankCards: [
  784. {
  785. subBankName: '北京分行',
  786. bankName: '中国工商银行',
  787. cardNumber: '6222021234567890123',
  788. cardholderName: '聚合创建测试',
  789. fileId: testFile.id,
  790. isDefault: 0
  791. }
  792. ],
  793. photos: [
  794. {
  795. photoType: '身份证照片',
  796. fileId: testFile.id // 使用测试文件ID
  797. }
  798. ],
  799. remarks: [
  800. {
  801. remarkContent: '家庭经济困难,需要帮助',
  802. operatorId: 1
  803. }
  804. ],
  805. visits: [
  806. {
  807. visitDate: '2025-12-02T10:00:00Z',
  808. visitType: '电话回访',
  809. visitContent: '初次回访,了解基本情况',
  810. visitorId: 1
  811. }
  812. ]
  813. };
  814. const response = await client.createAggregatedDisabledPerson.$post({
  815. json: createData
  816. }, {
  817. headers: {
  818. 'Authorization': `Bearer ${testToken}`
  819. }
  820. });
  821. expect(response.status).toBe(200);
  822. if (response.status === 200) {
  823. const data = await response.json();
  824. expect(data.personInfo.name).toBe('聚合创建测试');
  825. // 验证新增字段
  826. expect(data.personInfo.canDirectContact).toBe(1);
  827. expect(data.personInfo.isInBlackList).toBe(0);
  828. expect(data.personInfo.jobStatus).toBe(1);
  829. expect(data.personInfo.specificDisability).toBe('左腿截肢,右腿行动不便,需要轮椅');
  830. // 验证日期字段
  831. expect(data.personInfo.idValidDate).toBeDefined();
  832. expect(data.personInfo.disabilityValidDate).toBeDefined();
  833. if (data.personInfo.idValidDate) {
  834. expect(new Date(data.personInfo.idValidDate).toISOString().split('T')[0]).toBe('2045-11-30');
  835. }
  836. if (data.personInfo.disabilityValidDate) {
  837. expect(new Date(data.personInfo.disabilityValidDate).toISOString().split('T')[0]).toBe('2045-11-30');
  838. }
  839. expect(data.bankCards).toHaveLength(1);
  840. expect(data.photos).toHaveLength(1);
  841. expect(data.remarks).toHaveLength(1);
  842. expect(data.visits).toHaveLength(1);
  843. // 验证文件集成
  844. expect(data.photos[0].fileId).toBe(testFile.id);
  845. }
  846. });
  847. it('应该验证文件ID的有效性', async () => {
  848. const createData = {
  849. personInfo: {
  850. name: '文件验证测试',
  851. gender: '女',
  852. idCard: '110101199001011246',
  853. disabilityId: 'D123456766',
  854. disabilityType: '视力残疾',
  855. disabilityLevel: '二级',
  856. idAddress: '北京市房山区',
  857. phone: '13000130006',
  858. province: '北京市',
  859. city: '北京市',
  860. // 新增字段
  861. canDirectContact: 0,
  862. isInBlackList: 1,
  863. jobStatus: 2,
  864. // 日期字段
  865. idValidDate: new Date('2036-07-25'),
  866. disabilityValidDate: new Date('2036-07-25')
  867. },
  868. photos: [
  869. {
  870. photoType: '身份证照片',
  871. fileId: 99999 // 不存在的文件ID
  872. }
  873. ]
  874. };
  875. const response = await client.createAggregatedDisabledPerson.$post({
  876. json: createData
  877. }, {
  878. headers: {
  879. 'Authorization': `Bearer ${testToken}`
  880. }
  881. });
  882. expect(response.status).toBe(400); // 应该返回400,因为文件ID无效
  883. });
  884. });
  885. describe('GET /getAggregatedDisabledPerson/{personId}', () => {
  886. it('应该成功获取聚合残疾人信息', async () => {
  887. // 先创建一个完整的残疾人数据(包含所有关联数据)
  888. const dataSource = await IntegrationTestDatabase.getDataSource();
  889. // 创建残疾人
  890. const disabledPersonRepository = dataSource.getRepository(DisabledPerson);
  891. const person = disabledPersonRepository.create({
  892. name: '聚合查询测试',
  893. gender: '男',
  894. idCard: '110101199001011247',
  895. disabilityId: 'D123456765',
  896. disabilityType: '肢体残疾',
  897. disabilityLevel: '一级',
  898. idAddress: '北京市门头沟区',
  899. phone: '13000130007',
  900. province: '北京市',
  901. city: '北京市'
  902. });
  903. await disabledPersonRepository.save(person);
  904. // 创建银行卡
  905. const bankCardRepository = dataSource.getRepository(DisabledBankCard);
  906. const bankCard = bankCardRepository.create({
  907. personId: person.id,
  908. subBankName: '北京分行',
  909. bankName: '中国建设银行',
  910. cardNumber: '6227001234567890123',
  911. cardholderName: '聚合查询测试',
  912. fileId: testFile.id,
  913. isDefault: 0
  914. });
  915. await bankCardRepository.save(bankCard);
  916. // 创建照片(使用测试文件)
  917. const photoRepository = dataSource.getRepository(DisabledPhoto);
  918. const photo = photoRepository.create({
  919. personId: person.id,
  920. photoType: '身份证照片',
  921. fileId: testFile.id
  922. });
  923. await photoRepository.save(photo);
  924. // 创建备注
  925. const remarkRepository = dataSource.getRepository(DisabledRemark);
  926. const remark = remarkRepository.create({
  927. personId: person.id,
  928. remarkContent: '目前无工作,需要就业帮助',
  929. operatorId: 1
  930. });
  931. await remarkRepository.save(remark);
  932. // 创建回访记录
  933. const visitRepository = dataSource.getRepository(DisabledVisit);
  934. const visit = visitRepository.create({
  935. personId: person.id,
  936. visitDate: new Date('2025-12-01T14:30:00Z'),
  937. visitType: '上门回访',
  938. visitContent: '了解就业需求',
  939. visitorId: 2
  940. });
  941. await visitRepository.save(visit);
  942. const response = await client.getAggregatedDisabledPerson[':id'].$get({
  943. param: {
  944. id: person.id
  945. }
  946. }, {
  947. headers: {
  948. 'Authorization': `Bearer ${testToken}`
  949. }
  950. });
  951. // 调试:打印响应状态和错误信息
  952. console.debug('响应状态:', response.status);
  953. if (response.status !== 200) {
  954. const errorText = await response.text();
  955. console.debug('错误响应:', errorText);
  956. }
  957. expect(response.status).toBe(200);
  958. if (response.status === 200) {
  959. const data = await response.json();
  960. expect(data).not.toBeNull();
  961. expect(data!.personInfo.name).toBe('聚合查询测试');
  962. expect(data!.bankCards).toHaveLength(1);
  963. expect(data!.photos).toHaveLength(1);
  964. expect(data!.remarks).toHaveLength(1);
  965. expect(data!.visits).toHaveLength(1);
  966. // 验证文件数据完整性
  967. expect(data!.photos[0].fileId).toBe(testFile.id);
  968. }
  969. });
  970. it('应该处理不存在的残疾人ID', async () => {
  971. const response = await client.getAggregatedDisabledPerson[':id'].$get({
  972. param: {
  973. id: 99999 // 不存在的ID
  974. }
  975. }, {
  976. headers: {
  977. 'Authorization': `Bearer ${testToken}`
  978. }
  979. });
  980. expect(response.status).toBe(404);
  981. });
  982. });
  983. describe('认证测试', () => {
  984. it('应该验证所有端点需要认证', async () => {
  985. // 测试没有token的情况
  986. const response = await client.createDisabledPerson.$post({
  987. json: {
  988. name: '测试人员',
  989. gender: '男',
  990. idCard: '110101199001011235',
  991. disabilityId: 'D123456789',
  992. disabilityType: '视力残疾',
  993. disabilityLevel: '一级',
  994. idAddress: '北京市东城区',
  995. phone: '13800138000',
  996. province: '北京市',
  997. city: '北京市'
  998. }
  999. });
  1000. expect(response.status).toBe(401);
  1001. });
  1002. it('应该验证无效token', async () => {
  1003. const response = await client.createDisabledPerson.$post({
  1004. json: {
  1005. name: '测试人员',
  1006. gender: '男',
  1007. idCard: '110101199001011236',
  1008. disabilityId: 'D123456790',
  1009. disabilityType: '视力残疾',
  1010. disabilityLevel: '一级',
  1011. idAddress: '北京市东城区',
  1012. phone: '13800138001',
  1013. province: '北京市',
  1014. city: '北京市'
  1015. }
  1016. }, {
  1017. headers: {
  1018. 'Authorization': 'Bearer invalid_token'
  1019. }
  1020. });
  1021. expect(response.status).toBe(401);
  1022. });
  1023. });
  1024. });