|
|
@@ -17,16 +17,16 @@ setupIntegrationDatabaseHooksWithEntities([
|
|
|
|
|
|
describe('管理员父子商品管理API集成测试', () => {
|
|
|
let client: ReturnType<typeof testClient<typeof adminGoodsRoutesMt>>;
|
|
|
+ let adminToken: string;
|
|
|
let testUser: UserEntityMt;
|
|
|
+ let testAdmin: UserEntityMt;
|
|
|
let testCategory: GoodsCategoryMt;
|
|
|
let testSupplier: SupplierMt;
|
|
|
let testMerchant: MerchantMt;
|
|
|
let testFactory: GoodsTestFactory;
|
|
|
- let authToken: string;
|
|
|
let parentGoods: GoodsMt;
|
|
|
let childGoods1: GoodsMt;
|
|
|
let childGoods2: GoodsMt;
|
|
|
- let normalGoods: GoodsMt;
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
// 创建测试客户端
|
|
|
@@ -38,16 +38,16 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
|
|
|
// 使用测试工厂创建测试数据
|
|
|
testUser = await testFactory.createTestUser();
|
|
|
+ testAdmin = await testFactory.createTestAdmin();
|
|
|
testCategory = await testFactory.createTestCategory(testUser.id);
|
|
|
testSupplier = await testFactory.createTestSupplier(testUser.id);
|
|
|
testMerchant = await testFactory.createTestMerchant(testUser.id);
|
|
|
|
|
|
- // 生成认证token
|
|
|
- authToken = JWTUtil.generateToken({
|
|
|
- id: testUser.id,
|
|
|
- username: testUser.username,
|
|
|
- tenantId: testUser.tenantId,
|
|
|
- roles: ['admin']
|
|
|
+ // 生成测试管理员的token
|
|
|
+ adminToken = JWTUtil.generateToken({
|
|
|
+ id: testAdmin.id,
|
|
|
+ username: testAdmin.username,
|
|
|
+ roles: [{name:'admin'}]
|
|
|
});
|
|
|
|
|
|
// 创建父商品
|
|
|
@@ -60,8 +60,8 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
categoryId3: testCategory.id,
|
|
|
supplierId: testSupplier.id,
|
|
|
merchantId: testMerchant.id,
|
|
|
- state: 1,
|
|
|
- spuId: 0,
|
|
|
+ stock: 100,
|
|
|
+ spuId: 0, // 父商品
|
|
|
spuName: null
|
|
|
});
|
|
|
|
|
|
@@ -75,9 +75,9 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
categoryId3: testCategory.id,
|
|
|
supplierId: testSupplier.id,
|
|
|
merchantId: testMerchant.id,
|
|
|
- state: 1,
|
|
|
- spuId: parentGoods.id,
|
|
|
- spuName: '父商品测试'
|
|
|
+ stock: 50,
|
|
|
+ spuId: parentGoods.id, // 父商品ID
|
|
|
+ spuName: parentGoods.name
|
|
|
});
|
|
|
|
|
|
// 创建子商品2
|
|
|
@@ -90,114 +90,118 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
categoryId3: testCategory.id,
|
|
|
supplierId: testSupplier.id,
|
|
|
merchantId: testMerchant.id,
|
|
|
- state: 1,
|
|
|
- spuId: parentGoods.id,
|
|
|
- spuName: '父商品测试'
|
|
|
- });
|
|
|
-
|
|
|
- // 创建普通商品(非父子商品)
|
|
|
- normalGoods = await testFactory.createTestGoods(testUser.id, {
|
|
|
- name: '普通商品',
|
|
|
- price: 100.00,
|
|
|
- costPrice: 80.00,
|
|
|
- categoryId1: testCategory.id,
|
|
|
- categoryId2: testCategory.id,
|
|
|
- categoryId3: testCategory.id,
|
|
|
- supplierId: testSupplier.id,
|
|
|
- merchantId: testMerchant.id,
|
|
|
- state: 1,
|
|
|
- spuId: 0,
|
|
|
- spuName: null
|
|
|
+ stock: 60,
|
|
|
+ spuId: parentGoods.id, // 父商品ID
|
|
|
+ spuName: parentGoods.name
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- describe('GET /api/v1/goods/:id/children', () => {
|
|
|
+ describe('GET /goods/:id/children', () => {
|
|
|
it('应该成功获取父商品的子商品列表', async () => {
|
|
|
- const response = await client['{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: parentGoods.id },
|
|
|
query: { page: 1, pageSize: 10 }
|
|
|
}, {
|
|
|
headers: {
|
|
|
- 'Authorization': `Bearer ${authToken}`
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- console.debug('响应状态码:', response.status);
|
|
|
- const data = await response.json();
|
|
|
- console.debug('响应数据:', data);
|
|
|
expect(response.status).toBe(200);
|
|
|
- expect(data.data).toHaveLength(2);
|
|
|
- expect(data.total).toBe(2);
|
|
|
- expect(data.page).toBe(1);
|
|
|
- expect(data.pageSize).toBe(10);
|
|
|
- expect(data.totalPages).toBe(1);
|
|
|
-
|
|
|
- // 验证子商品数据
|
|
|
- const childIds = data.data.map((item: any) => item.id);
|
|
|
- expect(childIds).toContain(childGoods1.id);
|
|
|
- expect(childIds).toContain(childGoods2.id);
|
|
|
-
|
|
|
- // 验证子商品包含正确的关联关系
|
|
|
- const firstChild = data.data[0];
|
|
|
- expect(firstChild).toHaveProperty('category1');
|
|
|
- expect(firstChild).toHaveProperty('supplier');
|
|
|
- expect(firstChild).toHaveProperty('merchant');
|
|
|
- expect(firstChild.spuId).toBe(parentGoods.id);
|
|
|
- expect(firstChild.spuName).toBe('父商品测试');
|
|
|
+ if (response.status === 200 ){
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ expect(data.data).toHaveLength(2);
|
|
|
+ expect(data.total).toBe(2);
|
|
|
+ expect(data.page).toBe(1);
|
|
|
+ expect(data.pageSize).toBe(10);
|
|
|
+ expect(data.totalPages).toBe(1);
|
|
|
+
|
|
|
+ // 验证子商品数据
|
|
|
+ const childIds = data.data.map((item) => item.id);
|
|
|
+ expect(childIds).toContain(childGoods1.id);
|
|
|
+ expect(childIds).toContain(childGoods2.id);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
it('应该验证父商品是否存在', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: 99999 }, // 不存在的商品ID
|
|
|
- query: { page: 1, pageSize: 10 },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ query: { page: 1, pageSize: 10 }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(404);
|
|
|
- const data = await response.json();
|
|
|
- expect(data.code).toBe(404);
|
|
|
- expect(data.message).toContain('父商品不存在');
|
|
|
+ if (response.status === 404) {
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.code).toBe(404);
|
|
|
+ expect(data.message).toContain('父商品不存在');
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
it('应该支持搜索关键词过滤', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: parentGoods.id },
|
|
|
- query: { page: 1, pageSize: 10, keyword: '红色' },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ query: { page: 1, pageSize: 10, keyword: '红色' }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
- const data = await response.json();
|
|
|
- expect(data.data).toHaveLength(1);
|
|
|
- expect(data.data[0].name).toBe('子商品1 - 红色');
|
|
|
+ if (response.status === 200) {
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.data).toHaveLength(1);
|
|
|
+ expect(data.data[0].name).toBe('子商品1 - 红色');
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
it('应该支持排序', async () => {
|
|
|
- // 修改子商品的排序字段
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const goodsRepo = dataSource.getRepository(GoodsMt);
|
|
|
-
|
|
|
- await goodsRepo.update(childGoods1.id, { sort: 2 });
|
|
|
- await goodsRepo.update(childGoods2.id, { sort: 1 });
|
|
|
-
|
|
|
- const response = await client['api/v1/goods/{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: parentGoods.id },
|
|
|
- query: { page: 1, pageSize: 10, sortBy: 'sort', sortOrder: 'ASC' },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ query: { page: 1, pageSize: 10, sortBy: 'price', sortOrder: 'DESC' }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
const data = await response.json();
|
|
|
- expect(data.data[0].id).toBe(childGoods2.id); // sort=1 应该在前
|
|
|
- expect(data.data[1].id).toBe(childGoods1.id); // sort=2 应该在后
|
|
|
+ expect(data.data).toHaveLength(2);
|
|
|
+ // 价格降序排列:220 > 210
|
|
|
+ expect(data.data[0].price).toBe(220.00);
|
|
|
+ expect(data.data[1].price).toBe(210.00);
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- describe('POST /api/v1/goods/:id/set-as-parent', () => {
|
|
|
+ describe('POST /goods/:id/set-as-parent', () => {
|
|
|
it('应该成功将普通商品设为父商品', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/set-as-parent'].$post({
|
|
|
- param: { id: normalGoods.id },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ // 创建一个普通商品(不是子商品)
|
|
|
+ const normalGoods = await testFactory.createTestGoods(testUser.id, {
|
|
|
+ name: '普通商品',
|
|
|
+ price: 300.00,
|
|
|
+ costPrice: 250.00,
|
|
|
+ categoryId1: testCategory.id,
|
|
|
+ categoryId2: testCategory.id,
|
|
|
+ categoryId3: testCategory.id,
|
|
|
+ supplierId: testSupplier.id,
|
|
|
+ merchantId: testMerchant.id,
|
|
|
+ stock: 80,
|
|
|
+ spuId: 0,
|
|
|
+ spuName: null
|
|
|
+ });
|
|
|
+
|
|
|
+ const response = await client[':id']['set-as-parent'].$post({
|
|
|
+ param: { id: normalGoods.id }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
@@ -205,20 +209,15 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
expect(data.id).toBe(normalGoods.id);
|
|
|
expect(data.spuId).toBe(0);
|
|
|
expect(data.spuName).toBeNull();
|
|
|
-
|
|
|
- // 验证数据库中的更新
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const updatedGoods = await dataSource.getRepository(GoodsMt).findOne({
|
|
|
- where: { id: normalGoods.id } as any
|
|
|
- });
|
|
|
- expect(updatedGoods?.spuId).toBe(0);
|
|
|
- expect(updatedGoods?.spuName).toBeNull();
|
|
|
});
|
|
|
|
|
|
it('应该拒绝将子商品设为父商品', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/set-as-parent'].$post({
|
|
|
- param: { id: childGoods1.id },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ const response = await client[':id']['set-as-parent'].$post({
|
|
|
+ param: { id: childGoods1.id }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(400);
|
|
|
@@ -228,9 +227,12 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
|
|
|
it('应该验证商品是否存在', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/set-as-parent'].$post({
|
|
|
- param: { id: 99999 }, // 不存在的商品ID
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ const response = await client[':id']['set-as-parent'].$post({
|
|
|
+ param: { id: 99999 }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(404);
|
|
|
@@ -240,11 +242,14 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- describe('DELETE /api/v1/goods/:id/parent', () => {
|
|
|
+ describe('DELETE /goods/:id/parent', () => {
|
|
|
it('应该成功解除子商品的父子关系', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/parent'].$delete({
|
|
|
- param: { id: childGoods1.id },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ const response = await client[':id']['parent'].$delete({
|
|
|
+ param: { id: childGoods1.id }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
@@ -252,20 +257,15 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
expect(data.id).toBe(childGoods1.id);
|
|
|
expect(data.spuId).toBe(0);
|
|
|
expect(data.spuName).toBeNull();
|
|
|
-
|
|
|
- // 验证数据库中的更新
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const updatedGoods = await dataSource.getRepository(GoodsMt).findOne({
|
|
|
- where: { id: childGoods1.id } as any
|
|
|
- });
|
|
|
- expect(updatedGoods?.spuId).toBe(0);
|
|
|
- expect(updatedGoods?.spuName).toBeNull();
|
|
|
});
|
|
|
|
|
|
it('应该拒绝解除非子商品的父子关系', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/parent'].$delete({
|
|
|
- param: { id: normalGoods.id },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ const response = await client[':id']['parent'].$delete({
|
|
|
+ param: { id: parentGoods.id.toString() }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(400);
|
|
|
@@ -275,9 +275,12 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
|
|
|
it('应该验证商品是否存在', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/parent'].$delete({
|
|
|
- param: { id: 99999 }, // 不存在的商品ID
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ const response = await client[':id']['parent'].$delete({
|
|
|
+ param: { id: 99999 }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(404);
|
|
|
@@ -287,7 +290,7 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- describe('POST /api/v1/goods/batch-create-children', () => {
|
|
|
+ describe('POST /goods/batchCreateChildren', () => {
|
|
|
it('应该成功批量创建子商品', async () => {
|
|
|
const specs = [
|
|
|
{ name: '规格1 - 黑色', price: 230.00, costPrice: 180.00, stock: 50, sort: 1 },
|
|
|
@@ -299,8 +302,11 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
json: {
|
|
|
parentGoodsId: parentGoods.id,
|
|
|
specs
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
@@ -317,27 +323,24 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
expect(child.stock).toBe(specs[index].stock);
|
|
|
expect(child.sort).toBe(specs[index].sort);
|
|
|
expect(child.spuId).toBe(parentGoods.id);
|
|
|
- expect(child.spuName).toBe('父商品测试');
|
|
|
- expect(child.state).toBe(1);
|
|
|
- expect(child.tenantId).toBe(testUser.tenantId);
|
|
|
- });
|
|
|
-
|
|
|
- // 验证数据库中的记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const children = await dataSource.getRepository(GoodsMt).find({
|
|
|
- where: { spuId: parentGoods.id } as any,
|
|
|
- order: { sort: 'ASC' }
|
|
|
+ expect(child.spuName).toBe(parentGoods.name);
|
|
|
});
|
|
|
- expect(children).toHaveLength(5); // 原有2个 + 新增3个
|
|
|
});
|
|
|
|
|
|
it('应该验证父商品是否存在', async () => {
|
|
|
+ const specs = [
|
|
|
+ { name: '测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
|
|
|
+ ];
|
|
|
+
|
|
|
const response = await client.batchCreateChildren.$post({
|
|
|
json: {
|
|
|
- parentGoodsId: 99999, // 不存在的父商品ID
|
|
|
- specs: [{ name: '测试规格', price: 100, costPrice: 80, stock: 10, sort: 1 }]
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ parentGoodsId: 99999,
|
|
|
+ specs
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(404);
|
|
|
@@ -347,12 +350,20 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
|
|
|
it('应该验证父商品必须是父商品', async () => {
|
|
|
+ // 尝试为子商品创建子商品
|
|
|
+ const specs = [
|
|
|
+ { name: '测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
|
|
|
+ ];
|
|
|
+
|
|
|
const response = await client.batchCreateChildren.$post({
|
|
|
json: {
|
|
|
- parentGoodsId: childGoods1.id, // 子商品ID
|
|
|
- specs: [{ name: '测试规格', price: 100, costPrice: 80, stock: 10, sort: 1 }]
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ parentGoodsId: childGoods1.id,
|
|
|
+ specs
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(400);
|
|
|
@@ -362,104 +373,91 @@ describe('管理员父子商品管理API集成测试', () => {
|
|
|
});
|
|
|
|
|
|
it('应该验证规格数据有效性', async () => {
|
|
|
+ const specs = [
|
|
|
+ { name: '', price: -100, costPrice: -80, stock: -10, sort: 1 } // 无效数据
|
|
|
+ ];
|
|
|
+
|
|
|
const response = await client.batchCreateChildren.$post({
|
|
|
json: {
|
|
|
parentGoodsId: parentGoods.id,
|
|
|
- specs: [] // 空规格列表
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ specs
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(400);
|
|
|
const data = await response.json();
|
|
|
expect(data.code).toBe(400);
|
|
|
- expect(data.message).toContain('至少需要一个规格');
|
|
|
+ expect(data.message).toContain('规格名称不能为空');
|
|
|
});
|
|
|
|
|
|
it('应该继承父商品的分类和其他信息', async () => {
|
|
|
- const specs = [{ name: '继承测试规格', price: 100, costPrice: 80, stock: 10, sort: 1 }];
|
|
|
+ const specs = [
|
|
|
+ { name: '继承测试规格', price: 100.00, costPrice: 80.00, stock: 10, sort: 1 }
|
|
|
+ ];
|
|
|
|
|
|
const response = await client.batchCreateChildren.$post({
|
|
|
json: {
|
|
|
parentGoodsId: parentGoods.id,
|
|
|
specs
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${adminToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
const data = await response.json();
|
|
|
- const child = data.children[0];
|
|
|
+ expect(data.success).toBe(true);
|
|
|
+ expect(data.count).toBe(1);
|
|
|
|
|
|
- // 验证继承的字段
|
|
|
+ const child = data.children[0];
|
|
|
expect(child.categoryId1).toBe(parentGoods.categoryId1);
|
|
|
expect(child.categoryId2).toBe(parentGoods.categoryId2);
|
|
|
expect(child.categoryId3).toBe(parentGoods.categoryId3);
|
|
|
- expect(child.goodsType).toBe(parentGoods.goodsType);
|
|
|
expect(child.supplierId).toBe(parentGoods.supplierId);
|
|
|
expect(child.merchantId).toBe(parentGoods.merchantId);
|
|
|
- });
|
|
|
-
|
|
|
- it('应该支持事务,全部成功或全部失败', async () => {
|
|
|
- const specs = [
|
|
|
- { name: '有效规格1', price: 100, costPrice: 80, stock: 10, sort: 1 },
|
|
|
- { name: '', price: 100, costPrice: 80, stock: 10, sort: 2 }, // 无效:名称为空
|
|
|
- { name: '有效规格3', price: 100, costPrice: 80, stock: 10, sort: 3 }
|
|
|
- ];
|
|
|
-
|
|
|
- const response = await client.batchCreateChildren.$post({
|
|
|
- json: {
|
|
|
- parentGoodsId: parentGoods.id,
|
|
|
- specs
|
|
|
- },
|
|
|
- header: { authorization: `Bearer ${authToken}` }
|
|
|
- });
|
|
|
-
|
|
|
- // 由于数据库约束,这个测试可能会失败
|
|
|
- // 但重要的是验证事务机制
|
|
|
- expect(response.status).toBe(500);
|
|
|
-
|
|
|
- // 验证没有创建任何子商品(事务回滚)
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const children = await dataSource.getRepository(GoodsMt).find({
|
|
|
- where: { spuId: parentGoods.id } as any
|
|
|
- });
|
|
|
- expect(children).toHaveLength(2); // 只有原有的2个子商品
|
|
|
+ expect(child.goodsType).toBe(parentGoods.goodsType);
|
|
|
});
|
|
|
});
|
|
|
|
|
|
describe('认证和授权', () => {
|
|
|
it('应该要求认证', async () => {
|
|
|
- const response = await client['api/v1/goods/{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: parentGoods.id },
|
|
|
query: { page: 1, pageSize: 10 }
|
|
|
- // 不提供认证头
|
|
|
});
|
|
|
|
|
|
expect(response.status).toBe(401);
|
|
|
});
|
|
|
|
|
|
it('应该验证租户隔离', async () => {
|
|
|
- // 创建另一个租户的用户和商品
|
|
|
- const otherUser = await testFactory.createTestUser('other-tenant');
|
|
|
- const otherAuthToken = JWTUtil.generateToken({
|
|
|
- id: otherUser.id,
|
|
|
- username: otherUser.username,
|
|
|
- tenantId: otherUser.tenantId,
|
|
|
- roles: ['admin']
|
|
|
+ // 创建另一个租户的用户
|
|
|
+ const otherTenantUser = await testFactory.createTestUser();
|
|
|
+ otherTenantUser.tenantId = 2; // 不同租户
|
|
|
+ await testFactory.dataSource.getRepository(UserEntityMt).save(otherTenantUser);
|
|
|
+
|
|
|
+ const otherTenantToken = JWTUtil.generateToken({
|
|
|
+ id: otherTenantUser.id,
|
|
|
+ username: otherTenantUser.username,
|
|
|
+ roles: [{name:'admin'}]
|
|
|
});
|
|
|
|
|
|
- // 尝试访问第一个租户的商品
|
|
|
- const response = await client['api/v1/goods/{id}/children'].$get({
|
|
|
+ const response = await client[':id']['children'].$get({
|
|
|
param: { id: parentGoods.id },
|
|
|
- query: { page: 1, pageSize: 10 },
|
|
|
- header: { authorization: `Bearer ${otherAuthToken}` }
|
|
|
+ query: { page: 1, pageSize: 10 }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${otherTenantToken}`
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
+ // 不同租户应该看不到其他租户的数据
|
|
|
expect(response.status).toBe(404);
|
|
|
- const data = await response.json();
|
|
|
- expect(data.code).toBe(404);
|
|
|
- expect(data.message).toContain('父商品不存在');
|
|
|
});
|
|
|
});
|
|
|
-});
|
|
|
+});
|