admin-goods-categories.integration.test.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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 { UserEntityMt, RoleMt } from '@d8d/user-module-mt';
  6. import { FileMt } from '@d8d/file-module-mt';
  7. import { adminGoodsCategoriesRoutesMt } from '../../src/routes/admin-goods-categories.mt';
  8. import { GoodsCategoryMt } from '../../src/entities/index.mt';
  9. import { GoodsTestFactory } from '../factories/goods-test-factory';
  10. // 设置集成测试钩子
  11. setupIntegrationDatabaseHooksWithEntities([UserEntityMt, RoleMt, GoodsCategoryMt, FileMt])
  12. describe('管理员商品分类管理API集成测试', () => {
  13. let client: ReturnType<typeof testClient<typeof adminGoodsCategoriesRoutesMt>>;
  14. let adminToken: string;
  15. let testUser: UserEntityMt;
  16. let testAdmin: UserEntityMt;
  17. let testFactory: GoodsTestFactory;
  18. beforeEach(async () => {
  19. // 创建测试客户端
  20. client = testClient(adminGoodsCategoriesRoutesMt);
  21. // 获取数据源并创建测试工厂
  22. const dataSource = await IntegrationTestDatabase.getDataSource();
  23. testFactory = new GoodsTestFactory(dataSource);
  24. // 使用测试工厂创建测试数据
  25. testUser = await testFactory.createTestUser();
  26. testAdmin = await testFactory.createTestAdmin();
  27. // 生成测试管理员的token
  28. adminToken = JWTUtil.generateToken({
  29. id: testAdmin.id,
  30. username: testAdmin.username,
  31. roles: [{name:'admin'}]
  32. });
  33. });
  34. describe('GET /goods-categories', () => {
  35. it('应该返回商品分类列表', async () => {
  36. const response = await client.index.$get({
  37. query: {}
  38. }, {
  39. headers: {
  40. 'Authorization': `Bearer ${adminToken}`
  41. }
  42. });
  43. console.debug('商品分类列表响应状态:', response.status);
  44. expect(response.status).toBe(200);
  45. if (response.status === 200) {
  46. const data = await response.json();
  47. expect(data).toHaveProperty('data');
  48. expect(Array.isArray(data.data)).toBe(true);
  49. }
  50. });
  51. it('应该拒绝未认证用户的访问', async () => {
  52. const response = await client.index.$get({
  53. query: {}
  54. });
  55. expect(response.status).toBe(401);
  56. });
  57. });
  58. describe('POST /goods-categories', () => {
  59. it('应该成功创建商品分类', async () => {
  60. const createData = {
  61. name: '管理员创建商品分类',
  62. parentId: 0,
  63. level: 1,
  64. state: 1
  65. };
  66. const response = await client.index.$post({
  67. json: createData
  68. }, {
  69. headers: {
  70. 'Authorization': `Bearer ${adminToken}`
  71. }
  72. });
  73. console.debug('创建商品分类响应状态:', response.status);
  74. if (response.status !== 201) {
  75. const errorData = await response.json();
  76. console.debug('创建商品分类错误响应:', errorData);
  77. }
  78. expect(response.status).toBe(201);
  79. if (response.status === 201) {
  80. const data = await response.json();
  81. expect(data).toHaveProperty('id');
  82. expect(data.name).toBe(createData.name);
  83. expect(data.parentId).toBe(createData.parentId);
  84. expect(data.level).toBe(createData.level);
  85. expect(data.state).toBe(createData.state);
  86. }
  87. });
  88. it('应该验证创建商品分类的必填字段', async () => {
  89. const invalidData = {
  90. // 缺少必填字段
  91. name: '',
  92. parentId: -1,
  93. level: -1
  94. };
  95. const response = await client.index.$post({
  96. json: invalidData
  97. }, {
  98. headers: {
  99. 'Authorization': `Bearer ${adminToken}`
  100. }
  101. });
  102. expect(response.status).toBe(400);
  103. });
  104. });
  105. describe('GET /goods-categories/:id', () => {
  106. it('应该返回指定商品分类的详情', async () => {
  107. // 使用测试工厂创建一个商品分类
  108. const testCategory = await testFactory.createTestCategory(testUser.id, {
  109. name: '测试商品分类详情'
  110. });
  111. const response = await client[':id'].$get({
  112. param: { id: testCategory.id }
  113. }, {
  114. headers: {
  115. 'Authorization': `Bearer ${adminToken}`
  116. }
  117. });
  118. console.debug('商品分类详情响应状态:', response.status);
  119. expect(response.status).toBe(200);
  120. if (response.status === 200) {
  121. const data = await response.json();
  122. expect(data.id).toBe(testCategory.id);
  123. expect(data.name).toBe(testCategory.name);
  124. expect(data.parentId).toBe(testCategory.parentId);
  125. expect(data.level).toBe(testCategory.level);
  126. expect(data.state).toBe(testCategory.state);
  127. }
  128. });
  129. it('应该处理不存在的商品分类', async () => {
  130. const response = await client[':id'].$get({
  131. param: { id: 999999 }
  132. }, {
  133. headers: {
  134. 'Authorization': `Bearer ${adminToken}`
  135. }
  136. });
  137. expect(response.status).toBe(404);
  138. });
  139. });
  140. describe('PUT /goods-categories/:id', () => {
  141. it('应该成功更新商品分类', async () => {
  142. // 使用测试工厂创建一个商品分类
  143. const testCategory = await testFactory.createTestCategory(testUser.id, {
  144. name: '测试更新商品分类'
  145. });
  146. const updateData = {
  147. name: '更新后的商品分类名称',
  148. state: 2
  149. };
  150. const response = await client[':id'].$put({
  151. param: { id: testCategory.id },
  152. json: updateData
  153. }, {
  154. headers: {
  155. 'Authorization': `Bearer ${adminToken}`
  156. }
  157. });
  158. console.debug('更新商品分类响应状态:', response.status);
  159. expect(response.status).toBe(200);
  160. if (response.status === 200) {
  161. const data = await response.json();
  162. expect(data.name).toBe(updateData.name);
  163. expect(data.state).toBe(updateData.state);
  164. }
  165. });
  166. });
  167. describe('DELETE /goods-categories/:id', () => {
  168. it('应该成功删除商品分类', async () => {
  169. // 先创建一个商品分类
  170. const dataSource = await IntegrationTestDatabase.getDataSource();
  171. const categoryRepository = dataSource.getRepository(GoodsCategoryMt);
  172. const testCategory = categoryRepository.create({
  173. tenantId: 1,
  174. name: '测试删除商品分类',
  175. parentId: 0,
  176. level: 1,
  177. state: 1,
  178. createdBy: testUser.id
  179. });
  180. await categoryRepository.save(testCategory);
  181. const response = await client[':id'].$delete({
  182. param: { id: testCategory.id }
  183. }, {
  184. headers: {
  185. 'Authorization': `Bearer ${adminToken}`
  186. }
  187. });
  188. console.debug('删除商品分类响应状态:', response.status);
  189. expect(response.status).toBe(204);
  190. });
  191. });
  192. describe('商品分类树形结构测试', () => {
  193. it('应该支持多级分类结构', async () => {
  194. // 创建一级分类
  195. const level1Category = await testFactory.createTestCategory(testUser.id, {
  196. name: '一级分类',
  197. parentId: 0,
  198. level: 1
  199. });
  200. // 创建二级分类
  201. const level2Category = await testFactory.createTestCategory(testUser.id, {
  202. name: '二级分类',
  203. parentId: level1Category.id,
  204. level: 2
  205. });
  206. // 创建三级分类
  207. const level3Category = await testFactory.createTestCategory(testUser.id, {
  208. name: '三级分类',
  209. parentId: level2Category.id,
  210. level: 3
  211. });
  212. // 验证分类层级关系
  213. const response = await client.index.$get({
  214. query: {}
  215. }, {
  216. headers: {
  217. 'Authorization': `Bearer ${adminToken}`
  218. }
  219. });
  220. expect(response.status).toBe(200);
  221. const data = await response.json();
  222. // 类型检查确保data属性存在
  223. if ('data' in data && Array.isArray(data.data)) {
  224. // 验证分类数量
  225. expect(data.data.length).toBeGreaterThanOrEqual(3);
  226. } else {
  227. // 如果响应是错误格式,应该失败
  228. expect(data).toHaveProperty('data');
  229. }
  230. });
  231. });
  232. describe('商品分类状态管理测试', () => {
  233. it('应该正确处理分类状态变更', async () => {
  234. // 创建可用状态的分类
  235. const activeCategory = await testFactory.createTestCategory(testUser.id, {
  236. name: '可用分类',
  237. parentId: 0,
  238. level: 1,
  239. state: 1
  240. });
  241. // 创建不可用状态的分类
  242. const inactiveCategory = await testFactory.createTestCategory(testUser.id, {
  243. name: '不可用分类',
  244. parentId: 0,
  245. level: 1,
  246. state: 2
  247. });
  248. // 验证状态过滤
  249. const response = await client.index.$get({
  250. query: { filters: JSON.stringify({ state: 1 }) }
  251. }, {
  252. headers: {
  253. 'Authorization': `Bearer ${adminToken}`
  254. }
  255. });
  256. expect(response.status).toBe(200);
  257. const data = await response.json();
  258. // 类型检查确保data属性存在
  259. if ('data' in data && Array.isArray(data.data)) {
  260. // 应该只返回可用状态的分类
  261. const activeCategories = data.data.filter((category: any) => category.state === 1);
  262. expect(activeCategories.length).toBeGreaterThan(0);
  263. const inactiveCategories = data.data.filter((category: any) => category.state === 2);
  264. expect(inactiveCategories.length).toBe(0);
  265. } else {
  266. // 如果响应是错误格式,应该失败
  267. expect(data).toHaveProperty('data');
  268. }
  269. });
  270. });
  271. });