Files

322 lines
9.4 KiB
JavaScript
Raw Permalink Normal View History

/**
* 分类管理API测试
* TDD: 先写测试,再实现功能
*/
const request = require('supertest');
const express = require('express');
// 模拟Express应用
const app = express();
app.use(express.json());
// 测试数据
const testCategories = [
{ name: '测试一级分类1', parent_id: null, level: 1 },
{ name: '测试一级分类2', parent_id: null, level: 1 },
];
describe('分类管理API测试', () => {
// 测试1: 获取分类树
describe('GET /api/categories/tree', () => {
test('应该返回分类树结构', async () => {
const response = await request(app)
.get('/api/categories/tree')
.expect(200);
expect(response.body.success).toBe(true);
expect(Array.isArray(response.body.data)).toBe(true);
// 每个一级分类应该有children属性
if (response.body.data.length > 0) {
expect(response.body.data[0]).toHaveProperty('children');
}
});
test('应该支持按层级筛选', async () => {
const response = await request(app)
.get('/api/categories/tree?level=1')
.expect(200);
expect(response.body.success).toBe(true);
// 返回的都是一级分类
response.body.data.forEach(cat => {
expect(cat.level).toBe(1);
});
});
});
// 测试2: 创建分类
describe('POST /api/categories', () => {
test('应该能创建一级分类', async () => {
const newCategory = {
name: '新材料分类',
parent_id: null,
level: 1,
description: '测试描述'
};
const response = await request(app)
.post('/api/categories')
.send(newCategory)
.expect(200);
expect(response.body.success).toBe(true);
expect(response.body.data).toHaveProperty('id');
expect(response.body.data.name).toBe(newCategory.name);
});
test('应该能在指定父分类下创建二级分类', async () => {
// 先创建父分类
const parentResponse = await request(app)
.post('/api/categories')
.send({ name: '父分类', parent_id: null, level: 1 });
const parentId = parentResponse.body.data.id;
// 创建子分类
const childCategory = {
name: '子分类',
parent_id: parentId,
level: 2
};
const response = await request(app)
.post('/api/categories')
.send(childCategory)
.expect(200);
expect(response.body.success).toBe(true);
expect(response.body.data.parent_id).toBe(parentId);
expect(response.body.data.level).toBe(2);
});
test('分类名称不能为空', async () => {
const response = await request(app)
.post('/api/categories')
.send({ name: '', parent_id: null, level: 1 })
.expect(400);
expect(response.body.success).toBe(false);
expect(response.body.message).toContain('名称');
});
test('同一父分类下不能有重名子分类', async () => {
// 创建父分类
const parent = await request(app)
.post('/api/categories')
.send({ name: '唯一父分类', parent_id: null, level: 1 });
// 创建第一个子分类
await request(app)
.post('/api/categories')
.send({ name: '同名子分类', parent_id: parent.body.data.id, level: 2 });
// 尝试创建同名子分类
const response = await request(app)
.post('/api/categories')
.send({ name: '同名子分类', parent_id: parent.body.data.id, level: 2 })
.expect(400);
expect(response.body.success).toBe(false);
});
});
// 测试3: 更新分类
describe('PUT /api/categories/:id', () => {
test('应该能更新分类名称', async () => {
// 先创建分类
const createResponse = await request(app)
.post('/api/categories')
.send({ name: '原名称', parent_id: null, level: 1 });
const categoryId = createResponse.body.data.id;
// 更新分类
const response = await request(app)
.put(`/api/categories/${categoryId}`)
.send({ name: '新名称' })
.expect(200);
expect(response.body.success).toBe(true);
// 验证更新
const getResponse = await request(app)
.get(`/api/categories/${categoryId}`)
.expect(200);
expect(getResponse.body.data.name).toBe('新名称');
});
test('不能将分类设置为自己的子分类', async () => {
// 创建父分类
const parent = await request(app)
.post('/api/categories')
.send({ name: '父', parent_id: null, level: 1 });
// 创建子分类
const child = await request(app)
.post('/api/categories')
.send({ name: '子', parent_id: parent.body.data.id, level: 2 });
// 尝试将父分类的parent_id设为子分类(循环引用)
const response = await request(app)
.put(`/api/categories/${parent.body.data.id}`)
.send({ parent_id: child.body.data.id })
.expect(400);
expect(response.body.success).toBe(false);
});
});
// 测试4: 删除分类
describe('DELETE /api/categories/:id', () => {
test('应该能删除空分类', async () => {
// 创建分类
const createResponse = await request(app)
.post('/api/categories')
.send({ name: '待删除', parent_id: null, level: 1 });
const categoryId = createResponse.body.data.id;
// 删除分类
const response = await request(app)
.delete(`/api/categories/${categoryId}`)
.expect(200);
expect(response.body.success).toBe(true);
// 验证已删除
const getResponse = await request(app)
.get(`/api/categories/${categoryId}`)
.expect(404);
});
test('删除一级分类应该级联删除二级分类', async () => {
// 创建父分类
const parent = await request(app)
.post('/api/categories')
.send({ name: '父', parent_id: null, level: 1 });
// 创建子分类
const child = await request(app)
.post('/api/categories')
.send({ name: '子', parent_id: parent.body.data.id, level: 2 });
// 删除父分类
await request(app)
.delete(`/api/categories/${parent.body.data.id}`)
.expect(200);
// 验证子分类也被删除
await request(app)
.get(`/api/categories/${child.body.data.id}`)
.expect(404);
});
test('有商品的分类不应该被删除', async () => {
// 创建分类
const category = await request(app)
.post('/api/categories')
.send({ name: '有商品的分类', parent_id: null, level: 1 });
// 在该分类下创建商品(模拟)
// ... 创建商品逻辑
// 尝试删除分类
const response = await request(app)
.delete(`/api/categories/${category.body.data.id}`)
.expect(400);
expect(response.body.success).toBe(false);
expect(response.body.message).toContain('商品');
});
});
// 测试5: 批量导入时自动创建分类
describe('批量导入分类处理', () => {
test('导入时应该自动创建不存在的一级分类', async () => {
const importData = {
products: [
{
name: '测试商品',
category_level1: '新一级分类',
category_level2: '新二级分类'
}
]
};
const response = await request(app)
.post('/api/products/batch-import')
.send(importData)
.expect(200);
expect(response.body.success).toBe(true);
// 验证分类已创建
const categories = await request(app)
.get('/api/categories/tree')
.expect(200);
const level1Exists = categories.body.data.some(
cat => cat.name === '新一级分类'
);
expect(level1Exists).toBe(true);
});
test('导入时应该自动创建不存在的二级分类', async () => {
// 先创建一级分类
await request(app)
.post('/api/categories')
.send({ name: '已有的一级', parent_id: null, level: 1 });
// 导入带有新二级分类的商品
const importData = {
products: [
{
name: '测试商品2',
category_level1: '已有的一级',
category_level2: '新的二级'
}
]
};
await request(app)
.post('/api/products/batch-import')
.send(importData)
.expect(200);
// 验证二级分类已创建
const categories = await request(app)
.get('/api/categories/tree')
.expect(200);
const parent = categories.body.data.find(
cat => cat.name === '已有的一级'
);
expect(parent).toBeTruthy();
expect(parent.children).toBeDefined();
const level2Exists = parent.children.some(
child => child.name === '新的二级'
);
expect(level2Exists).toBe(true);
});
});
});
// 运行测试
if (require.main === module) {
const { execSync } = require('child_process');
try {
execSync('npx jest test-category-api.spec.js --verbose', {
cwd: __dirname,
stdio: 'inherit'
});
} catch (e) {
process.exit(1);
}
}
module.exports = { app };