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 { UserEntityMt, RoleMt } from '@d8d/user-module-mt'; import { FileMt } from '@d8d/file-module-mt'; import { SupplierMt } from '@d8d/supplier-module-mt'; import { MerchantMt } from '@d8d/merchant-module-mt'; import { publicGoodsRoutesMt } from '../../src/routes/index.mt'; import { GoodsMt, GoodsCategoryMt } from '../../src/entities/index.mt'; import { GoodsTestFactory } from '../factories/goods-test-factory'; // 设置集成测试钩子 setupIntegrationDatabaseHooksWithEntities([ UserEntityMt, RoleMt, GoodsMt, GoodsCategoryMt, FileMt, SupplierMt, MerchantMt ]) describe('公开商品API集成测试', () => { let client: ReturnType>; let testUser: UserEntityMt; let testCategory: GoodsCategoryMt; let testSupplier: SupplierMt; let testMerchant: MerchantMt; let testFactory: GoodsTestFactory; beforeEach(async () => { // 创建测试客户端 client = testClient(publicGoodsRoutesMt); // 获取数据源并创建测试工厂 const dataSource = await IntegrationTestDatabase.getDataSource(); testFactory = new GoodsTestFactory(dataSource); // 使用测试工厂创建测试数据 testUser = await testFactory.createTestUser(); testCategory = await testFactory.createTestCategory(testUser.id); testSupplier = await testFactory.createTestSupplier(testUser.id); testMerchant = await testFactory.createTestMerchant(testUser.id); // 创建测试商品 // 创建可用状态的商品 const activeGoods1 = await testFactory.createTestGoods(testUser.id, { name: '可用商品1', price: 100.00, costPrice: 80.00, categoryId1: testCategory.id, categoryId2: testCategory.id, categoryId3: testCategory.id, supplierId: testSupplier.id, merchantId: testMerchant.id, state: 1, stock: 100 }); const activeGoods2 = await testFactory.createTestGoods(testUser.id, { name: '可用商品2', price: 200.00, costPrice: 160.00, categoryId1: testCategory.id, categoryId2: testCategory.id, categoryId3: testCategory.id, supplierId: testSupplier.id, merchantId: testMerchant.id, state: 1, stock: 50 }); const activeGoods3 = await testFactory.createTestGoods(testUser.id, { name: '可用商品3', price: 300.00, costPrice: 240.00, categoryId1: testCategory.id, categoryId2: testCategory.id, categoryId3: testCategory.id, goodsType: 2, supplierId: testSupplier.id, merchantId: testMerchant.id, state: 1, stock: 30 }); // 创建不可用状态的商品(不应该被公开路由返回) const inactiveGoods = await testFactory.createTestGoods(testUser.id, { name: '不可用商品', price: 400.00, costPrice: 320.00, categoryId1: testCategory.id, categoryId2: testCategory.id, categoryId3: testCategory.id, supplierId: testSupplier.id, merchantId: testMerchant.id, state: 2, stock: 10 }); }); describe('GET /goods', () => { it('应该返回可用状态的商品列表', async () => { const response = await client.index.$get({ query: {} }); console.debug('公开商品列表响应状态:', response.status); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data).toHaveProperty('data'); expect(Array.isArray(data.data)).toBe(true); // 验证只返回可用状态的商品 data.data.forEach((goods: any) => { expect(goods.state).toBe(1); }); // 验证不包含不可用状态的商品 const inactiveGoodsInResponse = data.data.find((goods: any) => goods.state === 2); expect(inactiveGoodsInResponse).toBeUndefined(); } }); it('应该支持按名称搜索', async () => { const response = await client.index.$get({ query: { keyword: '可用商品1' } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); // 验证只返回匹配搜索的商品 data.data.forEach((goods: any) => { expect(goods.name).toContain('可用商品1'); expect(goods.state).toBe(1); }); } }); it('应该支持按分类过滤', async () => { const response = await client.index.$get({ query: { filters: JSON.stringify({ categoryId1: testCategory.id }) } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); // 验证只返回指定分类的商品 data.data.forEach((goods: any) => { expect(goods.categoryId1).toBe(testCategory.id); expect(goods.state).toBe(1); }); } }); it('应该支持按商品类型过滤', async () => { const response = await client.index.$get({ query: { filters: JSON.stringify({ goodsType: 2 }) } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); // 验证只返回指定类型的商品 data.data.forEach((goods: any) => { expect(goods.goodsType).toBe(2); expect(goods.state).toBe(1); }); } }); it('应该支持分页查询', async () => { const response = await client.index.$get({ query: { page: 1, pageSize: 2 } }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); expect(data.data.length).toBeLessThanOrEqual(2); // 验证只返回可用状态的商品 data.data.forEach((goods: any) => { expect(goods.state).toBe(1); }); } }); it('应该无需认证即可访问', async () => { const response = await client.index.$get({ query: {} }); expect(response.status).toBe(200); }); }); describe('GET /goods/:id', () => { it('应该返回指定商品的详情', async () => { // 先获取一个可用商品的ID const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(GoodsMt); const activeGoods = await goodsRepository.findOne({ where: { state: 1 } }); if (activeGoods) { const response = await client[':id'].$get({ param: { id: activeGoods.id } }); console.debug('公开商品详情响应状态:', response.status); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(data.id).toBe(activeGoods.id); expect(data.name).toBe(activeGoods.name); expect(data.state).toBe(1); // 确保是可用状态 } } }); it('应该拒绝访问不可用状态的商品', async () => { // 先获取一个不可用商品的ID const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(GoodsMt); const inactiveGoods = await goodsRepository.findOne({ where: { state: 2 } }); if (inactiveGoods) { const response = await client[':id'].$get({ param: { id: inactiveGoods.id } }); expect(response.status).toBe(404); // 不可用状态的商品应该返回404 } }); it('应该处理不存在的商品', async () => { const response = await client[':id'].$get({ param: { id: 999999 } }); expect(response.status).toBe(404); }); }); describe('POST /goods', () => { it('应该拒绝创建商品操作', async () => { const createData = { name: '尝试创建商品', price: 100.00, categoryId1: testCategory.id, state: 1 }; const response = await client.index.$post({ json: createData }); expect(response.status).toBe(404); // 只读模式下路由不存在 }); }); describe('PUT /goods/:id', () => { it('应该拒绝更新商品操作', async () => { // 先获取一个可用商品的ID const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(GoodsMt); const activeGoods = await goodsRepository.findOne({ where: { state: 1 } }); if (activeGoods) { const updateData = { name: '尝试更新商品' }; const response = await client[':id'].$put({ param: { id: activeGoods.id }, json: updateData }); expect(response.status).toBe(404); // 只读模式下路由不存在 } }); }); describe('DELETE /goods/:id', () => { it('应该拒绝删除商品操作', async () => { // 先获取一个可用商品的ID const dataSource = await IntegrationTestDatabase.getDataSource(); const goodsRepository = dataSource.getRepository(GoodsMt); const activeGoods = await goodsRepository.findOne({ where: { state: 1 } }); if (activeGoods) { const response = await client[':id'].$delete({ param: { id: activeGoods.id } }); expect(response.status).toBe(404); // 只读模式下路由不存在 } }); }); describe('公开路由权限验证测试', () => { it('应该验证公开路由无需认证', async () => { const response = await client.index.$get({ query: {} }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); // 验证只返回可用状态的商品 data.data.forEach((goods: any) => { expect(goods.state).toBe(1); }); } }); it('应该验证只支持查询操作', async () => { // 测试所有非查询操作都应该被拒绝 const createResponse = await client.index.$post({ json: { name: '测试' } }); expect(createResponse.status).toBe(404); const updateResponse = await client[':id'].$put({ param: { id: 1 }, json: { name: '测试' } }); expect(updateResponse.status).toBe(404); const deleteResponse = await client[':id'].$delete({ param: { id: 1 } }); expect(deleteResponse.status).toBe(404); }); }); describe('商品关联关系测试', () => { it('应该正确加载商品关联关系', async () => { const response = await client.index.$get({ query: {} }); expect(response.status).toBe(200); if (response.status === 200) { const data = await response.json(); expect(Array.isArray(data.data)).toBe(true); // 验证至少返回一个商品 if (data.data.length > 0) { const goods = data.data[0]; // 验证基础字段 expect(goods).toHaveProperty('id'); expect(goods).toHaveProperty('name'); expect(goods).toHaveProperty('price'); expect(goods).toHaveProperty('state', 1); // 验证关联关系字段存在 expect(goods).toHaveProperty('category1'); expect(goods).toHaveProperty('supplier'); expect(goods).toHaveProperty('merchant'); } } }); }); });