const request = require('supertest'); const app = require('../index'); describe('PDF转换工具 API 测试', () => { describe('系统健康检查', () => { test('GET /health 应该返回系统健康状态', async () => { const response = await request(app) .get('/health') .expect(200); expect(response.body).toHaveProperty('status', 'OK'); expect(response.body).toHaveProperty('timestamp'); expect(response.body).toHaveProperty('uptime'); expect(response.body).toHaveProperty('memory'); }); }); describe('系统信息 API', () => { test('GET /api/system/health 应该返回详细健康信息', async () => { const response = await request(app) .get('/api/system/health') .expect(200); expect(response.body).toHaveProperty('status'); expect(response.body).toHaveProperty('timestamp'); expect(response.body).toHaveProperty('system'); }); test('GET /api/system/stats 应该返回系统统计信息', async () => { const response = await request(app) .get('/api/system/stats') .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('files'); expect(response.body.data).toHaveProperty('conversions'); expect(response.body.data).toHaveProperty('users'); }); test('GET /api/system/formats 应该返回支持的格式信息', async () => { const response = await request(app) .get('/api/system/formats') .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('input'); expect(response.body.data).toHaveProperty('output'); expect(Array.isArray(response.body.data.input)).toBe(true); expect(Array.isArray(response.body.data.output)).toBe(true); }); test('GET /api/system/config 应该返回系统配置信息', async () => { const response = await request(app) .get('/api/system/config') .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('upload'); expect(response.body.data).toHaveProperty('conversion'); expect(response.body.data).toHaveProperty('security'); }); }); describe('用户认证 API', () => { const testUser = { email: 'test@example.com', username: 'testuser', password: 'password123' }; test('POST /api/users/register 应该成功注册新用户', async () => { const response = await request(app) .post('/api/users/register') .send(testUser) .expect(201); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('user'); expect(response.body.data).toHaveProperty('token'); expect(response.body.data.user.email).toBe(testUser.email); }); test('POST /api/users/register 应该拒绝重复邮箱', async () => { // 先注册一次 await request(app) .post('/api/users/register') .send(testUser); // 再次注册相同邮箱 const response = await request(app) .post('/api/users/register') .send(testUser) .expect(400); expect(response.body.success).toBe(false); expect(response.body.message).toContain('邮箱已被注册'); }); test('POST /api/users/login 应该成功登录', async () => { // 先注册用户 await request(app) .post('/api/users/register') .send(testUser); // 登录 const response = await request(app) .post('/api/users/login') .send({ email: testUser.email, password: testUser.password }) .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('user'); expect(response.body.data).toHaveProperty('token'); }); test('POST /api/users/login 应该拒绝错误密码', async () => { // 先注册用户 await request(app) .post('/api/users/register') .send(testUser); // 使用错误密码登录 const response = await request(app) .post('/api/users/login') .send({ email: testUser.email, password: 'wrongpassword' }) .expect(401); expect(response.body.success).toBe(false); expect(response.body.message).toContain('邮箱或密码错误'); }); }); describe('转换任务 API', () => { test('POST /api/convert/start 应该创建转换任务', async () => { const conversionData = { fileId: 'test-file-id', outputFormat: 'docx', options: { preserveLayout: true, includeImages: true } }; const response = await request(app) .post('/api/convert/start') .send(conversionData) .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('taskId'); expect(response.body.data).toHaveProperty('status', 'pending'); expect(response.body.data).toHaveProperty('progress', 0); }); test('POST /api/convert/start 应该验证必要参数', async () => { const response = await request(app) .post('/api/convert/start') .send({}) .expect(400); expect(response.body.success).toBe(false); expect(response.body.message).toContain('缺少必要参数'); }); test('POST /api/convert/start 应该验证输出格式', async () => { const response = await request(app) .post('/api/convert/start') .send({ fileId: 'test-file-id', outputFormat: 'invalid-format' }) .expect(400); expect(response.body.success).toBe(false); expect(response.body.message).toContain('不支持的输出格式'); }); test('GET /api/convert/status/:taskId 应该返回任务状态', async () => { // 先创建任务 const createResponse = await request(app) .post('/api/convert/start') .send({ fileId: 'test-file-id', outputFormat: 'docx' }); const taskId = createResponse.body.data.taskId; // 查询状态 const response = await request(app) .get(`/api/convert/status/${taskId}`) .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('taskId', taskId); expect(response.body.data).toHaveProperty('status'); expect(response.body.data).toHaveProperty('progress'); }); test('GET /api/convert/status/:taskId 应该处理不存在的任务', async () => { const response = await request(app) .get('/api/convert/status/non-existent-task') .expect(404); expect(response.body.success).toBe(false); expect(response.body.message).toContain('转换任务未找到'); }); }); describe('文件管理 API', () => { test('GET /api/files/:fileId 应该返回文件信息', async () => { const response = await request(app) .get('/api/files/test-file-id') .expect(200); expect(response.body.success).toBe(true); expect(response.body.data).toHaveProperty('fileId'); expect(response.body.data).toHaveProperty('originalName'); expect(response.body.data).toHaveProperty('fileSize'); }); test('DELETE /api/files/:fileId 应该删除文件', async () => { const response = await request(app) .delete('/api/files/test-file-id') .expect(200); expect(response.body.success).toBe(true); expect(response.body.message).toContain('文件删除成功'); }); }); describe('错误处理', () => { test('不存在的路由应该返回404', async () => { const response = await request(app) .get('/api/non-existent-route') .expect(404); expect(response.body.success).toBe(false); expect(response.body.message).toContain('接口不存在'); }); test('无效的JSON应该返回400', async () => { const response = await request(app) .post('/api/convert/start') .send('invalid json') .set('Content-Type', 'application/json') .expect(400); }); }); describe('请求限流', () => { test('短时间内大量请求应该被限制', async () => { const requests = []; // 发送多个并发请求 for (let i = 0; i < 20; i++) { requests.push( request(app) .get('/api/system/health') ); } const responses = await Promise.all(requests); // 应该有一些请求被限制 const rateLimitedResponses = responses.filter(res => res.status === 429); expect(rateLimitedResponses.length).toBeGreaterThan(0); }, 10000); }); }); // 测试工具函数 describe('工具函数测试', () => { test('应该正确格式化文件大小', () => { const formatBytes = require('../utils/formatBytes'); expect(formatBytes(0)).toBe('0 Bytes'); expect(formatBytes(1024)).toBe('1.0 KB'); expect(formatBytes(1048576)).toBe('1.0 MB'); expect(formatBytes(1073741824)).toBe('1.0 GB'); }); test('应该正确验证邮箱格式', () => { const validateEmail = require('../utils/validateEmail'); expect(validateEmail('test@example.com')).toBe(true); expect(validateEmail('invalid-email')).toBe(false); expect(validateEmail('test@')).toBe(false); expect(validateEmail('@example.com')).toBe(false); }); test('应该正确生成UUID', () => { const { v4: uuidv4 } = require('uuid'); const uuid1 = uuidv4(); const uuid2 = uuidv4(); expect(uuid1).not.toBe(uuid2); expect(uuid1).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i); }); });