company.integration.test.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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 { Platform } from '@d8d/allin-platform-module/entities';
  8. import companyRoutes from '../../src/routes/company.routes';
  9. import { Company } from '../../src/entities/company.entity';
  10. // 设置集成测试钩子 - 需要包含Platform实体
  11. setupIntegrationDatabaseHooksWithEntities([UserEntity, File, Role, Platform, Company])
  12. describe('公司管理API集成测试', () => {
  13. let client: ReturnType<typeof testClient<typeof companyRoutes>>;
  14. let testToken: string;
  15. let testUser: UserEntity;
  16. let testPlatform: Platform;
  17. beforeEach(async () => {
  18. // 创建测试客户端
  19. client = testClient(companyRoutes);
  20. // 获取数据源
  21. const dataSource = await IntegrationTestDatabase.getDataSource();
  22. // 创建测试用户
  23. const userRepository = dataSource.getRepository(UserEntity);
  24. testUser = userRepository.create({
  25. username: `test_user_${Date.now()}`,
  26. password: 'test_password',
  27. nickname: '测试用户',
  28. registrationSource: 'web'
  29. });
  30. await userRepository.save(testUser);
  31. // 生成测试用户的token
  32. testToken = JWTUtil.generateToken({
  33. id: testUser.id,
  34. username: testUser.username,
  35. roles: [{name:'user'}]
  36. });
  37. // 创建测试平台
  38. const platformRepository = dataSource.getRepository(Platform);
  39. testPlatform = platformRepository.create({
  40. platformName: `测试平台_${Date.now()}`,
  41. contactPerson: '平台管理员',
  42. contactPhone: '13800138000',
  43. contactEmail: 'admin@example.com',
  44. status: 1
  45. });
  46. await platformRepository.save(testPlatform);
  47. });
  48. describe('POST /company/createCompany', () => {
  49. it('应该成功创建公司', async () => {
  50. const createData = {
  51. platformId: testPlatform.id,
  52. companyName: '示例科技有限公司',
  53. contactPerson: '张三',
  54. contactPhone: '13800138000',
  55. contactEmail: 'zhangsan@example.com',
  56. address: '北京市朝阳区'
  57. };
  58. const response = await client.createCompany.$post({
  59. json: createData
  60. }, {
  61. headers: {
  62. 'Authorization': `Bearer ${testToken}`
  63. }
  64. });
  65. console.debug('创建公司响应状态:', response.status);
  66. expect(response.status).toBe(200);
  67. if (response.status === 200) {
  68. const data = await response.json();
  69. expect(data.success).toBe(true);
  70. }
  71. });
  72. it('应该验证公司名称在同一平台下重复', async () => {
  73. // 先创建一个公司
  74. const dataSource = await IntegrationTestDatabase.getDataSource();
  75. const companyRepository = dataSource.getRepository(Company);
  76. const existingCompany = companyRepository.create({
  77. platformId: testPlatform.id,
  78. companyName: '示例科技有限公司',
  79. contactPerson: '张三',
  80. contactPhone: '13800138000',
  81. status: 1
  82. });
  83. await companyRepository.save(existingCompany);
  84. // 尝试创建同名公司(同一平台下)
  85. const createData = {
  86. platformId: testPlatform.id,
  87. companyName: '示例科技有限公司', // 重复的名称
  88. contactPerson: '李四',
  89. contactPhone: '13900139000'
  90. };
  91. const response = await client.createCompany.$post({
  92. json: createData
  93. }, {
  94. headers: {
  95. 'Authorization': `Bearer ${testToken}`
  96. }
  97. });
  98. expect(response.status).toBe(400);
  99. if (response.status === 400) {
  100. const data = await response.json();
  101. expect(data.message).toContain('公司名称在该平台下已存在');
  102. }
  103. });
  104. it('应该允许不同平台下的相同公司名称', async () => {
  105. // 创建第二个平台
  106. const dataSource = await IntegrationTestDatabase.getDataSource();
  107. const platformRepository = dataSource.getRepository(Platform);
  108. const secondPlatform = platformRepository.create({
  109. platformName: `第二测试平台_${Date.now()}`,
  110. contactPerson: '第二平台管理员',
  111. contactPhone: '13900139000',
  112. contactEmail: 'admin2@example.com',
  113. status: 1
  114. });
  115. await platformRepository.save(secondPlatform);
  116. // 在第一个平台下创建公司
  117. const companyRepository = dataSource.getRepository(Company);
  118. const existingCompany = companyRepository.create({
  119. platformId: testPlatform.id,
  120. companyName: '示例科技有限公司',
  121. contactPerson: '张三',
  122. contactPhone: '13800138000',
  123. status: 1
  124. });
  125. await companyRepository.save(existingCompany);
  126. // 在第二个平台下创建同名公司(应该允许)
  127. const createData = {
  128. platformId: secondPlatform.id,
  129. companyName: '示例科技有限公司', // 相同名称,不同平台
  130. contactPerson: '李四',
  131. contactPhone: '13900139000'
  132. };
  133. const response = await client.createCompany.$post({
  134. json: createData
  135. }, {
  136. headers: {
  137. 'Authorization': `Bearer ${testToken}`
  138. }
  139. });
  140. expect(response.status).toBe(200);
  141. if (response.status === 200) {
  142. const data = await response.json();
  143. expect(data.success).toBe(true);
  144. }
  145. });
  146. it('应该拒绝未认证用户的访问', async () => {
  147. const createData = {
  148. platformId: testPlatform.id,
  149. companyName: '测试公司',
  150. contactPerson: '张三',
  151. contactPhone: '13800138000'
  152. };
  153. const response = await client.createCompany.$post({
  154. json: createData
  155. });
  156. expect(response.status).toBe(401);
  157. });
  158. });
  159. describe('POST /company/deleteCompany', () => {
  160. it('应该成功删除公司(软删除)', async () => {
  161. // 先创建一个公司
  162. const dataSource = await IntegrationTestDatabase.getDataSource();
  163. const companyRepository = dataSource.getRepository(Company);
  164. const testCompany = companyRepository.create({
  165. platformId: testPlatform.id,
  166. companyName: `待删除公司_${Date.now()}`,
  167. contactPerson: '张三',
  168. contactPhone: '13800138000',
  169. status: 1
  170. });
  171. await companyRepository.save(testCompany);
  172. const deleteData = {
  173. id: testCompany.id
  174. };
  175. const response = await client.deleteCompany.$post({
  176. json: deleteData
  177. }, {
  178. headers: {
  179. 'Authorization': `Bearer ${testToken}`
  180. }
  181. });
  182. console.debug('删除公司响应状态:', response.status);
  183. expect(response.status).toBe(200);
  184. if (response.status === 200) {
  185. const data = await response.json();
  186. expect(data.success).toBe(true);
  187. }
  188. // 验证公司状态变为0(软删除)
  189. const deletedCompany = await companyRepository.findOne({
  190. where: { id: testCompany.id }
  191. });
  192. expect(deletedCompany?.status).toBe(0);
  193. });
  194. });
  195. describe('POST /company/updateCompany', () => {
  196. it('应该成功更新公司', async () => {
  197. // 先创建一个公司
  198. const dataSource = await IntegrationTestDatabase.getDataSource();
  199. const companyRepository = dataSource.getRepository(Company);
  200. const testCompany = companyRepository.create({
  201. platformId: testPlatform.id,
  202. companyName: `原始公司_${Date.now()}`,
  203. contactPerson: '张三',
  204. contactPhone: '13800138000',
  205. status: 1
  206. });
  207. await companyRepository.save(testCompany);
  208. const updateData = {
  209. id: testCompany.id,
  210. companyName: '更新后的公司名称',
  211. contactPerson: '李四',
  212. contactPhone: '13900139000'
  213. };
  214. const response = await client.updateCompany.$post({
  215. json: updateData
  216. }, {
  217. headers: {
  218. 'Authorization': `Bearer ${testToken}`
  219. }
  220. });
  221. console.debug('更新公司响应状态:', response.status);
  222. if (response.status !== 200) {
  223. const errorData = await response.json();
  224. console.debug('更新公司错误:', errorData);
  225. }
  226. expect(response.status).toBe(200);
  227. if (response.status === 200) {
  228. const data = await response.json();
  229. expect(data.success).toBe(true);
  230. }
  231. // 验证公司已更新
  232. const updatedCompany = await companyRepository.findOne({
  233. where: { id: testCompany.id }
  234. });
  235. expect(updatedCompany?.companyName).toBe(updateData.companyName);
  236. expect(updatedCompany?.contactPerson).toBe(updateData.contactPerson);
  237. });
  238. it('应该验证更新时的公司名称在同一平台下重复', async () => {
  239. // 创建两个公司
  240. const dataSource = await IntegrationTestDatabase.getDataSource();
  241. const companyRepository = dataSource.getRepository(Company);
  242. const company1 = companyRepository.create({
  243. platformId: testPlatform.id,
  244. companyName: '公司A',
  245. contactPerson: '张三',
  246. contactPhone: '13800138000',
  247. status: 1
  248. });
  249. await companyRepository.save(company1);
  250. const company2 = companyRepository.create({
  251. platformId: testPlatform.id,
  252. companyName: '公司B',
  253. contactPerson: '李四',
  254. contactPhone: '13900139000',
  255. status: 1
  256. });
  257. await companyRepository.save(company2);
  258. // 尝试将公司B的名称改为公司A的名称(同一平台下)
  259. const updateData = {
  260. id: company2.id,
  261. companyName: '公司A' // 重复的名称
  262. };
  263. const response = await client.updateCompany.$post({
  264. json: updateData
  265. }, {
  266. headers: {
  267. 'Authorization': `Bearer ${testToken}`
  268. }
  269. });
  270. expect(response.status).toBe(400);
  271. if (response.status === 400) {
  272. const data = await response.json();
  273. expect(data.message).toContain('公司名称在该平台下已存在');
  274. }
  275. });
  276. it('应该允许更新到不同平台下的相同名称', async () => {
  277. // 创建第二个平台
  278. const dataSource = await IntegrationTestDatabase.getDataSource();
  279. const platformRepository = dataSource.getRepository(Platform);
  280. const secondPlatform = platformRepository.create({
  281. platformName: `第二测试平台_${Date.now()}`,
  282. contactPerson: '第二平台管理员',
  283. contactPhone: '13900139000',
  284. contactEmail: 'admin2@example.com',
  285. status: 1
  286. });
  287. await platformRepository.save(secondPlatform);
  288. // 创建两个公司,分别在不同平台下
  289. const companyRepository = dataSource.getRepository(Company);
  290. const company1 = companyRepository.create({
  291. platformId: testPlatform.id,
  292. companyName: '公司A',
  293. contactPerson: '张三',
  294. contactPhone: '13800138000',
  295. status: 1
  296. });
  297. await companyRepository.save(company1);
  298. const company2 = companyRepository.create({
  299. platformId: secondPlatform.id,
  300. companyName: '公司B',
  301. contactPerson: '李四',
  302. contactPhone: '13900139000',
  303. status: 1
  304. });
  305. await companyRepository.save(company2);
  306. // 将公司B的名称改为公司A的名称,但保持平台为第二个平台(应该允许,因为不同平台下可以有相同名称)
  307. const updateData = {
  308. id: company2.id,
  309. companyName: '公司A',
  310. platformId: secondPlatform.id // 保持第二个平台
  311. };
  312. const response = await client.updateCompany.$post({
  313. json: updateData
  314. }, {
  315. headers: {
  316. 'Authorization': `Bearer ${testToken}`
  317. }
  318. });
  319. expect(response.status).toBe(200);
  320. if (response.status === 200) {
  321. const data = await response.json();
  322. expect(data.success).toBe(true);
  323. }
  324. });
  325. });
  326. describe('GET /company/getAllCompanies', () => {
  327. it('应该返回公司列表(包含平台关联信息)', async () => {
  328. // 创建一些测试公司
  329. const dataSource = await IntegrationTestDatabase.getDataSource();
  330. const companyRepository = dataSource.getRepository(Company);
  331. for (let i = 0; i < 3; i++) {
  332. const company = companyRepository.create({
  333. platformId: testPlatform.id,
  334. companyName: `测试公司${i}`,
  335. contactPerson: `联系人${i}`,
  336. contactPhone: `1380013800${i}`,
  337. status: 1
  338. });
  339. await companyRepository.save(company);
  340. }
  341. const response = await client.getAllCompanies.$get({
  342. query: { skip: 0, take: 10 }
  343. }, {
  344. headers: {
  345. 'Authorization': `Bearer ${testToken}`
  346. }
  347. });
  348. console.debug('公司列表响应状态:', response.status);
  349. expect(response.status).toBe(200);
  350. if (response.status === 200) {
  351. const data = await response.json();
  352. expect(data).toHaveProperty('data');
  353. expect(data).toHaveProperty('total');
  354. expect(Array.isArray(data.data)).toBe(true);
  355. expect(data.total).toBeGreaterThanOrEqual(3);
  356. // 验证返回的数据包含平台关联信息
  357. if (data.data.length > 0) {
  358. expect(data.data[0]).toHaveProperty('platform');
  359. }
  360. }
  361. });
  362. it('应该支持分页参数', async () => {
  363. const response = await client.getAllCompanies.$get({
  364. query: { skip: 0, take: 5 }
  365. }, {
  366. headers: {
  367. 'Authorization': `Bearer ${testToken}`
  368. }
  369. });
  370. expect(response.status).toBe(200);
  371. });
  372. it('应该过滤已删除的公司(status=0)', async () => {
  373. // 创建测试数据:3个正常公司,2个已删除公司
  374. const dataSource = await IntegrationTestDatabase.getDataSource();
  375. const companyRepository = dataSource.getRepository(Company);
  376. // 创建3个正常公司
  377. for (let i = 1; i <= 3; i++) {
  378. const company = companyRepository.create({
  379. platformId: testPlatform.id,
  380. companyName: `正常公司${i}`,
  381. contactPerson: `联系人${i}`,
  382. contactPhone: `1380013800${i}`,
  383. status: 1
  384. });
  385. await companyRepository.save(company);
  386. }
  387. // 创建2个已删除公司
  388. for (let i = 4; i <= 5; i++) {
  389. const company = companyRepository.create({
  390. platformId: testPlatform.id,
  391. companyName: `已删除公司${i}`,
  392. contactPerson: `联系人${i}`,
  393. contactPhone: `1380013800${i}`,
  394. status: 0
  395. });
  396. await companyRepository.save(company);
  397. }
  398. const response = await client.getAllCompanies.$get({
  399. query: { skip: 0, take: 10 }
  400. }, {
  401. headers: {
  402. 'Authorization': `Bearer ${testToken}`
  403. }
  404. });
  405. expect(response.status).toBe(200);
  406. if (response.status === 200) {
  407. const data = await response.json();
  408. // 应该只返回3个正常公司,不返回已删除的公司
  409. expect(data.data).toHaveLength(3);
  410. expect(data.total).toBe(3);
  411. // 验证返回的都是正常公司
  412. data.data.forEach((company: any) => {
  413. expect(company.status).toBe(1);
  414. expect(company.companyName).toMatch(/^正常公司/);
  415. });
  416. }
  417. });
  418. });
  419. describe('GET /company/searchCompanies', () => {
  420. it('应该按名称搜索公司', async () => {
  421. // 创建测试公司
  422. const dataSource = await IntegrationTestDatabase.getDataSource();
  423. const companyRepository = dataSource.getRepository(Company);
  424. const company = companyRepository.create({
  425. platformId: testPlatform.id,
  426. companyName: '科技公司搜索测试',
  427. contactPerson: '张三',
  428. contactPhone: '13800138000',
  429. status: 1
  430. });
  431. await companyRepository.save(company);
  432. const response = await client.searchCompanies.$get({
  433. query: { name: '科技', skip: 0, take: 10 }
  434. }, {
  435. headers: {
  436. 'Authorization': `Bearer ${testToken}`
  437. }
  438. });
  439. console.debug('搜索公司响应状态:', response.status);
  440. expect(response.status).toBe(200);
  441. if (response.status === 200) {
  442. const data = await response.json();
  443. expect(data.data.length).toBeGreaterThan(0);
  444. expect(data.data[0].companyName).toContain('科技');
  445. }
  446. });
  447. it('应该过滤已删除的公司(搜索时)', async () => {
  448. // 创建测试数据
  449. const dataSource = await IntegrationTestDatabase.getDataSource();
  450. const companyRepository = dataSource.getRepository(Company);
  451. // 创建正常公司
  452. const normalCompany = companyRepository.create({
  453. platformId: testPlatform.id,
  454. companyName: '测试搜索公司正常',
  455. contactPerson: '张三',
  456. contactPhone: '13800138000',
  457. status: 1
  458. });
  459. await companyRepository.save(normalCompany);
  460. // 创建已删除的公司(不同名称)
  461. const deletedCompany = companyRepository.create({
  462. platformId: testPlatform.id,
  463. companyName: '测试搜索公司已删除',
  464. contactPerson: '李四',
  465. contactPhone: '13900139000',
  466. status: 0
  467. });
  468. await companyRepository.save(deletedCompany);
  469. const response = await client.searchCompanies.$get({
  470. query: { name: '测试搜索', skip: 0, take: 10 }
  471. }, {
  472. headers: {
  473. 'Authorization': `Bearer ${testToken}`
  474. }
  475. });
  476. expect(response.status).toBe(200);
  477. if (response.status === 200) {
  478. const data = await response.json();
  479. // 应该只返回1个正常公司,不返回已删除的公司
  480. expect(data.data).toHaveLength(1);
  481. expect(data.total).toBe(1);
  482. expect(data.data[0].companyName).toBe('测试搜索公司正常');
  483. expect(data.data[0].status).toBe(1);
  484. expect(data.data[0].contactPerson).toBe('张三'); // 正常公司的联系人
  485. }
  486. });
  487. });
  488. describe('GET /company/getCompaniesByPlatform/:platformId', () => {
  489. it('应该按平台ID查询公司', async () => {
  490. // 创建测试公司
  491. const dataSource = await IntegrationTestDatabase.getDataSource();
  492. const companyRepository = dataSource.getRepository(Company);
  493. const company = companyRepository.create({
  494. platformId: testPlatform.id,
  495. companyName: '平台关联测试公司',
  496. contactPerson: '张三',
  497. contactPhone: '13800138000',
  498. status: 1
  499. });
  500. await companyRepository.save(company);
  501. const response = await client.getCompaniesByPlatform[':platformId'].$get({
  502. param: { platformId: testPlatform.id }
  503. }, {
  504. headers: {
  505. 'Authorization': `Bearer ${testToken}`
  506. }
  507. });
  508. console.debug('按平台查询公司响应状态:', response.status);
  509. expect(response.status).toBe(200);
  510. if (response.status === 200) {
  511. const data = await response.json();
  512. expect(Array.isArray(data)).toBe(true);
  513. expect(data.length).toBeGreaterThan(0);
  514. expect(data[0].platformId).toBe(testPlatform.id);
  515. }
  516. });
  517. it('应该处理不存在的平台ID', async () => {
  518. const response = await client.getCompaniesByPlatform[':platformId'].$get({
  519. param: { platformId: 999999 }
  520. }, {
  521. headers: {
  522. 'Authorization': `Bearer ${testToken}`
  523. }
  524. });
  525. expect(response.status).toBe(200);
  526. if (response.status === 200) {
  527. const data = await response.json();
  528. expect(Array.isArray(data)).toBe(true);
  529. expect(data.length).toBe(0);
  530. }
  531. });
  532. });
  533. describe('GET /company/getCompany/:id', () => {
  534. it('应该返回指定公司的详情(包含平台关联信息)', async () => {
  535. // 先创建一个公司
  536. const dataSource = await IntegrationTestDatabase.getDataSource();
  537. const companyRepository = dataSource.getRepository(Company);
  538. const testCompany = companyRepository.create({
  539. platformId: testPlatform.id,
  540. companyName: `详情测试公司_${Date.now()}`,
  541. contactPerson: '张三',
  542. contactPhone: '13800138000',
  543. status: 1
  544. });
  545. await companyRepository.save(testCompany);
  546. const response = await client.getCompany[':id'].$get({
  547. param: { id: testCompany.id }
  548. }, {
  549. headers: {
  550. 'Authorization': `Bearer ${testToken}`
  551. }
  552. });
  553. console.debug('公司详情响应状态:', response.status);
  554. expect(response.status).toBe(200);
  555. if (response.status === 200) {
  556. const data = await response.json();
  557. expect(data!.id).toBe(testCompany.id);
  558. expect(data!.companyName).toBe(testCompany.companyName);
  559. expect(data!.platformId).toBe(testPlatform.id);
  560. // 验证包含平台关联信息
  561. expect(data!).toHaveProperty('platform');
  562. }
  563. });
  564. it('应该处理不存在的公司', async () => {
  565. const response = await client.getCompany[':id'].$get({
  566. param: { id: 999999 }
  567. }, {
  568. headers: {
  569. 'Authorization': `Bearer ${testToken}`
  570. }
  571. });
  572. expect(response.status).toBe(200);
  573. const data = await response.json();
  574. expect(data).toBeNull();
  575. });
  576. });
  577. });