Текстовый файл из учебного комплекта, не свидетельство установленного runtime. Вернуться к учебнику · Исходный файл
1 import { beforeEach, describe, expect, it, vi } from "vitest"; 2 3 import type { AppConfig } from "../config/appConfig"; 4 import type { AssistantElements } from "../ui/elements"; 5 import type { AudioState } from "../audio/audioState"; 6 import { startMic, stopMic } from "../audio/mic"; 7 import { createEnergyVad } from "../audio/vad"; 8 import { startWaveforms } from "../ui/waves"; 9 import { negotiate } from "./negotiate"; 10 import { connectSession, isConnected } from "./session"; 11 12 vi.mock("../audio/mic", () => ({ 13 startMic: vi.fn(), 14 stopMic: vi.fn(), 15 })); 16 vi.mock("../audio/vad", () => ({ createEnergyVad: vi.fn() })); 17 vi.mock("../ui/waves", () => ({ startWaveforms: vi.fn() })); 18 vi.mock("./negotiate", () => ({ negotiate: vi.fn() })); 19 20 const config = { 21 webrtc: { 22 iceServers: [], 23 iceCandidatePoolSize: 0, 24 bundlePolicy: "max-bundle", 25 rtcpMuxPolicy: "require", 26 }, 27 } as unknown as AppConfig; 28 29 const audio = { 30 vadEnabled: true, 31 vadThreshold: -55, 32 } as AudioState; 33 34 describe("connectSession", () => { 35 const micTrack = {} as MediaStreamTrack; 36 const micStream = { 37 getAudioTracks: () => [micTrack], 38 } as unknown as MediaStream; 39 const sender = { replaceTrack: vi.fn() } as unknown as RTCRtpSender; 40 const peer = { 41 addTrack: vi.fn(() => sender), 42 close: vi.fn(), 43 ontrack: null, 44 }; 45 const vad = { track: {} as MediaStreamTrack, stop: vi.fn() }; 46 const waves = { stop: vi.fn() }; 47 48 beforeEach(() => { 49 vi.clearAllMocks(); 50 class FakePeerConnection { 51 constructor() { 52 return peer; 53 } 54 } 55 vi.stubGlobal("RTCPeerConnection", FakePeerConnection); 56 vi.mocked(startMic).mockResolvedValue(micStream); 57 vi.mocked(createEnergyVad).mockReturnValue(vad); 58 vi.mocked(startWaveforms).mockReturnValue(waves); 59 vi.mocked(negotiate).mockRejectedValue(new Error("signaling failed")); 60 }); 61 62 it("releases all resources when negotiation fails", async () => { 63 await expect( 64 connectSession( 65 config, 66 {} as AssistantElements, 67 audio, 68 vi.fn(), 69 ), 70 ).rejects.toThrow("signaling failed"); 71 72 expect(vad.stop).toHaveBeenCalledOnce(); 73 expect(waves.stop).toHaveBeenCalledOnce(); 74 expect(stopMic).toHaveBeenCalledWith(micStream); 75 expect(peer.close).toHaveBeenCalledOnce(); 76 expect(isConnected()).toBe(false); 77 }); 78 });