subscription-flow.test.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * 订阅流程集成测试
  3. * 测试套餐切换→配额计算→超额完整流程
  4. */
  5. import { describe, it, expect, beforeAll } from 'vitest';
  6. import { apiGet, apiPost, setAuthToken, initHttpClient, createTestUser } from '../../integration/http-client';
  7. describe('订阅流程集成测试', () => {
  8. let authToken: string;
  9. let userId: string;
  10. beforeAll(async () => {
  11. try {
  12. const user = await createTestUser();
  13. authToken = user.token;
  14. userId = user.userId;
  15. setAuthToken(authToken);
  16. } catch (e) {
  17. console.log('创建测试用户失败,跳过部分测试');
  18. }
  19. });
  20. describe('Step 1: 套餐查询', () => {
  21. it('获取可用套餐列表', async () => {
  22. if (!authToken) return;
  23. const res = await apiGet('/api/payment/plans');
  24. expect(res.code).toBe(0);
  25. expect(Array.isArray(res.data?.plans)).toBe(true);
  26. expect(res.data?.plans.length).toBeGreaterThan(0);
  27. });
  28. it('获取单个套餐详情', async () => {
  29. if (!authToken) return;
  30. const res = await apiGet('/api/payment/plan/1');
  31. expect(res.code).toBe(0);
  32. expect(res.data?.name).toBeDefined();
  33. });
  34. it('获取不存在的套餐返回错误', async () => {
  35. if (!authToken) return;
  36. const res = await apiGet('/api/payment/plan/9999');
  37. expect(res.code).not.toBe(0);
  38. });
  39. });
  40. describe('Step 2: 当前用户订阅状态', () => {
  41. it('获取当前会员等级', async () => {
  42. if (!authToken) return;
  43. const res = await apiGet('/api/auth/user-info');
  44. expect(res.code).toBe(0);
  45. expect(res.data).toHaveProperty('memberLevel');
  46. // 新用户应该是免费会员 (memberLevel = 0)
  47. expect(res.data?.memberLevel).toBe(0);
  48. });
  49. it('获取每日配额信息', async () => {
  50. if (!authToken) return;
  51. const res = await apiGet('/api/auth/user-info');
  52. expect(res.code).toBe(0);
  53. // 应该包含配额相关信息
  54. expect(res.data).toHaveProperty('dailyUsage');
  55. });
  56. });
  57. describe('Step 3: 订阅配额计算', () => {
  58. it('免费版月配额正确', async () => {
  59. if (!authToken) return;
  60. const res = await apiGet('/api/auth/user-info');
  61. expect(res.code).toBe(0);
  62. const memberLevel = res.data?.memberLevel || 0;
  63. // 免费版配额应该是 0 或有限值
  64. if (memberLevel === 0) {
  65. // 免费版不应该有太多配额
  66. expect(res.data?.dailyUsage).toBeDefined();
  67. }
  68. });
  69. it('专业版月配额更高', async () => {
  70. // 这个测试需要先购买会员,暂时跳过
  71. // 实际应该对比不同会员等级的配额差异
  72. });
  73. it('年付套餐价格计算', async () => {
  74. if (!authToken) return;
  75. // 查询月付和年付价格
  76. const res = await apiGet('/api/payment/plans');
  77. expect(res.code).toBe(0);
  78. const plans = res.data?.plans || [];
  79. const monthlyPlan = plans.find((p: any) => p.period === 'monthly');
  80. const yearlyPlan = plans.find((p: any) => p.period === 'yearly');
  81. if (monthlyPlan && yearlyPlan) {
  82. // 年付价格应该是月付的 10 倍左右(通常有折扣)
  83. expect(yearlyPlan.amount).toBeGreaterThan(monthlyPlan.amount);
  84. }
  85. });
  86. });
  87. describe('Step 4: 配额超额处理', () => {
  88. it('超额时返回正确错误码', async () => {
  89. if (!authToken) return;
  90. // 尝试超额使用(通过生成超长音频)
  91. const res = await apiPost('/api/tts/generate', {
  92. text: 'A'.repeat(100000),
  93. voiceId: 'Cherry',
  94. });
  95. // 应该返回配额不足或类似错误
  96. expect(res.code).toBeDefined();
  97. });
  98. it('超额后配额正确更新', async () => {
  99. if (!authToken) return;
  100. // 获取超额前配额
  101. const beforeRes = await apiGet('/api/auth/user-info');
  102. const usageBefore = beforeRes.data?.dailyUsage || 0;
  103. // 尝试生成音频(可能会超额)
  104. await apiPost('/api/tts/generate', {
  105. text: '测试超额处理',
  106. voiceId: 'Cherry',
  107. });
  108. // 获取超额后配额
  109. const afterRes = await apiGet('/api/auth/user-info');
  110. const usageAfter = afterRes.data?.dailyUsage || 0;
  111. // 使用量应该增加了
  112. expect(usageAfter).toBeGreaterThanOrEqual(usageBefore);
  113. });
  114. });
  115. describe('Step 5: 套餐切换', () => {
  116. it('当前套餐信息包含订阅类型', async () => {
  117. if (!authToken) return;
  118. const res = await apiGet('/api/auth/user-info');
  119. expect(res.code).toBe(0);
  120. // 应该包含订阅相关信息
  121. expect(res.data).toHaveProperty('memberLevel');
  122. });
  123. it('订阅记录可查询', async () => {
  124. if (!authToken) return;
  125. const res = await apiGet('/api/payment/orders');
  126. expect(res.code).toBe(0);
  127. expect(Array.isArray(res.data?.list)).toBe(true);
  128. });
  129. });
  130. });