| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /**
- * 订阅流程集成测试
- * 测试套餐切换→配额计算→超额完整流程
- */
- import { describe, it, expect, beforeAll } from 'vitest';
- import { apiGet, apiPost, setAuthToken, initHttpClient, createTestUser } from '../../integration/http-client';
- describe('订阅流程集成测试', () => {
- let authToken: string;
- let userId: 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/payment/plans');
- expect(res.code).toBe(0);
- expect(Array.isArray(res.data?.plans)).toBe(true);
- expect(res.data?.plans.length).toBeGreaterThan(0);
- });
- it('获取单个套餐详情', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/payment/plan/1');
- expect(res.code).toBe(0);
- expect(res.data?.name).toBeDefined();
- });
- it('获取不存在的套餐返回错误', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/payment/plan/9999');
- expect(res.code).not.toBe(0);
- });
- });
- describe('Step 2: 当前用户订阅状态', () => {
- it('获取当前会员等级', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/auth/user-info');
- expect(res.code).toBe(0);
- expect(res.data).toHaveProperty('memberLevel');
- // 新用户应该是免费会员 (memberLevel = 0)
- expect(res.data?.memberLevel).toBe(0);
- });
- 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 3: 订阅配额计算', () => {
- it('免费版月配额正确', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/auth/user-info');
- expect(res.code).toBe(0);
- const memberLevel = res.data?.memberLevel || 0;
- // 免费版配额应该是 0 或有限值
- if (memberLevel === 0) {
- // 免费版不应该有太多配额
- expect(res.data?.dailyUsage).toBeDefined();
- }
- });
- it('专业版月配额更高', async () => {
- // 这个测试需要先购买会员,暂时跳过
- // 实际应该对比不同会员等级的配额差异
- });
- it('年付套餐价格计算', async () => {
- if (!authToken) return;
- // 查询月付和年付价格
- const res = await apiGet('/api/payment/plans');
- expect(res.code).toBe(0);
- const plans = res.data?.plans || [];
- const monthlyPlan = plans.find((p: any) => p.period === 'monthly');
- const yearlyPlan = plans.find((p: any) => p.period === 'yearly');
- if (monthlyPlan && yearlyPlan) {
- // 年付价格应该是月付的 10 倍左右(通常有折扣)
- expect(yearlyPlan.amount).toBeGreaterThan(monthlyPlan.amount);
- }
- });
- });
- describe('Step 4: 配额超额处理', () => {
- it('超额时返回正确错误码', async () => {
- if (!authToken) return;
- // 尝试超额使用(通过生成超长音频)
- const res = await apiPost('/api/tts/generate', {
- text: 'A'.repeat(100000),
- voiceId: 'Cherry',
- });
- // 应该返回配额不足或类似错误
- expect(res.code).toBeDefined();
- });
- it('超额后配额正确更新', async () => {
- if (!authToken) return;
- // 获取超额前配额
- const beforeRes = await apiGet('/api/auth/user-info');
- const usageBefore = beforeRes.data?.dailyUsage || 0;
- // 尝试生成音频(可能会超额)
- await apiPost('/api/tts/generate', {
- text: '测试超额处理',
- voiceId: 'Cherry',
- });
- // 获取超额后配额
- const afterRes = await apiGet('/api/auth/user-info');
- const usageAfter = afterRes.data?.dailyUsage || 0;
- // 使用量应该增加了
- expect(usageAfter).toBeGreaterThanOrEqual(usageBefore);
- });
- });
- describe('Step 5: 套餐切换', () => {
- it('当前套餐信息包含订阅类型', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/auth/user-info');
- expect(res.code).toBe(0);
- // 应该包含订阅相关信息
- expect(res.data).toHaveProperty('memberLevel');
- });
- it('订阅记录可查询', async () => {
- if (!authToken) return;
- const res = await apiGet('/api/payment/orders');
- expect(res.code).toBe(0);
- expect(Array.isArray(res.data?.list)).toBe(true);
- });
- });
- });
|