// packages/api-client/__tests__/transcribe.test.ts // transcribeAudio 함수 단위 및 통합 인터페이스 테스트 import { describe, it, expect, vi, beforeEach } from 'vitest' import { transcribeAudio } from '../src/transcribe' describe('transcribeAudio', () => { beforeEach(() => { vi.restoreAllMocks() }) it('Blob 입력 시 multipart/form-data로 /api/stt/transcribe를 호출하여 전사 결과를 반환한다', async () => { const mockAudioBlob = new Blob(['mock-audio-content'], { type: 'audio/webm' }) const mockResponse = { text: '안녕하세요, 클라우드 음성 전사 테스트입니다.', confidence: 0.99, language: 'ko', durationSeconds: 2.5, provider: 'groq', modelId: 'whisper-large-v3-turbo', latencyMs: 145, cost: 0.000021, } const fetchMock = vi.fn().mockResolvedValue({ ok: true, status: 200, json: async () => mockResponse, }) vi.stubGlobal('fetch', fetchMock) const result = await transcribeAudio({ audio: mockAudioBlob, language: 'ko', apiBaseUrl: 'http://localhost:5000', token: 'test-token', }) expect(fetchMock).toHaveBeenCalledTimes(1) const [url, options] = fetchMock.mock.calls[0] expect(url).toBe('http://localhost:5000/api/stt/transcribe') expect(options.method).toBe('POST') expect(options.headers['Authorization']).toBe('Bearer test-token') expect(options.body).toBeInstanceOf(FormData) expect(result.text).toBe('안녕하세요, 클라우드 음성 전사 테스트입니다.') expect(result.provider).toBe('groq') expect(result.durationSeconds).toBe(2.5) expect(result.latencyMs).toBe(145) }) it('Base64 문자열 입력 시 JSON 페이로드로 전송한다', async () => { const mockBase64 = 'UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAAAAA=' const mockResponse = { text: 'Base64 전사 성공', confidence: 0.98, language: 'ko', durationSeconds: 1.0, provider: 'openai', modelId: 'whisper-1', latencyMs: 320, cost: 0.0001, } const fetchMock = vi.fn().mockResolvedValue({ ok: true, status: 200, json: async () => mockResponse, }) vi.stubGlobal('fetch', fetchMock) const result = await transcribeAudio({ audio: mockBase64, language: 'ko', prompt: '의료 용어 가이드', apiBaseUrl: 'http://localhost:5000', }) expect(fetchMock).toHaveBeenCalledTimes(1) const [url, options] = fetchMock.mock.calls[0] expect(url).toBe('http://localhost:5000/api/stt/transcribe') expect(options.headers['Content-Type']).toBe('application/json') const body = JSON.parse(options.body) expect(body.audioBase64).toBe(mockBase64) expect(body.language).toBe('ko') expect(body.initialPrompt).toBe('의료 용어 가이드') expect(result.text).toBe('Base64 전사 성공') }) it('서버 응답이 4xx/5xx 실패 시 에러를 throw한다', async () => { vi.stubGlobal( 'fetch', vi.fn().mockResolvedValue({ ok: false, status: 500, text: async () => 'Internal STT Proxy Failure', }) ) await expect( transcribeAudio({ audio: new Blob(['data']), apiBaseUrl: 'http://localhost:5000', }) ).rejects.toThrow('STT transcription failed (500): Internal STT Proxy Failure') }) })