test-data.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * 测试数据工厂
  3. * 提供创建/清理测试数据的统一方法
  4. */
  5. import { apiPost, apiDelete, apiGet, apiPut } from './api-client';
  6. /** 已创建的测试资源追踪(测试结束后统一清理) */
  7. const createdResources: { type: string; id: string | number; cleanup: () => Promise<void> }[] = [];
  8. /** 注册需要清理的资源 */
  9. export function trackResource(type: string, id: string | number, cleanup: () => Promise<void>) {
  10. createdResources.push({ type, id, cleanup });
  11. }
  12. /** 获取所有待清理资源数量 */
  13. export function getTrackedCount(): number {
  14. return createdResources.length;
  15. }
  16. /** 清理所有已追踪的资源(倒序清理,先删子资源) */
  17. export async function cleanupAllResources() {
  18. console.log(` [cleanup] 清理 ${createdResources.length} 个测试资源...`);
  19. // 倒序清理
  20. const reversed = [...createdResources].reverse();
  21. for (const resource of reversed) {
  22. try {
  23. await resource.cleanup();
  24. } catch (e: any) {
  25. console.warn(` [cleanup] 清理失败 ${resource.type}#${resource.id}: ${e.message}`);
  26. }
  27. }
  28. createdResources.length = 0;
  29. }
  30. // ============ 用户相关 ============
  31. /** 测试手机号计数器 */
  32. let phoneCounter = 13800000000;
  33. /** 获取一个唯一的测试手机号 */
  34. function nextPhone(): string {
  35. phoneCounter++;
  36. return String(phoneCounter);
  37. }
  38. /** 注册并登录一个测试用户,返回 token */
  39. export async function createTestUser(): Promise<{ token: string; userId: string; phone: string }> {
  40. const phone = nextPhone();
  41. // 发送验证码
  42. const codeRes = await apiPost('/api/auth/send-code', { phone });
  43. const code = codeRes.data?.code || '123456';
  44. // 登录
  45. const loginRes = await apiPost('/api/auth/login', { phone, code });
  46. const token = loginRes.data?.token;
  47. const userId = loginRes.data?.user?.id || loginRes.data?.userId;
  48. if (!token) throw new Error(`创建测试用户失败: ${JSON.stringify(loginRes)}`);
  49. trackResource('user', userId, async () => {
  50. // 用户通常不直接删除,由数据库清理
  51. });
  52. return { token, userId: String(userId), phone };
  53. }
  54. // ============ 书籍相关 ============
  55. /** 创建测试书籍 */
  56. export async function createTestBook(token?: string): Promise<{ bookId: number }> {
  57. const res = await apiPost('/api/book-generator/langgraph/books', {
  58. title: `[自动化测试] 测试书籍 ${Date.now()}`,
  59. description: '由自动化测试创建的临时书籍',
  60. });
  61. const bookId = res.data?.id || res.data?.book?.id;
  62. if (!bookId) throw new Error(`创建测试书籍失败: ${JSON.stringify(res)}`);
  63. trackResource('book', bookId, async () => {
  64. await apiDelete(`/api/book-generator/langgraph/books/${bookId}`);
  65. });
  66. return { bookId };
  67. }
  68. // ============ 音频相关 ============
  69. /** 创建测试音频记录(不实际生成音频) */
  70. export async function createTestAudio(text?: string): Promise<{ audioId: string }> {
  71. const res = await apiPost('/api/tts/generate', {
  72. text: text || '[自动化测试] 测试文本',
  73. voiceId: 'Cherry',
  74. voiceParams: { speed: 1.0, pitch: 0, volume: 50 },
  75. });
  76. const audioId = res.data?.audioId || res.data?.id;
  77. if (!audioId) throw new Error(`创建测试音频失败: ${JSON.stringify(res)}`);
  78. trackResource('audio', audioId, async () => {
  79. // 音频记录通常不直接删除
  80. });
  81. return { audioId };
  82. }
  83. // ============ 视频相关 ============
  84. /** 创建测试视频项目 */
  85. export async function createTestVideoProject(): Promise<{ projectId: number }> {
  86. const res = await apiPost('/api/video/projects', {
  87. title: `[自动化测试] 视频项目 ${Date.now()}`,
  88. });
  89. const projectId = res.data?.id || res.data?.project?.id;
  90. if (!projectId) throw new Error(`创建测试视频项目失败: ${JSON.stringify(res)}`);
  91. trackResource('videoProject', projectId, async () => {
  92. await apiDelete(`/api/video/projects/${projectId}`);
  93. });
  94. return { projectId };
  95. }
  96. // ============ 专辑相关 ============
  97. /** 创建测试专辑 */
  98. export async function createTestAlbum(): Promise<{ albumId: number }> {
  99. const res = await apiPost('/api/book-generator/albums', {
  100. name: `[自动化测试] 专辑 ${Date.now()}`,
  101. description: '由自动化测试创建的临时专辑',
  102. });
  103. const albumId = res.data?.id || res.data?.album?.id;
  104. if (!albumId) throw new Error(`创建测试专辑失败: ${JSON.stringify(res)}`);
  105. trackResource('album', albumId, async () => {
  106. await apiDelete(`/api/book-generator/albums/${albumId}`);
  107. });
  108. return { albumId };
  109. }
  110. // ============ 播放列表相关 ============
  111. /** 创建测试播放列表 */
  112. export async function createTestPlaylist(): Promise<{ playlistId: number }> {
  113. const res = await apiPost('/api/playlists', {
  114. name: `[自动化测试] 播放列表 ${Date.now()}`,
  115. });
  116. const playlistId = res.data?.id || res.data?.playlist?.id;
  117. if (!playlistId) throw new Error(`创建测试播放列表失败: ${JSON.stringify(res)}`);
  118. trackResource('playlist', playlistId, async () => {
  119. await apiDelete(`/api/playlists/${playlistId}`);
  120. });
  121. return { playlistId };
  122. }
  123. // ============ 收藏相关 ============
  124. /** 收藏一个音频 */
  125. export async function createTestFavorite(audioId: string | number): Promise<void> {
  126. await apiPost('/api/favorites', { audioId: String(audioId) });
  127. trackResource('favorite', audioId, async () => {
  128. await apiDelete(`/api/favorites/${audioId}`);
  129. });
  130. }
  131. // ============ 评论相关 ============
  132. /** 创建测试评论 */
  133. export async function createTestComment(audioId: string | number, content?: string): Promise<{ commentId: number }> {
  134. const res = await apiPost('/api/comments', {
  135. audioId: String(audioId),
  136. content: content || '[自动化测试] 测试评论',
  137. });
  138. const commentId = res.data?.id || res.data?.comment?.id;
  139. if (!commentId) throw new Error(`创建测试评论失败: ${JSON.stringify(res)}`);
  140. trackResource('comment', commentId, async () => {
  141. await apiDelete(`/api/comments/${commentId}`);
  142. });
  143. return { commentId };
  144. }
  145. // ============ 草稿相关 ============
  146. /** 创建测试草稿 */
  147. export async function createTestDraft(): Promise<{ draftId: number }> {
  148. const res = await apiPost('/api/drafts', {
  149. type: 'tts',
  150. data: { text: '[自动化测试] 草稿内容', voiceId: 'Cherry' },
  151. });
  152. const draftId = res.data?.id || res.data?.draft?.id;
  153. if (!draftId) throw new Error(`创建测试草稿失败: ${JSON.stringify(res)}`);
  154. trackResource('draft', draftId, async () => {
  155. await apiDelete(`/api/drafts/${draftId}`);
  156. });
  157. return { draftId };
  158. }