13-douyinInsightManager.spec.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const modulePath = './13-douyinInsightManager';
  2. const transcriptionEnvNames = [
  3. 'TRANSCRIPTION_VOC_TOKEN',
  4. 'VOICE_TOKEN',
  5. 'OPENCLAW_VOC_TOKEN',
  6. 'VOC_TOKEN',
  7. 'VOC_SOCIAL_TOKEN',
  8. ];
  9. const originalNodeEnv = process.env.NODE_ENV;
  10. const originalTranscriptionEnv = Object.fromEntries(transcriptionEnvNames.map(name => [name, process.env[name]]));
  11. function loadHelpers(env = {}) {
  12. process.env.NODE_ENV = 'test';
  13. transcriptionEnvNames.forEach(name => {
  14. delete process.env[name];
  15. });
  16. Object.entries(env).forEach(([key, value]) => {
  17. process.env[key] = value;
  18. });
  19. delete require.cache[require.resolve(modulePath)];
  20. return require(modulePath).__test;
  21. }
  22. describe('douyinInsightManager transcript helpers', () => {
  23. afterAll(() => {
  24. process.env.NODE_ENV = originalNodeEnv;
  25. transcriptionEnvNames.forEach(name => {
  26. if (originalTranscriptionEnv[name] === undefined) {
  27. delete process.env[name];
  28. } else {
  29. process.env[name] = originalTranscriptionEnv[name];
  30. }
  31. });
  32. delete require.cache[require.resolve(modulePath)];
  33. });
  34. it('prefers Douyin video audio candidates before music fallback', () => {
  35. const helpers = loadHelpers();
  36. const payload = {
  37. data: {
  38. aweme_detail: {
  39. aweme_id: '7636915997076770089',
  40. video: {
  41. duration: 380,
  42. dynamic_audio_list: [
  43. {
  44. url_list: ['https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/dynamic-audio.m4a'],
  45. data_size: 1200,
  46. bit_rate: 64000,
  47. },
  48. ],
  49. play_addr: {
  50. url_list: ['https://v3-web.douyinvod.com/aweme/v1/play/video.mp4?mime_type=video_mp4'],
  51. },
  52. },
  53. music: {
  54. play_url: {
  55. url_list: ['https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/music-fallback.mp3'],
  56. },
  57. },
  58. },
  59. },
  60. };
  61. const detail = helpers.findAwemeDetail(payload);
  62. const selected = helpers.selectMediaCandidate(detail, 'audio');
  63. expect(selected.url).toContain('dynamic-audio.m4a');
  64. expect(selected.kind).toBe('audio');
  65. expect(selected.keyPath).toBe('video.dynamic_audio_list.0.url_list');
  66. expect(selected.durationMs).toBe(0);
  67. expect(helpers.durationFromDetail(detail)).toBe(380000);
  68. });
  69. it('decodes base64 encoded media urls from Douyin payloads', () => {
  70. const helpers = loadHelpers();
  71. const encoded = Buffer.from('https://v3-web.douyinvod.com/aweme/v1/play/video.mp4?mime_type=video_mp4').toString('base64');
  72. expect(helpers.decodeMaybeBase64Url(encoded)).toContain('/aweme/v1/play/video.mp4');
  73. });
  74. it('uses current Parse session token for transcription gateway auth', () => {
  75. const helpers = loadHelpers({ TRANSCRIPTION_VOC_TOKEN: 'global-token' });
  76. expect(helpers.transcriptionGatewayToken({ sessionToken: 'r:current-user-session' })).toBe('r:current-user-session');
  77. expect(helpers.transcriptTokenSource('r:current-user-session')).toBe('current_user_sessionToken');
  78. });
  79. it('can fall back to a configured transcription gateway token for diagnostics or legacy callers', () => {
  80. const helpers = loadHelpers({ TRANSCRIPTION_VOC_TOKEN: 'gateway-token' });
  81. expect(helpers.transcriptionGatewayToken()).toBe('gateway-token');
  82. expect(helpers.transcriptTokenSource('gateway-token')).toBe('TRANSCRIPTION_VOC_TOKEN');
  83. });
  84. it('reports no gateway token when neither session nor env token is available', () => {
  85. const helpers = loadHelpers();
  86. expect(helpers.transcriptionGatewayToken()).toBe('');
  87. expect(helpers.transcriptTokenSource('')).toBe('');
  88. });
  89. it('formats gateway unauthorized responses as operator-readable token errors', () => {
  90. const helpers = loadHelpers();
  91. expect(helpers.readGatewayError({ type: 'unauthorized' })).toContain('转写网关鉴权失败');
  92. });
  93. });