refactor(backend): 优化API文档、认证路由和分页查询,统一响应格式并添加字段验证
This commit is contained in:
@@ -1,261 +1,74 @@
|
||||
const request = require('supertest');
|
||||
const testSequelize = require('../test-database');
|
||||
const app = require('../../src/main');
|
||||
const { User } = require('../../src/models');
|
||||
|
||||
// 创建测试专用的User模型
|
||||
const { DataTypes } = require('sequelize');
|
||||
const User = testSequelize.define('User', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
comment: '用户ID'
|
||||
},
|
||||
nickname: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '用户昵称'
|
||||
},
|
||||
phone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: true,
|
||||
unique: true,
|
||||
comment: '手机号码'
|
||||
},
|
||||
password_hash: {
|
||||
type: DataTypes.STRING(255),
|
||||
allowNull: true,
|
||||
comment: '密码哈希值'
|
||||
},
|
||||
user_type: {
|
||||
type: DataTypes.ENUM('buyer', 'trader', 'supplier', 'driver', 'staff', 'admin'),
|
||||
allowNull: false,
|
||||
defaultValue: 'buyer',
|
||||
comment: '用户类型'
|
||||
}
|
||||
}, {
|
||||
tableName: 'users',
|
||||
timestamps: true,
|
||||
createdAt: 'created_at',
|
||||
updatedAt: 'updated_at'
|
||||
});
|
||||
|
||||
// 创建测试专用的app实例
|
||||
const createTestApp = () => {
|
||||
// 确保测试环境
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
// 导入app但不启动服务器
|
||||
const app = require('../../src/main');
|
||||
return app;
|
||||
};
|
||||
|
||||
describe('Authentication Integration Tests', () => {
|
||||
let app;
|
||||
let testUser;
|
||||
describe('Auth API Tests', () => {
|
||||
let authToken;
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建测试app
|
||||
app = createTestApp();
|
||||
|
||||
// 同步测试数据库
|
||||
await testSequelize.sync({ force: true });
|
||||
|
||||
// 创建测试用户 - 使用User模型中实际存在的字段
|
||||
testUser = await User.create({
|
||||
nickname: 'Test User', // 必填字段
|
||||
phone: '13800138000', // 可选字段
|
||||
password_hash: 'testpassword123', // 可选字段
|
||||
user_type: 'buyer' // 必填字段,默认值
|
||||
// 创建测试用户
|
||||
await User.create({
|
||||
username: 'testadmin',
|
||||
password: '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
email: 'test@example.com',
|
||||
role: 'admin',
|
||||
status: 'active'
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// 清理测试数据
|
||||
if (testUser) {
|
||||
await testUser.destroy();
|
||||
}
|
||||
|
||||
// 关闭测试数据库连接
|
||||
await testSequelize.close();
|
||||
await User.destroy({ where: { username: 'testadmin' } });
|
||||
});
|
||||
|
||||
describe('POST /api/auth/login', () => {
|
||||
it('应该成功登录并返回token', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: '13800138000', // 使用phone登录
|
||||
password: 'testpassword123'
|
||||
})
|
||||
.expect(200);
|
||||
test('POST /auth/login - 用户登录成功', async () => {
|
||||
const response = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'testadmin',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toBe('登录成功');
|
||||
expect(response.body.data).toHaveProperty('access_token');
|
||||
expect(response.body.data).toHaveProperty('user');
|
||||
expect(response.body.data.user.username).toBe('Test User');
|
||||
expect(response.body.data.user).not.toHaveProperty('password');
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('token');
|
||||
expect(response.body.data).toHaveProperty('user');
|
||||
expect(response.body.data.user.username).toBe('testadmin');
|
||||
|
||||
// 保存token用于后续测试
|
||||
authToken = response.body.data.access_token;
|
||||
|
||||
// 保存token用于后续测试
|
||||
authToken = response.body.data.access_token;
|
||||
});
|
||||
|
||||
it('应该在用户名不存在时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: 'nonexistent',
|
||||
password: 'testpassword123'
|
||||
})
|
||||
.expect(401);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toBe('用户名或密码错误');
|
||||
});
|
||||
|
||||
it('应该在密码错误时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: '13800138000',
|
||||
password: 'wrongpassword'
|
||||
})
|
||||
.expect(401);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toBe('用户名或密码错误');
|
||||
});
|
||||
|
||||
it('应该在缺少参数时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: '13800138000'
|
||||
// 缺少password
|
||||
})
|
||||
.expect(400);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toBe('用户名和密码不能为空');
|
||||
});
|
||||
authToken = response.body.data.token;
|
||||
});
|
||||
|
||||
describe('POST /api/auth/logout', () => {
|
||||
it('应该成功登出', async () => {
|
||||
// 先登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: '13800138000',
|
||||
password: 'testpassword123'
|
||||
});
|
||||
test('POST /auth/login - 用户登录失败(密码错误)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'testadmin',
|
||||
password: 'wrongpassword'
|
||||
});
|
||||
|
||||
const token = loginResponse.body.data.access_token;
|
||||
|
||||
const response = await request(app)
|
||||
.post('/api/auth/logout')
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toBe('登出成功');
|
||||
});
|
||||
|
||||
it('应该在没有认证时也能成功登出', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/logout')
|
||||
.expect(401); // 因为没有提供token,应该返回401
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
});
|
||||
expect(response.status).toBe(401);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toContain('密码错误');
|
||||
});
|
||||
|
||||
describe('GET /api/auth/current', () => {
|
||||
it('应该返回当前用户信息', async () => {
|
||||
// 先登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/api/auth/login')
|
||||
.send({
|
||||
username: '13800138000',
|
||||
password: 'testpassword123'
|
||||
});
|
||||
test('GET /auth/me - 获取当前用户信息', async () => {
|
||||
const response = await request(app)
|
||||
.get('/auth/me')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
const token = loginResponse.body.data.access_token;
|
||||
|
||||
const response = await request(app)
|
||||
.get('/api/auth/current')
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('id');
|
||||
expect(response.body.data).toHaveProperty('username');
|
||||
expect(response.body.data).not.toHaveProperty('password');
|
||||
});
|
||||
|
||||
it('应该在没有认证时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.get('/api/auth/current')
|
||||
.expect(401);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
});
|
||||
|
||||
it('应该在token无效时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.get('/api/auth/current')
|
||||
.set('Authorization', 'Bearer invalid_token')
|
||||
.expect(401);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.username).toBe('testadmin');
|
||||
expect(response.body.data.email).toBe('test@example.com');
|
||||
});
|
||||
|
||||
describe('POST /api/auth/mini-program/login', () => {
|
||||
it('应该成功进行小程序登录', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/mini-program/login')
|
||||
.send({
|
||||
phone: '13900139000',
|
||||
code: '123456',
|
||||
miniProgramType: 'client'
|
||||
})
|
||||
.expect(200);
|
||||
test('POST /auth/logout - 用户登出', async () => {
|
||||
const response = await request(app)
|
||||
.post('/auth/logout')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toBe('登录成功');
|
||||
expect(response.body.data).toHaveProperty('token');
|
||||
expect(response.body.data).toHaveProperty('userInfo');
|
||||
});
|
||||
|
||||
it('应该在验证码错误时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/mini-program/login')
|
||||
.send({
|
||||
phone: '13900139000',
|
||||
code: '000000', // 错误的验证码
|
||||
miniProgramType: 'client'
|
||||
})
|
||||
.expect(400);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toBe('验证码错误');
|
||||
});
|
||||
|
||||
it('应该在缺少参数时返回错误', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/auth/mini-program/login')
|
||||
.send({
|
||||
phone: '13900139000'
|
||||
// 缺少code和miniProgramType
|
||||
})
|
||||
.expect(400);
|
||||
|
||||
expect(response.body.success).toBe(false);
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toContain('登出成功');
|
||||
});
|
||||
});
|
||||
142
backend/tests/integration/orders.test.js
Normal file
142
backend/tests/integration/orders.test.js
Normal file
@@ -0,0 +1,142 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../../src/main');
|
||||
const { User, Order, Product } = require('../../src/models');
|
||||
|
||||
describe('Orders API Tests', () => {
|
||||
let authToken;
|
||||
let testOrderId;
|
||||
let testProductId;
|
||||
let testUserId;
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建测试用户
|
||||
const user = await User.create({
|
||||
username: 'orderuser',
|
||||
password: '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
|
||||
email: 'order@example.com',
|
||||
role: 'user',
|
||||
status: 'active'
|
||||
});
|
||||
testUserId = user.id;
|
||||
|
||||
// 创建测试商品
|
||||
const product = await Product.create({
|
||||
name: '测试牛只',
|
||||
price: 5000,
|
||||
stock: 10,
|
||||
category: 'cattle',
|
||||
status: 'available'
|
||||
});
|
||||
testProductId = product.id;
|
||||
|
||||
// 登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'orderuser',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
authToken = loginResponse.body.data.token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// 清理测试数据
|
||||
await User.destroy({ where: { id: testUserId } });
|
||||
await Product.destroy({ where: { id: testProductId } });
|
||||
if (testOrderId) {
|
||||
await Order.destroy({ where: { id: testOrderId } });
|
||||
}
|
||||
});
|
||||
|
||||
test('POST /orders - 创建订单', async () => {
|
||||
const response = await request(app)
|
||||
.post('/orders')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
userId: testUserId,
|
||||
items: [
|
||||
{
|
||||
productId: testProductId,
|
||||
quantity: 1,
|
||||
price: 5000
|
||||
}
|
||||
],
|
||||
totalAmount: 5000,
|
||||
shippingAddress: '测试地址',
|
||||
paymentMethod: 'bank_transfer'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('id');
|
||||
expect(response.body.data.totalAmount).toBe(5000);
|
||||
expect(response.body.data.status).toBe('pending');
|
||||
|
||||
testOrderId = response.body.data.id;
|
||||
});
|
||||
|
||||
test('GET /orders - 获取订单列表', async () => {
|
||||
const response = await request(app)
|
||||
.get('/orders')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(Array.isArray(response.body.data)).toBe(true);
|
||||
expect(response.body.data[0]).toHaveProperty('id');
|
||||
expect(response.body.data[0]).toHaveProperty('totalAmount');
|
||||
expect(response.body.data[0]).toHaveProperty('status');
|
||||
});
|
||||
|
||||
test('GET /orders/:id - 获取订单详情', async () => {
|
||||
const response = await request(app)
|
||||
.get(`/orders/${testOrderId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.id).toBe(testOrderId);
|
||||
expect(response.body.data.totalAmount).toBe(5000);
|
||||
expect(Array.isArray(response.body.data.items)).toBe(true);
|
||||
});
|
||||
|
||||
test('PUT /orders/:id - 更新订单状态', async () => {
|
||||
const response = await request(app)
|
||||
.put(`/orders/${testOrderId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
status: 'processing'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.status).toBe('processing');
|
||||
});
|
||||
|
||||
test('DELETE /orders/:id - 删除订单', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`/orders/${testOrderId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toContain('删除成功');
|
||||
|
||||
testOrderId = null;
|
||||
});
|
||||
|
||||
test('POST /orders - 创建订单验证失败(缺少必填字段)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/orders')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
// 缺少items和totalAmount
|
||||
shippingAddress: '测试地址'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toContain('验证失败');
|
||||
});
|
||||
});
|
||||
122
backend/tests/integration/payments.test.js
Normal file
122
backend/tests/integration/payments.test.js
Normal file
@@ -0,0 +1,122 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../../src/main');
|
||||
const { User, Order, Payment } = require('../../src/models');
|
||||
|
||||
describe('Payments API Tests', () => {
|
||||
let authToken;
|
||||
let testOrderId;
|
||||
let testPaymentId;
|
||||
let testUserId;
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建测试用户
|
||||
const user = await User.create({
|
||||
username: 'paymentuser',
|
||||
password: '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
|
||||
email: 'payment@example.com',
|
||||
role: 'user',
|
||||
status: 'active'
|
||||
});
|
||||
testUserId = user.id;
|
||||
|
||||
// 创建测试订单
|
||||
const order = await Order.create({
|
||||
userId: testUserId,
|
||||
totalAmount: 3000,
|
||||
status: 'pending',
|
||||
shippingAddress: '测试地址'
|
||||
});
|
||||
testOrderId = order.id;
|
||||
|
||||
// 登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'paymentuser',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
authToken = loginResponse.body.data.token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// 清理测试数据
|
||||
await User.destroy({ where: { id: testUserId } });
|
||||
await Order.destroy({ where: { id: testOrderId } });
|
||||
if (testPaymentId) {
|
||||
await Payment.destroy({ where: { id: testPaymentId } });
|
||||
}
|
||||
});
|
||||
|
||||
test('POST /payments - 创建支付记录', async () => {
|
||||
const response = await request(app)
|
||||
.post('/payments')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
orderId: testOrderId,
|
||||
amount: 3000,
|
||||
paymentMethod: 'alipay',
|
||||
status: 'pending'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.amount).toBe(3000);
|
||||
expect(response.body.data.paymentMethod).toBe('alipay');
|
||||
|
||||
testPaymentId = response.body.data.id;
|
||||
});
|
||||
|
||||
test('GET /payments - 获取支付记录列表', async () => {
|
||||
const response = await request(app)
|
||||
.get('/payments')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(Array.isArray(response.body.data)).toBe(true);
|
||||
expect(response.body.data[0]).toHaveProperty('id');
|
||||
expect(response.body.data[0]).toHaveProperty('amount');
|
||||
});
|
||||
|
||||
test('GET /payments/:id - 获取支付记录详情', async () => {
|
||||
const response = await request(app)
|
||||
.get(`/payments/${testPaymentId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.id).toBe(testPaymentId);
|
||||
expect(response.body.data.amount).toBe(3000);
|
||||
});
|
||||
|
||||
test('PUT /payments/:id - 更新支付状态', async () => {
|
||||
const response = await request(app)
|
||||
.put(`/payments/${testPaymentId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
status: 'completed',
|
||||
transactionId: 'TRX123456789'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.status).toBe('completed');
|
||||
expect(response.body.data.transactionId).toBe('TRX123456789');
|
||||
});
|
||||
|
||||
test('POST /payments - 验证失败(金额为负数)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/payments')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
orderId: testOrderId,
|
||||
amount: -100,
|
||||
paymentMethod: 'alipay'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toContain('验证失败');
|
||||
});
|
||||
});
|
||||
127
backend/tests/integration/suppliers.test.js
Normal file
127
backend/tests/integration/suppliers.test.js
Normal file
@@ -0,0 +1,127 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../../src/main');
|
||||
const { User, Supplier } = require('../../src/models');
|
||||
|
||||
describe('Suppliers API Tests', () => {
|
||||
let authToken;
|
||||
let testSupplierId;
|
||||
let testUserId;
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建管理员用户
|
||||
const user = await User.create({
|
||||
username: 'supplieradmin',
|
||||
password: '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
|
||||
email: 'supplier@example.com',
|
||||
role: 'admin',
|
||||
status: 'active'
|
||||
});
|
||||
testUserId = user.id;
|
||||
|
||||
// 登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'supplieradmin',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
authToken = loginResponse.body.data.token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// 清理测试数据
|
||||
await User.destroy({ where: { id: testUserId } });
|
||||
if (testSupplierId) {
|
||||
await Supplier.destroy({ where: { id: testSupplierId } });
|
||||
}
|
||||
});
|
||||
|
||||
test('POST /suppliers - 创建供应商', async () => {
|
||||
const response = await request(app)
|
||||
.post('/suppliers')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
name: '测试供应商',
|
||||
contactPerson: '张经理',
|
||||
phone: '13800138000',
|
||||
email: 'supplier@test.com',
|
||||
address: '供应商地址',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.name).toBe('测试供应商');
|
||||
expect(response.body.data.contactPerson).toBe('张经理');
|
||||
|
||||
testSupplierId = response.body.data.id;
|
||||
});
|
||||
|
||||
test('GET /suppliers - 获取供应商列表', async () => {
|
||||
const response = await request(app)
|
||||
.get('/suppliers')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(Array.isArray(response.body.data)).toBe(true);
|
||||
expect(response.body.data[0]).toHaveProperty('id');
|
||||
expect(response.body.data[0]).toHaveProperty('name');
|
||||
});
|
||||
|
||||
test('GET /suppliers/:id - 获取供应商详情', async () => {
|
||||
const response = await request(app)
|
||||
.get(`/suppliers/${testSupplierId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.id).toBe(testSupplierId);
|
||||
expect(response.body.data.name).toBe('测试供应商');
|
||||
});
|
||||
|
||||
test('PUT /suppliers/:id - 更新供应商信息', async () => {
|
||||
const response = await request(app)
|
||||
.put(`/suppliers/${testSupplierId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
phone: '13900139000',
|
||||
email: 'updated@test.com'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.phone).toBe('13900139000');
|
||||
expect(response.body.data.email).toBe('updated@test.com');
|
||||
});
|
||||
|
||||
test('DELETE /suppliers/:id - 删除供应商', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`/suppliers/${testSupplierId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toContain('删除成功');
|
||||
|
||||
testSupplierId = null;
|
||||
});
|
||||
|
||||
test('POST /suppliers - 验证失败(邮箱格式错误)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/suppliers')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
name: '测试供应商',
|
||||
contactPerson: '张经理',
|
||||
phone: '13800138000',
|
||||
email: 'invalid-email',
|
||||
address: '供应商地址'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toContain('验证失败');
|
||||
});
|
||||
});
|
||||
122
backend/tests/integration/users.test.js
Normal file
122
backend/tests/integration/users.test.js
Normal file
@@ -0,0 +1,122 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../../src/main');
|
||||
const { User } = require('../../src/models');
|
||||
|
||||
describe('Users API Tests', () => {
|
||||
let authToken;
|
||||
let testUserId;
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建管理员用户用于测试
|
||||
const adminUser = await User.create({
|
||||
username: 'adminuser',
|
||||
password: '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
email: 'admin@example.com',
|
||||
role: 'admin',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
// 登录获取token
|
||||
const loginResponse = await request(app)
|
||||
.post('/auth/login')
|
||||
.send({
|
||||
username: 'adminuser',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
authToken = loginResponse.body.data.token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// 清理测试数据
|
||||
await User.destroy({ where: { username: 'adminuser' } });
|
||||
if (testUserId) {
|
||||
await User.destroy({ where: { id: testUserId } });
|
||||
}
|
||||
});
|
||||
|
||||
test('GET /users - 获取用户列表', async () => {
|
||||
const response = await request(app)
|
||||
.get('/users')
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(Array.isArray(response.body.data)).toBe(true);
|
||||
expect(response.body.data[0]).toHaveProperty('id');
|
||||
expect(response.body.data[0]).toHaveProperty('username');
|
||||
expect(response.body.data[0]).toHaveProperty('email');
|
||||
});
|
||||
|
||||
test('POST /users - 创建新用户', async () => {
|
||||
const response = await request(app)
|
||||
.post('/users')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
username: 'newuser',
|
||||
password: 'password123',
|
||||
email: 'newuser@example.com',
|
||||
role: 'user',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.username).toBe('newuser');
|
||||
expect(response.body.data.email).toBe('newuser@example.com');
|
||||
|
||||
testUserId = response.body.data.id;
|
||||
});
|
||||
|
||||
test('GET /users/:id - 获取用户详情', async () => {
|
||||
const response = await request(app)
|
||||
.get(`/users/${testUserId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.id).toBe(testUserId);
|
||||
expect(response.body.data.username).toBe('newuser');
|
||||
});
|
||||
|
||||
test('PUT /users/:id - 更新用户信息', async () => {
|
||||
const response = await request(app)
|
||||
.put(`/users/${testUserId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
email: 'updated@example.com',
|
||||
status: 'inactive'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.email).toBe('updated@example.com');
|
||||
expect(response.body.data.status).toBe('inactive');
|
||||
});
|
||||
|
||||
test('DELETE /users/:id - 删除用户', async () => {
|
||||
const response = await request(app)
|
||||
.delete(`/users/${testUserId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toContain('删除成功');
|
||||
|
||||
testUserId = null;
|
||||
});
|
||||
|
||||
test('POST /users - 创建用户验证失败(缺少必填字段)', async () => {
|
||||
const response = await request(app)
|
||||
.post('/users')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
username: 'incomplete'
|
||||
// 缺少password和email
|
||||
});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
expect(response.body.success).toBe(false);
|
||||
expect(response.body.message).toContain('验证失败');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user