salary.integration.test.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  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 { AreaEntity } from '@d8d/geo-areas';
  8. import salaryRoutes from '../../src/routes/salary.routes';
  9. import { SalaryLevel } from '../../src/entities/salary-level.entity';
  10. // 设置集成测试钩子
  11. setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, AreaEntity, SalaryLevel])
  12. describe('薪资管理API集成测试', () => {
  13. let client: ReturnType<typeof testClient<typeof salaryRoutes>>;
  14. let testToken: string;
  15. let testUser: UserEntity;
  16. let testProvince: AreaEntity;
  17. let testCity: AreaEntity;
  18. let testDistrict: AreaEntity;
  19. let testProvince2: AreaEntity;
  20. let testCity2: AreaEntity;
  21. beforeEach(async () => {
  22. // 创建测试客户端
  23. client = testClient(salaryRoutes);
  24. // 获取数据源
  25. const dataSource = await IntegrationTestDatabase.getDataSource();
  26. // 创建测试用户
  27. const userRepository = dataSource.getRepository(UserEntity);
  28. testUser = userRepository.create({
  29. username: `test_user_${Date.now()}`,
  30. password: 'test_password',
  31. nickname: '测试用户',
  32. registrationSource: 'web'
  33. });
  34. await userRepository.save(testUser);
  35. // 生成测试用户的token
  36. testToken = JWTUtil.generateToken({
  37. id: testUser.id,
  38. username: testUser.username,
  39. roles: [{name:'user'}]
  40. });
  41. // 创建测试区域数据
  42. const areaRepository = dataSource.getRepository(AreaEntity);
  43. // 创建省份
  44. testProvince = areaRepository.create({
  45. code: '110000',
  46. name: '北京市',
  47. level: 1,
  48. parentId: null
  49. });
  50. await areaRepository.save(testProvince);
  51. // 创建城市
  52. testCity = areaRepository.create({
  53. code: '110100',
  54. name: '北京市',
  55. level: 2,
  56. parentId: testProvince.id
  57. });
  58. await areaRepository.save(testCity);
  59. // 创建区县
  60. testDistrict = areaRepository.create({
  61. code: '110101',
  62. name: '东城区',
  63. level: 3,
  64. parentId: testCity.id
  65. });
  66. await areaRepository.save(testDistrict);
  67. // 创建第二个省份
  68. testProvince2 = areaRepository.create({
  69. code: '120000',
  70. name: '天津市',
  71. level: 1,
  72. parentId: null
  73. });
  74. await areaRepository.save(testProvince2);
  75. // 创建第二个城市
  76. testCity2 = areaRepository.create({
  77. code: '120100',
  78. name: '天津市',
  79. level: 2,
  80. parentId: testProvince2.id
  81. });
  82. await areaRepository.save(testCity2);
  83. });
  84. describe('POST /salary/create', () => {
  85. it('应该成功创建薪资水平', async () => {
  86. const createData = {
  87. provinceId: testProvince.id,
  88. cityId: testCity.id,
  89. districtId: testDistrict.id,
  90. basicSalary: 5000.00
  91. };
  92. console.debug('发送的创建数据:', JSON.stringify(createData, null, 2));
  93. const response = await client.create.$post({
  94. json: createData
  95. }, {
  96. headers: {
  97. 'Authorization': `Bearer ${testToken}`
  98. }
  99. });
  100. if (response.status !== 200) {
  101. const error = await response.json();
  102. console.debug('创建薪资失败:', JSON.stringify(error, null, 2));
  103. }
  104. expect(response.status).toBe(200);
  105. if (response.status === 200) {
  106. const data = await response.json();
  107. expect(data.id).toBeDefined();
  108. expect(data.provinceId).toBe(testProvince.id);
  109. expect(data.cityId).toBe(testCity.id);
  110. expect(data.districtId).toBe(testDistrict.id);
  111. expect(data.basicSalary).toBe(5000.00);
  112. expect(data.totalSalary).toBe(5000.00); // 只有基本工资
  113. }
  114. });
  115. it('应该验证区域层级关系', async () => {
  116. const createData = {
  117. provinceId: testProvince.id,
  118. cityId: testDistrict.id, // 错误的层级:城市ID使用了区县ID
  119. districtId: testCity.id, // 错误的层级:区县ID使用了城市ID
  120. basicSalary: 5000.00
  121. };
  122. const response = await client.create.$post({
  123. json: createData
  124. }, {
  125. headers: {
  126. 'Authorization': `Bearer ${testToken}`
  127. }
  128. });
  129. expect(response.status).toBe(400);
  130. });
  131. it('应该验证中文错误消息 - 缺少必填字段', async () => {
  132. const createData = {
  133. provinceId: 0, // 发送0而不是null
  134. cityId: 0, // 发送0而不是null
  135. basicSalary: 5000.00
  136. };
  137. const response = await client.create.$post({
  138. json: createData
  139. }, {
  140. headers: {
  141. 'Authorization': `Bearer ${testToken}`
  142. }
  143. });
  144. expect(response.status).toBe(400);
  145. if (response.status === 400) {
  146. const errorData = await response.json() as any;
  147. console.debug('缺少必填字段错误响应:', JSON.stringify(errorData, null, 2));
  148. // 验证错误响应格式 - 根据实际响应调整
  149. if ('success' in errorData) {
  150. // 格式: { success: boolean; error: { name: string; message: string } }
  151. expect(errorData.success).toBe(false);
  152. expect(errorData.error).toHaveProperty('name');
  153. expect(errorData.error.name).toBe('ZodError');
  154. expect(errorData.error).toHaveProperty('message');
  155. // 解析错误消息
  156. const errorMessages = JSON.parse(errorData.error.message);
  157. expect(Array.isArray(errorMessages)).toBe(true);
  158. // 验证具体的错误消息
  159. const errorTexts = errorMessages.map((err: any) => err.message);
  160. expect(errorTexts).toContain('请选择省份');
  161. expect(errorTexts).toContain('请选择城市');
  162. } else {
  163. // 格式: { code: number; message: string; errors?: any }
  164. expect(errorData.code).toBe(400);
  165. expect(errorData.message).toBe('参数错误');
  166. expect(errorData).toHaveProperty('errors');
  167. expect(Array.isArray(errorData.errors)).toBe(true);
  168. // 验证具体的错误消息
  169. const errorTexts = errorData.errors.map((err: any) => err.message);
  170. expect(errorTexts).toContain('请选择省份');
  171. expect(errorTexts).toContain('请选择城市');
  172. }
  173. }
  174. });
  175. it('应该验证中文错误消息 - 基本工资为0', async () => {
  176. const createData = {
  177. provinceId: testProvince.id,
  178. cityId: testCity.id,
  179. basicSalary: 0 // 基本工资为0,应该触发错误
  180. };
  181. const response = await client.create.$post({
  182. json: createData
  183. }, {
  184. headers: {
  185. 'Authorization': `Bearer ${testToken}`
  186. }
  187. });
  188. expect(response.status).toBe(400);
  189. if (response.status === 400) {
  190. const errorData = await response.json() as any;
  191. console.debug('基本工资为0错误响应:', JSON.stringify(errorData, null, 2));
  192. // 验证错误响应格式 - 支持两种格式
  193. if (errorData.success !== undefined) {
  194. // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
  195. expect(errorData.success).toBe(false);
  196. expect(errorData).toHaveProperty('error');
  197. expect(errorData.error).toHaveProperty('name');
  198. expect(errorData.error.name).toBe('ZodError');
  199. expect(errorData.error).toHaveProperty('message');
  200. // 解析错误消息
  201. const errorMessages = JSON.parse(errorData.error.message);
  202. expect(Array.isArray(errorMessages)).toBe(true);
  203. // 验证具体的错误消息
  204. const errorTexts = errorMessages.map((err: any) => err.message);
  205. expect(errorTexts).toContain('基本工资必须大于0');
  206. } else {
  207. // 格式: { code: number; message: string; errors?: any }
  208. expect(errorData.code).toBe(400);
  209. expect(errorData.message).toBe('参数错误');
  210. expect(errorData).toHaveProperty('errors');
  211. expect(Array.isArray(errorData.errors)).toBe(true);
  212. // 验证具体的错误消息
  213. const errorTexts = errorData.errors.map((err: any) => err.message);
  214. expect(errorTexts).toContain('基本工资必须大于0');
  215. }
  216. }
  217. });
  218. it('应该验证中文错误消息 - 津贴补贴为负数', async () => {
  219. const createData = {
  220. provinceId: testProvince.id,
  221. cityId: testCity.id,
  222. basicSalary: 5000.00,
  223. allowance: -100 // 津贴补贴为负数,应该触发错误
  224. };
  225. const response = await client.create.$post({
  226. json: createData
  227. }, {
  228. headers: {
  229. 'Authorization': `Bearer ${testToken}`
  230. }
  231. });
  232. expect(response.status).toBe(400);
  233. if (response.status === 400) {
  234. const errorData = await response.json() as any;
  235. console.debug('津贴补贴为负数错误响应:', JSON.stringify(errorData, null, 2));
  236. // 验证错误响应格式 - 支持两种格式
  237. if (errorData.success !== undefined) {
  238. // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
  239. expect(errorData.success).toBe(false);
  240. expect(errorData).toHaveProperty('error');
  241. expect(errorData.error).toHaveProperty('name');
  242. expect(errorData.error.name).toBe('ZodError');
  243. expect(errorData.error).toHaveProperty('message');
  244. // 解析错误消息
  245. const errorMessages = JSON.parse(errorData.error.message);
  246. expect(Array.isArray(errorMessages)).toBe(true);
  247. // 验证具体的错误消息
  248. const errorTexts = errorMessages.map((err: any) => err.message);
  249. expect(errorTexts).toContain('津贴补贴不能为负数');
  250. } else {
  251. // 格式: { code: number; message: string; errors?: any }
  252. expect(errorData.code).toBe(400);
  253. expect(errorData.message).toBe('参数错误');
  254. expect(errorData).toHaveProperty('errors');
  255. expect(Array.isArray(errorData.errors)).toBe(true);
  256. // 验证具体的错误消息
  257. const errorTexts = errorData.errors.map((err: any) => err.message);
  258. expect(errorTexts).toContain('津贴补贴不能为负数');
  259. }
  260. }
  261. });
  262. it('应该验证中文错误消息 - 类型转换错误', async () => {
  263. const createData = {
  264. provinceId: testProvince.id,
  265. cityId: testCity.id,
  266. basicSalary: '不是数字' as any, // 字符串,应该触发类型转换错误
  267. allowance: 100
  268. };
  269. const response = await client.create.$post({
  270. json: createData
  271. }, {
  272. headers: {
  273. 'Authorization': `Bearer ${testToken}`
  274. }
  275. });
  276. expect(response.status).toBe(400);
  277. if (response.status === 400) {
  278. const errorData = await response.json() as any;
  279. console.debug('类型转换错误响应:', JSON.stringify(errorData, null, 2));
  280. // 验证错误响应格式 - 支持两种格式
  281. if (errorData.success !== undefined) {
  282. // 格式: { success: false, error: { name: 'ZodError', message: '...' } }
  283. expect(errorData.success).toBe(false);
  284. expect(errorData).toHaveProperty('error');
  285. expect(errorData.error).toHaveProperty('name');
  286. expect(errorData.error.name).toBe('ZodError');
  287. expect(errorData.error).toHaveProperty('message');
  288. // 解析错误消息
  289. const errorMessages = JSON.parse(errorData.error.message);
  290. expect(Array.isArray(errorMessages)).toBe(true);
  291. // 验证具体的错误消息
  292. const errorTexts = errorMessages.map((err: any) => err.message);
  293. console.debug('类型转换错误消息:', errorTexts);
  294. // 类型转换错误显示我们设置的中文错误消息
  295. expect(errorTexts).toContain('基本工资必须大于0');
  296. } else {
  297. // 格式: { code: number; message: string; errors?: any }
  298. expect(errorData.code).toBe(400);
  299. expect(errorData.message).toBe('参数错误');
  300. expect(errorData).toHaveProperty('errors');
  301. expect(Array.isArray(errorData.errors)).toBe(true);
  302. // 验证具体的错误消息
  303. const errorTexts = errorData.errors.map((err: any) => err.message);
  304. console.debug('类型转换错误消息:', errorTexts);
  305. expect(errorTexts).toContain('基本工资必须大于0');
  306. }
  307. }
  308. });
  309. it('应该验证区域唯一性约束', async () => {
  310. // 第一次创建
  311. const createData = {
  312. provinceId: testProvince.id,
  313. cityId: testCity.id,
  314. basicSalary: 5000.00
  315. };
  316. const firstResponse = await client.create.$post({
  317. json: createData
  318. }, {
  319. headers: {
  320. 'Authorization': `Bearer ${testToken}`
  321. }
  322. });
  323. expect(firstResponse.status).toBe(200);
  324. // 第二次创建相同区域
  325. const secondResponse = await client.create.$post({
  326. json: createData
  327. }, {
  328. headers: {
  329. 'Authorization': `Bearer ${testToken}`
  330. }
  331. });
  332. expect(secondResponse.status).toBe(400);
  333. });
  334. });
  335. describe('GET /salary/list', () => {
  336. beforeEach(async () => {
  337. // 创建测试数据
  338. const dataSource = await IntegrationTestDatabase.getDataSource();
  339. const salaryRepository = dataSource.getRepository(SalaryLevel);
  340. const salary1 = salaryRepository.create({
  341. provinceId: testProvince.id,
  342. cityId: testCity.id,
  343. districtId: testDistrict.id,
  344. basicSalary: 5000.00,
  345. allowance: 1000.00,
  346. insurance: 500.00,
  347. housingFund: 800.00,
  348. totalSalary: 7300.00
  349. });
  350. await salaryRepository.save(salary1);
  351. const salary2 = salaryRepository.create({
  352. provinceId: testProvince2.id, // 使用不同的省份
  353. cityId: testCity2.id, // 使用不同的城市
  354. basicSalary: 6000.00,
  355. allowance: 1200.00,
  356. insurance: 600.00,
  357. housingFund: 900.00,
  358. totalSalary: 8700.00
  359. });
  360. await salaryRepository.save(salary2);
  361. });
  362. it('应该返回所有薪资水平列表', async () => {
  363. const response = await client.list.$get({
  364. query: {}
  365. }, {
  366. headers: {
  367. 'Authorization': `Bearer ${testToken}`
  368. }
  369. });
  370. expect(response.status).toBe(200);
  371. if (response.status === 200) {
  372. const data = await response.json();
  373. expect(data).toHaveProperty('data');
  374. expect(data).toHaveProperty('total');
  375. expect(data.data).toHaveLength(2);
  376. expect(data.total).toBe(2);
  377. }
  378. });
  379. it('应该支持按区域ID过滤', async () => {
  380. const response = await client.list.$get({
  381. query: {
  382. provinceId: testProvince.id,
  383. cityId: testCity.id
  384. }
  385. }, {
  386. headers: {
  387. 'Authorization': `Bearer ${testToken}`
  388. }
  389. });
  390. expect(response.status).toBe(200);
  391. if (response.status === 200) {
  392. const data = await response.json();
  393. expect(data.data).toHaveLength(1);
  394. }
  395. });
  396. it('应该支持分页查询', async () => {
  397. const response = await client.list.$get({
  398. query: {
  399. skip: 0,
  400. take: 1
  401. }
  402. }, {
  403. headers: {
  404. 'Authorization': `Bearer ${testToken}`
  405. }
  406. });
  407. expect(response.status).toBe(200);
  408. if (response.status === 200) {
  409. const data = await response.json();
  410. expect(data.data).toHaveLength(1);
  411. expect(data.total).toBe(2);
  412. }
  413. });
  414. });
  415. describe('GET /salary/detail/:id', () => {
  416. let testSalary: SalaryLevel;
  417. beforeEach(async () => {
  418. // 创建测试薪资数据
  419. const dataSource = await IntegrationTestDatabase.getDataSource();
  420. const salaryRepository = dataSource.getRepository(SalaryLevel);
  421. testSalary = salaryRepository.create({
  422. provinceId: testProvince.id,
  423. cityId: testCity.id,
  424. districtId: testDistrict.id,
  425. basicSalary: 5000.00,
  426. allowance: 1000.00,
  427. insurance: 500.00,
  428. housingFund: 800.00,
  429. totalSalary: 7300.00,
  430. });
  431. await salaryRepository.save(testSalary);
  432. });
  433. it('应该返回指定ID的薪资详情', async () => {
  434. const response = await client.detail[':id'].$get({
  435. param: { id: testSalary.id.toString() }
  436. }, {
  437. headers: {
  438. 'Authorization': `Bearer ${testToken}`
  439. }
  440. });
  441. expect(response.status).toBe(200);
  442. if (response.status === 200) {
  443. const data = await response.json();
  444. expect(data?.id).toBe(testSalary.id);
  445. expect(data?.provinceId).toBe(testProvince.id);
  446. expect(data?.cityId).toBe(testCity.id);
  447. }
  448. });
  449. it('应该处理不存在的薪资ID', async () => {
  450. const response = await client.detail[':id'].$get({
  451. param: { id: 999999 }
  452. }, {
  453. headers: {
  454. 'Authorization': `Bearer ${testToken}`
  455. }
  456. });
  457. expect(response.status).toBe(404);
  458. });
  459. });
  460. describe('GET /salary/byProvinceCity', () => {
  461. let testSalary: SalaryLevel;
  462. beforeEach(async () => {
  463. // 创建测试薪资数据
  464. const dataSource = await IntegrationTestDatabase.getDataSource();
  465. const salaryRepository = dataSource.getRepository(SalaryLevel);
  466. testSalary = salaryRepository.create({
  467. provinceId: testProvince.id,
  468. cityId: testCity.id,
  469. basicSalary: 5000.00,
  470. allowance: 1000.00,
  471. insurance: 500.00,
  472. housingFund: 800.00,
  473. totalSalary: 7300.00,
  474. });
  475. await salaryRepository.save(testSalary);
  476. });
  477. it('应该按省份城市查询薪资', async () => {
  478. const response = await client.byProvinceCity.$get({
  479. query: {
  480. provinceId: testProvince.id,
  481. cityId: testCity.id
  482. }
  483. }, {
  484. headers: {
  485. 'Authorization': `Bearer ${testToken}`
  486. }
  487. });
  488. expect(response.status).toBe(200);
  489. if (response.status === 200) {
  490. const data = await response.json();
  491. expect(data?.id).toBe(testSalary.id);
  492. expect(data?.provinceId).toBe(testProvince.id);
  493. expect(data?.cityId).toBe(testCity.id);
  494. }
  495. });
  496. it('应该处理不存在的区域组合', async () => {
  497. const response = await client.byProvinceCity.$get({
  498. query: {
  499. provinceId: 999999,
  500. cityId: 999999
  501. }
  502. }, {
  503. headers: {
  504. 'Authorization': `Bearer ${testToken}`
  505. }
  506. });
  507. expect(response.status).toBe(404);
  508. });
  509. });
  510. describe('PUT /salary/update/:id', () => {
  511. let testSalary: SalaryLevel;
  512. beforeEach(async () => {
  513. // 创建测试薪资数据
  514. const dataSource = await IntegrationTestDatabase.getDataSource();
  515. const salaryRepository = dataSource.getRepository(SalaryLevel);
  516. testSalary = salaryRepository.create({
  517. provinceId: testProvince.id,
  518. cityId: testCity.id,
  519. basicSalary: 5000.00,
  520. allowance: 1000.00,
  521. insurance: 500.00,
  522. housingFund: 800.00,
  523. totalSalary: 7300.00,
  524. });
  525. await salaryRepository.save(testSalary);
  526. });
  527. it('应该成功更新薪资水平', async () => {
  528. const updateData = {
  529. basicSalary: 5500.00,
  530. allowance: 1200.00
  531. };
  532. const response = await client.update[':id'].$put({
  533. param: { id: testSalary.id.toString() },
  534. json: updateData
  535. }, {
  536. headers: {
  537. 'Authorization': `Bearer ${testToken}`
  538. }
  539. });
  540. expect(response.status).toBe(200);
  541. if (response.status === 200) {
  542. const data = await response.json();
  543. expect(data.id).toBe(testSalary.id);
  544. expect(data.basicSalary).toBe(5500.00);
  545. expect(data.allowance).toBe(1200.00);
  546. expect(data.totalSalary).toBe(8000.00); // 5500 + 1200 + 500 + 800
  547. }
  548. });
  549. it('应该验证更新后的区域数据', async () => {
  550. const updateData = {
  551. provinceId: 999999 // 不存在的区域ID
  552. };
  553. const response = await client.update[':id'].$put({
  554. param: { id: testSalary.id.toString() },
  555. json: updateData
  556. }, {
  557. headers: {
  558. 'Authorization': `Bearer ${testToken}`
  559. }
  560. });
  561. expect(response.status).toBe(400);
  562. });
  563. });
  564. describe('DELETE /salary/delete/:id', () => {
  565. let testSalary: SalaryLevel;
  566. beforeEach(async () => {
  567. // 创建测试薪资数据
  568. const dataSource = await IntegrationTestDatabase.getDataSource();
  569. const salaryRepository = dataSource.getRepository(SalaryLevel);
  570. testSalary = salaryRepository.create({
  571. provinceId: testProvince.id,
  572. cityId: testCity.id,
  573. basicSalary: 5000.00,
  574. allowance: 1000.00,
  575. insurance: 500.00,
  576. housingFund: 800.00,
  577. totalSalary: 7300.00,
  578. });
  579. await salaryRepository.save(testSalary);
  580. });
  581. it('应该成功删除薪资水平', async () => {
  582. const response = await client.delete[':id'].$delete({
  583. param: { id: testSalary.id.toString() }
  584. }, {
  585. headers: {
  586. 'Authorization': `Bearer ${testToken}`
  587. }
  588. });
  589. expect(response.status).toBe(200);
  590. if (response.status === 200) {
  591. const data = await response.json();
  592. expect(data).toEqual({ success: true });
  593. // 验证数据已删除
  594. const dataSource = await IntegrationTestDatabase.getDataSource();
  595. const salaryRepository = dataSource.getRepository(SalaryLevel);
  596. const deletedSalary = await salaryRepository.findOne({
  597. where: { id: testSalary.id }
  598. });
  599. expect(deletedSalary).toBeNull();
  600. }
  601. });
  602. it('应该处理不存在的薪资ID', async () => {
  603. const response = await client.delete[':id'].$delete({
  604. param: { id: 999999 }
  605. }, {
  606. headers: {
  607. 'Authorization': `Bearer ${testToken}`
  608. }
  609. });
  610. expect(response.status).toBe(404);
  611. });
  612. });
  613. describe('认证测试', () => {
  614. it('应该要求认证', async () => {
  615. const response = await client.list.$get({
  616. query: {}
  617. // 不提供Authorization header
  618. });
  619. expect(response.status).toBe(401);
  620. });
  621. it('应该验证无效token', async () => {
  622. const response = await client.list.$get({
  623. query: {}
  624. }, {
  625. headers: {
  626. 'Authorization': 'Bearer invalid_token'
  627. }
  628. });
  629. expect(response.status).toBe(401);
  630. });
  631. });
  632. });