company.integration.test.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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. });
  373. describe('GET /company/searchCompanies', () => {
  374. it('应该按名称搜索公司', async () => {
  375. // 创建测试公司
  376. const dataSource = await IntegrationTestDatabase.getDataSource();
  377. const companyRepository = dataSource.getRepository(Company);
  378. const company = companyRepository.create({
  379. platformId: testPlatform.id,
  380. companyName: '科技公司搜索测试',
  381. contactPerson: '张三',
  382. contactPhone: '13800138000',
  383. status: 1
  384. });
  385. await companyRepository.save(company);
  386. const response = await client.searchCompanies.$get({
  387. query: { name: '科技', skip: 0, take: 10 }
  388. }, {
  389. headers: {
  390. 'Authorization': `Bearer ${testToken}`
  391. }
  392. });
  393. console.debug('搜索公司响应状态:', response.status);
  394. expect(response.status).toBe(200);
  395. if (response.status === 200) {
  396. const data = await response.json();
  397. expect(data.data.length).toBeGreaterThan(0);
  398. expect(data.data[0].companyName).toContain('科技');
  399. }
  400. });
  401. });
  402. describe('GET /company/getCompaniesByPlatform/:platformId', () => {
  403. it('应该按平台ID查询公司', async () => {
  404. // 创建测试公司
  405. const dataSource = await IntegrationTestDatabase.getDataSource();
  406. const companyRepository = dataSource.getRepository(Company);
  407. const company = companyRepository.create({
  408. platformId: testPlatform.id,
  409. companyName: '平台关联测试公司',
  410. contactPerson: '张三',
  411. contactPhone: '13800138000',
  412. status: 1
  413. });
  414. await companyRepository.save(company);
  415. const response = await client.getCompaniesByPlatform[':platformId'].$get({
  416. param: { platformId: testPlatform.id }
  417. }, {
  418. headers: {
  419. 'Authorization': `Bearer ${testToken}`
  420. }
  421. });
  422. console.debug('按平台查询公司响应状态:', response.status);
  423. expect(response.status).toBe(200);
  424. if (response.status === 200) {
  425. const data = await response.json();
  426. expect(Array.isArray(data)).toBe(true);
  427. expect(data.length).toBeGreaterThan(0);
  428. expect(data[0].platformId).toBe(testPlatform.id);
  429. }
  430. });
  431. it('应该处理不存在的平台ID', async () => {
  432. const response = await client.getCompaniesByPlatform[':platformId'].$get({
  433. param: { platformId: 999999 }
  434. }, {
  435. headers: {
  436. 'Authorization': `Bearer ${testToken}`
  437. }
  438. });
  439. expect(response.status).toBe(200);
  440. if (response.status === 200) {
  441. const data = await response.json();
  442. expect(Array.isArray(data)).toBe(true);
  443. expect(data.length).toBe(0);
  444. }
  445. });
  446. });
  447. describe('GET /company/getCompany/:id', () => {
  448. it('应该返回指定公司的详情(包含平台关联信息)', async () => {
  449. // 先创建一个公司
  450. const dataSource = await IntegrationTestDatabase.getDataSource();
  451. const companyRepository = dataSource.getRepository(Company);
  452. const testCompany = companyRepository.create({
  453. platformId: testPlatform.id,
  454. companyName: `详情测试公司_${Date.now()}`,
  455. contactPerson: '张三',
  456. contactPhone: '13800138000',
  457. status: 1
  458. });
  459. await companyRepository.save(testCompany);
  460. const response = await client.getCompany[':id'].$get({
  461. param: { id: testCompany.id }
  462. }, {
  463. headers: {
  464. 'Authorization': `Bearer ${testToken}`
  465. }
  466. });
  467. console.debug('公司详情响应状态:', response.status);
  468. expect(response.status).toBe(200);
  469. if (response.status === 200) {
  470. const data = await response.json();
  471. expect(data!.id).toBe(testCompany.id);
  472. expect(data!.companyName).toBe(testCompany.companyName);
  473. expect(data!.platformId).toBe(testPlatform.id);
  474. // 验证包含平台关联信息
  475. expect(data!).toHaveProperty('platform');
  476. }
  477. });
  478. it('应该处理不存在的公司', async () => {
  479. const response = await client.getCompany[':id'].$get({
  480. param: { id: 999999 }
  481. }, {
  482. headers: {
  483. 'Authorization': `Bearer ${testToken}`
  484. }
  485. });
  486. expect(response.status).toBe(200);
  487. const data = await response.json();
  488. expect(data).toBeNull();
  489. });
  490. });
  491. });