/** * TTS 流程集成测试 * 测试合成→存储→配额扣除完整流程 */ import { describe, it, expect, beforeAll } from 'vitest'; import { apiPost, apiGet, setAuthToken, initHttpClient, createTestUser } from '../../integration/http-client'; describe('TTS 流程集成测试', () => { let authToken: string; let userId: string; let audioId: string; beforeAll(async () => { try { const user = await createTestUser(); authToken = user.token; userId = user.userId; setAuthToken(authToken); } catch (e) { console.log('创建测试用户失败,跳过部分测试'); } }); describe('Step 1: 音色和提供商', () => { it('获取音色列表', async () => { if (!authToken) return; const res = await apiGet('/api/tts/voices'); expect(res.code).toBe(0); expect(res.data?.voices).toBeDefined(); expect(Array.isArray(res.data.voices)).toBe(true); expect(res.data.voices.length).toBeGreaterThan(0); }); it('获取提供商列表', async () => { if (!authToken) return; const res = await apiGet('/api/tts/providers'); expect(res.code).toBe(0); expect(res.data?.providers).toBeDefined(); }); it('获取用户可用配额', async () => { if (!authToken) return; const res = await apiGet('/api/auth/user-info'); expect(res.code).toBe(0); // 检查每日配额字段存在 expect(res.data).toHaveProperty('dailyUsage'); }); }); describe('Step 2: TTS 音频生成', () => { it('生成 TTS 音频任务成功', async () => { if (!authToken) return; const res = await apiPost('/api/tts/generate', { text: '这是一段自动化测试文本,用于验证TTS音频生成功能。人工智能正在改变我们的生活方式。', voiceId: 'Cherry', voiceParams: { speed: 1.0, pitch: 0, volume: 50, }, }); expect(res.code).toBe(0); expect(res.data?.audioId).toBeDefined(); audioId = res.data?.audioId; }); it('无效音色返回错误', async () => { if (!authToken) return; const res = await apiPost('/api/tts/generate', { text: '测试文本', voiceId: 'InvalidVoiceName', }); // 应该返回错误 expect(res.code).not.toBe(0); }); it('空文本返回错误', async () => { if (!authToken) return; const res = await apiPost('/api/tts/generate', { text: '', voiceId: 'Cherry', }); expect(res.code).not.toBe(0); }); }); describe('Step 3: 查询音频状态', () => { it('查询刚生成的音频状态', async () => { if (!authToken || !audioId) return; const res = await apiGet(`/api/tts/status/${audioId}`); // 刚生成的音频查询请求应成功返回 expect(res.code).toBeDefined(); expect([401, 403]).not.toContain(res.code); // 不应该是认证/权限错误 }); it('查询不存在的音频返回错误', async () => { if (!authToken) return; const res = await apiGet('/api/tts/status/nonexistent_audio_id'); // 不存在的音频应返回错误(404 或业务错误码) expect(res.code).not.toBe(0); }); }); describe('Step 4: 配额消耗验证', () => { it('生成音频后配额已使用', async () => { if (!authToken || !audioId) return; // 先获取用户信息记录当前使用量 const userBefore = await apiGet('/api/auth/user-info'); const usageBefore = userBefore.data?.dailyUsage || 0; // 生成新音频 const genRes = await apiPost('/api/tts/generate', { text: '测试配额消耗', voiceId: 'Cherry', }); // 如果生成成功,配额应该增加 if (genRes.code === 0) { const userAfter = await apiGet('/api/auth/user-info'); const usageAfter = userAfter.data?.dailyUsage || 0; // 配额应该增加了(或者已达上限) expect(usageAfter).toBeGreaterThanOrEqual(usageBefore); } }); it('超额使用时返回配额不足错误', async () => { if (!authToken) return; // 尝试生成超长文本(超出免费配额) const res = await apiPost('/api/tts/generate', { text: 'A'.repeat(50000), // 超长文本 voiceId: 'Cherry', }); // 可能是配额不足或直接生成(取决于实现) // 免费用户可能有不同处理逻辑 expect(res.code).toBeDefined(); }); }); describe('Step 5: 音频下载', () => { it('获取下载信息', async () => { if (!authToken || !audioId) return; const res = await apiGet(`/api/tts/download/${audioId}`); // 音频可能尚未生成完毕(处理中)或已可下载 expect(res.code).toBeDefined(); expect([401, 403]).not.toContain(res.code); }); }); });