platform.integration.test.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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 platformRoutes from '../../src/routes/platform.routes';
  8. import { Platform } from '../../src/entities/platform.entity';
  9. // 设置集成测试钩子
  10. setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, Platform])
  11. describe('平台管理API集成测试', () => {
  12. let client: ReturnType<typeof testClient<typeof platformRoutes>>;
  13. let testToken: string;
  14. let testUser: UserEntity;
  15. beforeEach(async () => {
  16. // 创建测试客户端
  17. client = testClient(platformRoutes);
  18. // 获取数据源
  19. const dataSource = await IntegrationTestDatabase.getDataSource();
  20. // 创建测试用户
  21. const userRepository = dataSource.getRepository(UserEntity);
  22. testUser = userRepository.create({
  23. username: `test_user_${Date.now()}`,
  24. password: 'test_password',
  25. nickname: '测试用户',
  26. registrationSource: 'web'
  27. });
  28. await userRepository.save(testUser);
  29. // 生成测试用户的token
  30. testToken = JWTUtil.generateToken({
  31. id: testUser.id,
  32. username: testUser.username,
  33. roles: [{name:'user'}]
  34. });
  35. });
  36. describe('POST /platform/createPlatform', () => {
  37. it('应该成功创建平台', async () => {
  38. const createData = {
  39. platformName: '微信平台',
  40. contactPerson: '张三',
  41. contactPhone: '13800138000',
  42. contactEmail: 'zhangsan@example.com'
  43. };
  44. const response = await client.createPlatform.$post({
  45. json: createData
  46. }, {
  47. headers: {
  48. 'Authorization': `Bearer ${testToken}`
  49. }
  50. });
  51. console.debug('创建平台响应状态:', response.status);
  52. expect(response.status).toBe(200);
  53. if (response.status === 200) {
  54. const data = await response.json();
  55. expect(data.platformName).toBe(createData.platformName);
  56. expect(data.contactPerson).toBe(createData.contactPerson);
  57. expect(data.contactPhone).toBe(createData.contactPhone);
  58. }
  59. });
  60. it('应该验证平台名称重复', async () => {
  61. // 先创建一个平台
  62. const dataSource = await IntegrationTestDatabase.getDataSource();
  63. const platformRepository = dataSource.getRepository(Platform);
  64. const existingPlatform = platformRepository.create({
  65. platformName: '微信平台',
  66. contactPerson: '张三',
  67. contactPhone: '13800138000',
  68. status: 1
  69. });
  70. await platformRepository.save(existingPlatform);
  71. // 尝试创建同名平台
  72. const createData = {
  73. platformName: '微信平台', // 重复的名称
  74. contactPerson: '李四',
  75. contactPhone: '13900139000'
  76. };
  77. const response = await client.createPlatform.$post({
  78. json: createData
  79. }, {
  80. headers: {
  81. 'Authorization': `Bearer ${testToken}`
  82. }
  83. });
  84. expect(response.status).toBe(400);
  85. });
  86. it('应该验证必填字段', async () => {
  87. const createData = {
  88. platformName: '', // 空字符串,应该验证失败
  89. contactPerson: '张三',
  90. contactPhone: '13800138000'
  91. };
  92. const response = await client.createPlatform.$post({
  93. json: createData
  94. }, {
  95. headers: {
  96. 'Authorization': `Bearer ${testToken}`
  97. }
  98. });
  99. expect(response.status).toBe(400);
  100. });
  101. });
  102. describe('POST /platform/deletePlatform', () => {
  103. it('应该成功删除平台(软删除)', async () => {
  104. // 先创建一个平台
  105. const dataSource = await IntegrationTestDatabase.getDataSource();
  106. const platformRepository = dataSource.getRepository(Platform);
  107. const platform = platformRepository.create({
  108. platformName: '测试删除平台',
  109. contactPerson: '张三',
  110. contactPhone: '13800138000',
  111. status: 1
  112. });
  113. await platformRepository.save(platform);
  114. const deleteData = {
  115. id: platform.id
  116. };
  117. const response = await client.deletePlatform.$post({
  118. json: deleteData
  119. }, {
  120. headers: {
  121. 'Authorization': `Bearer ${testToken}`
  122. }
  123. });
  124. expect(response.status).toBe(200);
  125. if (response.status === 200) {
  126. const data = await response.json();
  127. expect(data.success).toBe(true);
  128. // 验证平台状态已改为0(软删除)
  129. const deletedPlatform = await platformRepository.findOne({ where: { id: platform.id } });
  130. expect(deletedPlatform?.status).toBe(0);
  131. }
  132. });
  133. it('应该处理不存在的平台ID', async () => {
  134. const deleteData = {
  135. id: 99999 // 不存在的ID
  136. };
  137. const response = await client.deletePlatform.$post({
  138. json: deleteData
  139. }, {
  140. headers: {
  141. 'Authorization': `Bearer ${testToken}`
  142. }
  143. });
  144. expect(response.status).toBe(200); // 删除不存在的平台也返回成功(软删除逻辑)
  145. });
  146. });
  147. describe('POST /platform/updatePlatform', () => {
  148. it('应该成功更新平台', async () => {
  149. // 先创建一个平台
  150. const dataSource = await IntegrationTestDatabase.getDataSource();
  151. const platformRepository = dataSource.getRepository(Platform);
  152. const platform = platformRepository.create({
  153. platformName: '原始平台名称',
  154. contactPerson: '张三',
  155. contactPhone: '13800138000',
  156. status: 1
  157. });
  158. await platformRepository.save(platform);
  159. const updateData = {
  160. id: platform.id,
  161. platformName: '更新后的平台名称',
  162. contactPerson: '李四',
  163. contactPhone: '13900139000'
  164. };
  165. const response = await client.updatePlatform.$post({
  166. json: updateData
  167. }, {
  168. headers: {
  169. 'Authorization': `Bearer ${testToken}`
  170. }
  171. });
  172. expect(response.status).toBe(200);
  173. if (response.status === 200) {
  174. const data = await response.json();
  175. expect(data.platformName).toBe(updateData.platformName);
  176. expect(data.contactPerson).toBe(updateData.contactPerson);
  177. }
  178. });
  179. it('应该验证平台名称重复(更新时)', async () => {
  180. // 创建两个平台
  181. const dataSource = await IntegrationTestDatabase.getDataSource();
  182. const platformRepository = dataSource.getRepository(Platform);
  183. const platform1 = platformRepository.create({
  184. platformName: '平台A',
  185. contactPerson: '张三',
  186. contactPhone: '13800138000',
  187. status: 1
  188. });
  189. await platformRepository.save(platform1);
  190. const platform2 = platformRepository.create({
  191. platformName: '平台B',
  192. contactPerson: '李四',
  193. contactPhone: '13900139000',
  194. status: 1
  195. });
  196. await platformRepository.save(platform2);
  197. // 尝试将平台2的名称改为平台1的名称
  198. const updateData = {
  199. id: platform2.id,
  200. platformName: '平台A' // 重复的名称
  201. };
  202. const response = await client.updatePlatform.$post({
  203. json: updateData
  204. }, {
  205. headers: {
  206. 'Authorization': `Bearer ${testToken}`
  207. }
  208. });
  209. expect(response.status).toBe(400);
  210. });
  211. it('应该处理不存在的平台', async () => {
  212. const updateData = {
  213. id: 99999, // 不存在的ID
  214. platformName: '新名称'
  215. };
  216. const response = await client.updatePlatform.$post({
  217. json: updateData
  218. }, {
  219. headers: {
  220. 'Authorization': `Bearer ${testToken}`
  221. }
  222. });
  223. expect(response.status).toBe(404);
  224. });
  225. });
  226. describe('GET /platform/getAllPlatforms', () => {
  227. it('应该成功获取平台列表(分页)', async () => {
  228. // 创建一些测试数据
  229. const dataSource = await IntegrationTestDatabase.getDataSource();
  230. const platformRepository = dataSource.getRepository(Platform);
  231. for (let i = 1; i <= 5; i++) {
  232. const platform = platformRepository.create({
  233. platformName: `平台${i}`,
  234. contactPerson: `联系人${i}`,
  235. contactPhone: `1380013800${i}`,
  236. status: 1
  237. });
  238. await platformRepository.save(platform);
  239. }
  240. const response = await client.getAllPlatforms.$get({
  241. query: {
  242. skip: 0,
  243. take: 10
  244. }
  245. }, {
  246. headers: {
  247. 'Authorization': `Bearer ${testToken}`
  248. }
  249. });
  250. expect(response.status).toBe(200);
  251. if (response.status === 200) {
  252. const data = await response.json();
  253. expect(data.data).toHaveLength(5);
  254. expect(data.total).toBe(5);
  255. expect(data.data[0].platformName).toBe('平台5'); // 按ID降序排列
  256. }
  257. });
  258. it('应该处理分页参数', async () => {
  259. // 创建更多测试数据
  260. const dataSource = await IntegrationTestDatabase.getDataSource();
  261. const platformRepository = dataSource.getRepository(Platform);
  262. for (let i = 1; i <= 15; i++) {
  263. const platform = platformRepository.create({
  264. platformName: `分页平台${i}`,
  265. contactPerson: `联系人${i}`,
  266. contactPhone: `1380013800${i}`,
  267. status: 1
  268. });
  269. await platformRepository.save(platform);
  270. }
  271. const response = await client.getAllPlatforms.$get({
  272. query: {
  273. skip: 5,
  274. take: 5
  275. }
  276. }, {
  277. headers: {
  278. 'Authorization': `Bearer ${testToken}`
  279. }
  280. });
  281. expect(response.status).toBe(200);
  282. if (response.status === 200) {
  283. const data = await response.json();
  284. expect(data.data).toHaveLength(5);
  285. expect(data.total).toBe(15);
  286. }
  287. });
  288. it('应该过滤已删除的平台(status=0)', async () => {
  289. // 创建测试数据:3个正常平台,2个已删除平台
  290. const dataSource = await IntegrationTestDatabase.getDataSource();
  291. const platformRepository = dataSource.getRepository(Platform);
  292. // 创建3个正常平台
  293. for (let i = 1; i <= 3; i++) {
  294. const platform = platformRepository.create({
  295. platformName: `正常平台${i}`,
  296. contactPerson: `联系人${i}`,
  297. contactPhone: `1380013800${i}`,
  298. status: 1
  299. });
  300. await platformRepository.save(platform);
  301. }
  302. // 创建2个已删除平台
  303. for (let i = 4; i <= 5; i++) {
  304. const platform = platformRepository.create({
  305. platformName: `已删除平台${i}`,
  306. contactPerson: `联系人${i}`,
  307. contactPhone: `1380013800${i}`,
  308. status: 0
  309. });
  310. await platformRepository.save(platform);
  311. }
  312. const response = await client.getAllPlatforms.$get({
  313. query: {
  314. skip: 0,
  315. take: 10
  316. }
  317. }, {
  318. headers: {
  319. 'Authorization': `Bearer ${testToken}`
  320. }
  321. });
  322. expect(response.status).toBe(200);
  323. if (response.status === 200) {
  324. const data = await response.json();
  325. // 应该只返回3个正常平台,不返回已删除的平台
  326. expect(data.data).toHaveLength(3);
  327. expect(data.total).toBe(3);
  328. // 验证返回的都是正常平台
  329. data.data.forEach((platform: any) => {
  330. expect(platform.status).toBe(1);
  331. expect(platform.platformName).toMatch(/^正常平台/);
  332. });
  333. }
  334. });
  335. });
  336. describe('GET /platform/searchPlatforms', () => {
  337. it('应该成功按名称搜索平台', async () => {
  338. // 创建测试数据
  339. const dataSource = await IntegrationTestDatabase.getDataSource();
  340. const platformRepository = dataSource.getRepository(Platform);
  341. const platform1 = platformRepository.create({
  342. platformName: '微信平台',
  343. contactPerson: '张三',
  344. contactPhone: '13800138000',
  345. status: 1
  346. });
  347. await platformRepository.save(platform1);
  348. const platform2 = platformRepository.create({
  349. platformName: '支付宝平台',
  350. contactPerson: '李四',
  351. contactPhone: '13900139000',
  352. status: 1
  353. });
  354. await platformRepository.save(platform2);
  355. const response = await client.searchPlatforms.$get({
  356. query: {
  357. name: '微信',
  358. skip: 0,
  359. take: 10
  360. }
  361. }, {
  362. headers: {
  363. 'Authorization': `Bearer ${testToken}`
  364. }
  365. });
  366. expect(response.status).toBe(200);
  367. if (response.status === 200) {
  368. const data = await response.json();
  369. expect(data.data).toHaveLength(1);
  370. expect(data.data[0].platformName).toBe('微信平台');
  371. }
  372. });
  373. it('应该验证搜索关键词不能为空', async () => {
  374. const response = await client.searchPlatforms.$get({
  375. query: {
  376. name: '', // 空关键词
  377. skip: 0,
  378. take: 10
  379. }
  380. }, {
  381. headers: {
  382. 'Authorization': `Bearer ${testToken}`
  383. }
  384. });
  385. expect(response.status).toBe(400);
  386. });
  387. it('应该过滤已删除的平台(搜索时)', async () => {
  388. // 创建测试数据
  389. const dataSource = await IntegrationTestDatabase.getDataSource();
  390. const platformRepository = dataSource.getRepository(Platform);
  391. // 创建正常平台
  392. const normalPlatform = platformRepository.create({
  393. platformName: '测试搜索平台正常',
  394. contactPerson: '张三',
  395. contactPhone: '13800138000',
  396. status: 1
  397. });
  398. await platformRepository.save(normalPlatform);
  399. // 创建已删除的平台(不同名称)
  400. const deletedPlatform = platformRepository.create({
  401. platformName: '测试搜索平台已删除',
  402. contactPerson: '李四',
  403. contactPhone: '13900139000',
  404. status: 0
  405. });
  406. await platformRepository.save(deletedPlatform);
  407. const response = await client.searchPlatforms.$get({
  408. query: {
  409. name: '测试搜索',
  410. skip: 0,
  411. take: 10
  412. }
  413. }, {
  414. headers: {
  415. 'Authorization': `Bearer ${testToken}`
  416. }
  417. });
  418. expect(response.status).toBe(200);
  419. if (response.status === 200) {
  420. const data = await response.json();
  421. // 应该只返回1个正常平台,不返回已删除的平台
  422. expect(data.data).toHaveLength(1);
  423. expect(data.total).toBe(1);
  424. expect(data.data[0].platformName).toBe('测试搜索平台正常');
  425. expect(data.data[0].status).toBe(1);
  426. expect(data.data[0].contactPerson).toBe('张三'); // 正常平台的联系人
  427. }
  428. });
  429. });
  430. describe('GET /platform/getPlatform/{id}', () => {
  431. it('应该成功获取单个平台详情', async () => {
  432. // 先创建一个平台
  433. const dataSource = await IntegrationTestDatabase.getDataSource();
  434. const platformRepository = dataSource.getRepository(Platform);
  435. const platform = platformRepository.create({
  436. platformName: '测试平台详情',
  437. contactPerson: '张三',
  438. contactPhone: '13800138000',
  439. contactEmail: 'zhangsan@example.com',
  440. status: 1
  441. });
  442. await platformRepository.save(platform);
  443. const response = await client.getPlatform[':id'].$get({
  444. param: {
  445. id: platform.id
  446. }
  447. }, {
  448. headers: {
  449. 'Authorization': `Bearer ${testToken}`
  450. }
  451. });
  452. expect(response.status).toBe(200);
  453. if (response.status === 200) {
  454. const data = await response.json();
  455. expect(data?.platformName).toBe('测试平台详情');
  456. expect(data?.contactEmail).toBe('zhangsan@example.com');
  457. }
  458. });
  459. it('应该处理不存在的平台ID', async () => {
  460. const response = await client.getPlatform[':id'].$get({
  461. param: {
  462. id: 99999 // 不存在的ID
  463. }
  464. }, {
  465. headers: {
  466. 'Authorization': `Bearer ${testToken}`
  467. }
  468. });
  469. expect(response.status).toBe(200); // 返回200,但数据为null
  470. if (response.status === 200) {
  471. const data = await response.json();
  472. expect(data).toBeNull();
  473. }
  474. });
  475. });
  476. describe('认证测试', () => {
  477. it('应该验证所有端点需要认证', async () => {
  478. // 测试没有token的情况
  479. const response = await client.createPlatform.$post({
  480. json: {
  481. platformName: '测试平台'
  482. }
  483. });
  484. expect(response.status).toBe(401);
  485. });
  486. it('应该验证无效token', async () => {
  487. const response = await client.createPlatform.$post({
  488. json: {
  489. platformName: '测试平台'
  490. }
  491. }, {
  492. headers: {
  493. 'Authorization': 'Bearer invalid_token'
  494. }
  495. });
  496. expect(response.status).toBe(401);
  497. });
  498. });
  499. });