import { describe, it, expect, beforeEach } from 'vitest'; import { testClient } from 'hono/testing'; import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util'; import { JWTUtil } from '@d8d/shared-utils'; import { UserEntity, Role } from '@d8d/user-module'; import { DeliveryAddress } from '@d8d/delivery-address-module'; import { AreaEntity } from '@d8d/geo-areas'; import { Goods, GoodsCategory } from '@d8d/goods-module'; import { Supplier } from '@d8d/supplier-module'; import { File } from '@d8d/file-module'; import { Merchant } from '@d8d/merchant-module'; import createOrderRoutes from '../../src/routes/create-order'; import { Order, OrderGoods } from '../../src/entities'; // 设置集成测试钩子 setupIntegrationDatabaseHooksWithEntities([ UserEntity, Role, Order, OrderGoods, Goods, GoodsCategory, File, Supplier, DeliveryAddress, Merchant, AreaEntity ]) describe('订单创建API集成测试', () => { let client: ReturnType>; let userToken: string; let testUser: UserEntity; let testGoods: Goods; let testSupplier: Supplier; let testFile: File; let testDeliveryAddress: DeliveryAddress; beforeEach(async () => { // 创建测试客户端 client = testClient(createOrderRoutes); // 获取数据源 const dataSource = await IntegrationTestDatabase.getDataSource(); // 创建测试用户 const userRepository = dataSource.getRepository(UserEntity); testUser = userRepository.create({ username: `test_user_${Math.floor(Math.random() * 100000)}`, password: 'test_password', nickname: '测试用户', registrationSource: 'web' }); await userRepository.save(testUser); // 生成测试用户的token userToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, roles: [{name:'user'}] }); // 创建测试商品分类 const goodsCategoryRepository = dataSource.getRepository(GoodsCategory); const testCategory1 = goodsCategoryRepository.create({ name: '一级分类', level: 1, sort: 1, state: 1, createdBy: testUser.id }); await goodsCategoryRepository.save(testCategory1); const testCategory2 = goodsCategoryRepository.create({ name: '二级分类', level: 2, sort: 1, state: 1, createdBy: testUser.id }); await goodsCategoryRepository.save(testCategory2); const testCategory3 = goodsCategoryRepository.create({ name: '三级分类', level: 3, sort: 1, state: 1, createdBy: testUser.id }); await goodsCategoryRepository.save(testCategory3); // 创建测试供应商 const supplierRepository = dataSource.getRepository(Supplier); testSupplier = supplierRepository.create({ name: '测试供应商', username: `test_supplier_${Math.floor(Math.random() * 100000)}`, password: 'password123', phone: '13800138000', realname: '测试供应商', state: 1, createdBy: testUser.id }); await supplierRepository.save(testSupplier); // 创建测试商户 const merchantRepository = dataSource.getRepository(Merchant); const testMerchant = merchantRepository.create({ name: '测试商户', username: `test_merchant_${Math.floor(Math.random() * 100000)}`, password: 'password123', phone: '13800138000', realname: '测试商户', state: 1, createdBy: testUser.id }); await merchantRepository.save(testMerchant); // 创建测试商品 const goodsRepository = dataSource.getRepository(Goods); testGoods = goodsRepository.create({ name: '测试商品', price: 100.00, costPrice: 80.00, categoryId1: testCategory1.id, categoryId2: testCategory2.id, categoryId3: testCategory3.id, goodsType: 1, supplierId: testSupplier.id, merchantId: testMerchant.id, state: 1, stock: 100, lowestBuy: 1, createdBy: testUser.id }); await goodsRepository.save(testGoods); // 创建测试文件 const fileRepository = dataSource.getRepository(File); testFile = fileRepository.create({ name: 'test_image.jpg', type: 'image/jpeg', size: 102400, path: 'images/test_image.jpg', uploadUserId: testUser.id, uploadTime: new Date(), createdAt: new Date(), updatedAt: new Date() }); await fileRepository.save(testFile); // 创建测试地区数据 const areaRepository = dataSource.getRepository(AreaEntity); const testProvince = areaRepository.create({ name: '广东省', level: 1, code: '440000', isDisabled: 0, isDeleted: 0, createdBy: testUser.id }); await areaRepository.save(testProvince); const testCity = areaRepository.create({ name: '深圳市', level: 2, code: '440300', parentId: testProvince.id, isDisabled: 0, isDeleted: 0, createdBy: testUser.id }); await areaRepository.save(testCity); const testDistrict = areaRepository.create({ name: '南山区', level: 3, code: '440305', parentId: testCity.id, isDisabled: 0, isDeleted: 0, createdBy: testUser.id }); await areaRepository.save(testDistrict); const testTown = areaRepository.create({ name: '粤海街道', level: 4, code: '440305001', parentId: testDistrict.id, isDisabled: 0, isDeleted: 0, createdBy: testUser.id }); await areaRepository.save(testTown); // 创建测试配送地址 const deliveryAddressRepository = dataSource.getRepository(DeliveryAddress); testDeliveryAddress = deliveryAddressRepository.create({ userId: testUser.id, name: '收货人姓名', phone: '13800138000', receiverProvince: testProvince.id, receiverCity: testCity.id, receiverDistrict: testDistrict.id, receiverTown: testTown.id, address: '测试地址', isDefault: 1, state: 1, createdBy: testUser.id }); await deliveryAddressRepository.save(testDeliveryAddress); }); describe('POST /create-order', () => { it('应该成功创建订单并关联商品', async () => { const createData = { addressId: testDeliveryAddress.id, productOwn: '自营', consumeFrom: '积分兑换', products: [ { id: testGoods.id, num: 2 }, { id: testGoods.id, num: 1 } ] }; const response = await client.index.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); console.debug('订单创建响应状态:', response.status); if (response.status !== 201) { const errorData = await response.json(); console.debug('订单创建错误响应:', errorData); } expect(response.status).toBe(201); if (response.status === 201) { const data = await response.json(); expect(data).toHaveProperty('orderId'); expect(data).toHaveProperty('orderNo'); expect(data).toHaveProperty('amount'); expect(data).toHaveProperty('payAmount'); // 验证订单商品被正确创建(需要从数据库查询验证) const dataSource = await IntegrationTestDatabase.getDataSource(); const orderGoodsRepository = dataSource.getRepository(OrderGoods); const createdOrderGoods = await orderGoodsRepository.find({ where: { orderId: data.orderId } }); expect(createdOrderGoods).toBeDefined(); expect(Array.isArray(createdOrderGoods)).toBe(true); expect(createdOrderGoods.length).toBe(2); // 验证商品信息 createdOrderGoods.forEach((orderGoods: any, index: number) => { expect(orderGoods.goodsName).toBe(testGoods.name); expect(orderGoods.price).toBe(testGoods.price); expect(orderGoods.num).toBe(createData.products[index].num); expect(orderGoods.createdBy).toBe(testUser.id); // 验证商品创建用户 }); } }); it('应该验证创建订单的必填字段', async () => { const invalidData = { // 缺少必填字段 amount: -1, orderType: -1 }; const response = await client.index.$post({ json: invalidData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); expect(response.status).toBe(400); }); it('应该处理商品库存不足的情况', async () => { // 创建一个库存为0的商品 const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(Goods); const outOfStockGoods = goodsRepository.create({ name: '库存不足商品', price: 100.00, costPrice: 80.00, categoryId1: 1, categoryId2: 1, categoryId3: 1, goodsType: 1, supplierId: 1, state: 1, stock: 0, // 库存为0 lowestBuy: 1, createdBy: testUser.id }); await goodsRepository.save(outOfStockGoods); const createData = { orderNo: `ORDER_${Math.floor(Math.random() * 100000)}`, amount: 100.00, costAmount: 80.00, payAmount: 100.00, orderType: 1, payType: 1, payState: 0, state: 0, deliveryAddressId: testDeliveryAddress.id, merchantId: 1, supplierId: testSupplier.id, orderGoods: [ { goodsId: outOfStockGoods.id, goodsName: '库存不足商品', price: 100.00, num: 1, state: 0, supplierId: testSupplier.id, imageFileId: testFile.id } ] }; const response = await client.index.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); // 应该返回错误状态(库存不足) expect(response.status).toBe(400); }); it('应该拒绝未认证用户的访问', async () => { const createData = { orderNo: `ORDER_${Math.floor(Math.random() * 100000)}`, amount: 150.00, costAmount: 120.00, payAmount: 150.00, orderType: 1, payType: 1, payState: 0, state: 0, deliveryAddressId: testDeliveryAddress.id, merchantId: 1, supplierId: testSupplier.id, orderGoods: [ { goodsId: testGoods.id, goodsName: '测试商品', price: 50.00, num: 3, state: 0, supplierId: testSupplier.id, imageFileId: testFile.id } ] }; const response = await client.index.$post({ json: createData }); expect(response.status).toBe(401); }); }); describe('事务性测试', () => { it('应该确保订单和商品创建的事务一致性', async () => { const createData = { addressId: testDeliveryAddress.id, productOwn: '自营', consumeFrom: '积分兑换', products: [ { id: testGoods.id, num: 2 } ] }; const response = await client.index.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); expect(response.status).toBe(201); if (response.status === 201) { const data = await response.json(); // 验证订单和商品都被正确创建 const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(Order); const orderGoodsRepository = dataSource.getRepository(OrderGoods); // 验证订单存在 const createdOrder = await orderRepository.findOne({ where: { id: data.orderId } }); expect(createdOrder).toBeDefined(); expect(createdOrder?.orderNo).toBe(data.orderNo); expect(createdOrder?.userId).toBe(testUser.id); // 验证订单商品存在 const createdOrderGoods = await orderGoodsRepository.find({ where: { orderId: data.orderId } }); expect(createdOrderGoods.length).toBe(1); expect(createdOrderGoods[0].goodsName).toBe(testGoods.name); expect(createdOrderGoods[0].num).toBe(createData.products[0].num); } }); it('应该验证库存更新功能', async () => { const initialStock = testGoods.stock; const purchaseQuantity = 2; const createData = { addressId: testDeliveryAddress.id, productOwn: '自营', consumeFrom: '积分兑换', products: [ { id: testGoods.id, num: purchaseQuantity } ] }; const response = await client.index.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); expect(response.status).toBe(201); if (response.status === 201) { // 验证商品库存被正确更新 const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(Goods); const updatedGoods = await goodsRepository.findOne({ where: { id: testGoods.id } }); expect(updatedGoods).toBeDefined(); expect(Number(updatedGoods?.stock)).toBe(initialStock - purchaseQuantity); } }); }); describe('数据权限测试', () => { it('应该自动设置当前用户权限', async () => { const createData = { addressId: testDeliveryAddress.id, productOwn: '自营', consumeFrom: '积分兑换', products: [ { id: testGoods.id, num: 1 } ] }; const response = await client.index.$post({ json: createData }, { headers: { 'Authorization': `Bearer ${userToken}` } }); expect(response.status).toBe(201); if (response.status === 201) { const data = await response.json(); // 验证订单和商品都设置了正确的用户权限(需要从数据库查询验证) const dataSource = await IntegrationTestDatabase.getDataSource(); const orderRepository = dataSource.getRepository(Order); const orderGoodsRepository = dataSource.getRepository(OrderGoods); // 验证订单权限 const createdOrder = await orderRepository.findOne({ where: { id: data.orderId } }); expect(createdOrder?.userId).toBe(testUser.id); expect(createdOrder?.createdBy).toBe(testUser.id); // 验证订单商品权限 const createdOrderGoods = await orderGoodsRepository.find({ where: { orderId: data.orderId } }); createdOrderGoods.forEach((orderGoods: any) => { expect(orderGoods.createdBy).toBe(testUser.id); }); } }); }); });