{"version":3,"sources":["../../../src/voice/room_io/_input.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n  AudioFrame,\n  type FrameProcessor,\n  type RemoteTrack,\n  type RemoteTrackPublication,\n  type Room,\n  RoomEvent,\n  TrackSource,\n} from '@livekit/rtc-node';\nimport { EventEmitter } from 'node:events';\nimport { ReadableStream, type ReadableStreamDefaultController } from 'node:stream/web';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { AgentInput } from '../io.js';\nimport { ParticipantAudioInputStream } from './_input.js';\n\nconst audioStreams = vi.hoisted(() => [] as ReadableStream<AudioFrame>[]);\nconst audioStreamLifecycle = vi.hoisted(() => [] as string[]);\n\nvi.mock('@livekit/rtc-node', async (importOriginal) => {\n  const actual = await importOriginal<Record<string, unknown>>();\n  return {\n    ...actual,\n    AudioStream: vi.fn(function MockAudioStream() {\n      audioStreamLifecycle.push('create');\n      const stream = audioStreams.shift();\n      if (!stream) {\n        throw new Error('No mock audio stream configured');\n      }\n      return stream;\n    }),\n  };\n});\n\nconst nextTick = () => new Promise<void>((resolve) => setImmediate(resolve));\n\nfunction createAudioStream(onCancel?: () => void | Promise<void>) {\n  let controller!: ReadableStreamDefaultController<AudioFrame>;\n  const stream = new ReadableStream<AudioFrame>({\n    start(streamController) {\n      controller = streamController;\n    },\n    cancel: onCancel,\n  });\n  return { stream, controller: () => controller };\n}\n\nfunction createFrame(value: number): AudioFrame {\n  return new AudioFrame(new Int16Array([value]), 24000, 1, 1);\n}\n\nfunction createParticipantInput(\n  frameProcessor?: FrameProcessor<AudioFrame>,\n  onCancel?: () => void | Promise<void>,\n) {\n  const source = createAudioStream(onCancel);\n  audioStreams.push(source.stream);\n\n  const track = {} as RemoteTrack;\n  const publication = {\n    sid: 'microphone-track',\n    source: TrackSource.SOURCE_MICROPHONE,\n    track: track as RemoteTrack | null,\n  } as RemoteTrackPublication;\n  const participant = {\n    identity: 'caller',\n    trackPublications: new Map([[publication.sid, publication]]),\n  };\n  const emitter = new EventEmitter();\n  const room = {\n    remoteParticipants: new Map([[participant.identity, participant]]),\n    on: vi.fn((event, listener) => emitter.on(event, listener)),\n    off: vi.fn((event, listener) => emitter.off(event, listener)),\n    emit: (event: RoomEvent, ...args: unknown[]) => emitter.emit(event, ...args),\n    listenerCount: (event: RoomEvent) => emitter.listenerCount(event),\n  };\n  const input = new ParticipantAudioInputStream({\n    room: room as unknown as Room,\n    sampleRate: 24000,\n    numChannels: 1,\n    noiseCancellation: frameProcessor,\n  });\n\n  return { input, participant, publication, room, source, track };\n}\n\ndescribe('ParticipantAudioInputStream', () => {\n  afterEach(() => {\n    audioStreams.length = 0;\n    audioStreamLifecycle.length = 0;\n    vi.clearAllMocks();\n  });\n\n  it('unregisters track listeners when closed', async () => {\n    const { input, room } = createParticipantInput();\n\n    expect(room.listenerCount(RoomEvent.TrackSubscribed)).toBe(1);\n    expect(room.listenerCount(RoomEvent.TrackUnsubscribed)).toBe(1);\n    expect(room.listenerCount(RoomEvent.TrackUnpublished)).toBe(1);\n\n    await input.close();\n\n    expect(room.listenerCount(RoomEvent.TrackSubscribed)).toBe(0);\n    expect(room.listenerCount(RoomEvent.TrackUnsubscribed)).toBe(0);\n    expect(room.listenerCount(RoomEvent.TrackUnpublished)).toBe(0);\n  });\n\n  it('replaces the concrete track for the same publication', async () => {\n    const { input, participant, publication, room, source, track } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    const reader = input.stream.getReader();\n    const replacement = createAudioStream();\n    const replacementTrack = {} as RemoteTrack;\n    audioStreams.push(replacement.stream);\n\n    publication.track = null;\n    room.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);\n    publication.track = replacementTrack;\n    room.emit(RoomEvent.TrackSubscribed, replacementTrack, publication, participant);\n\n    source.controller().enqueue(createFrame(1));\n    const replacementFrame = createFrame(2);\n    replacement.controller().enqueue(replacementFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: replacementFrame });\n\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('ignores duplicate subscribe events for the active track', async () => {\n    const { input, participant, publication, room, track } = createParticipantInput();\n    input.setParticipant(participant.identity);\n\n    room.emit(RoomEvent.TrackSubscribed, track, publication, participant);\n\n    expect(audioStreams).toHaveLength(0);\n    await input.close();\n  });\n\n  it('ignores a stale unsubscribe after a same-publication replacement', async () => {\n    const { input, participant, publication, room, track } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    const reader = input.stream.getReader();\n    const replacement = createAudioStream();\n    const replacementTrack = {} as RemoteTrack;\n    audioStreams.push(replacement.stream);\n\n    publication.track = replacementTrack;\n    room.emit(RoomEvent.TrackSubscribed, replacementTrack, publication, participant);\n    room.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);\n\n    const frame = createFrame(3);\n    replacement.controller().enqueue(frame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: frame });\n\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('cancels the superseded stream before starting replacement', async () => {\n    const onCancel = vi.fn(() => audioStreamLifecycle.push('cancel'));\n    const { input, participant, publication, room, source } = createParticipantInput(\n      undefined,\n      onCancel,\n    );\n    input.setParticipant(participant.identity);\n    const replacement = createAudioStream();\n    const replacementTrack = {} as RemoteTrack;\n    audioStreams.push(replacement.stream);\n\n    publication.track = replacementTrack;\n    room.emit(RoomEvent.TrackSubscribed, replacementTrack, publication, participant);\n\n    await vi.waitFor(() => expect(audioStreams).toHaveLength(0));\n    expect(onCancel).toHaveBeenCalledOnce();\n    await vi.waitFor(() => expect(source.stream.locked).toBe(false));\n    expect(audioStreamLifecycle).toEqual(['create', 'cancel', 'create']);\n\n    await input.close();\n  });\n\n  it('starts a replacement after the superseded stream errors', async () => {\n    const { input, participant, publication, room, source } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    const reader = input.stream.getReader();\n    const currentInput = Reflect.get(input, 'currentInput') as { pipe: Promise<void> };\n    const replacement = createAudioStream();\n    const replacementTrack = {} as RemoteTrack;\n    audioStreams.push(replacement.stream);\n\n    source.controller().error(new Error('source failed'));\n    await expect(currentInput.pipe).rejects.toThrow('source failed');\n\n    publication.track = replacementTrack;\n    room.emit(RoomEvent.TrackSubscribed, replacementTrack, publication, participant);\n\n    await vi.waitFor(() => expect(audioStreams).toHaveLength(0));\n    expect(audioStreamLifecycle).toEqual(['create', 'create']);\n    const replacementFrame = createFrame(4);\n    replacement.controller().enqueue(replacementFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: replacementFrame });\n\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('closes the active track on unsubscribe', async () => {\n    const { input, participant, publication, room, source, track } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    const reader = input.stream.getReader();\n\n    publication.track = null;\n    room.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);\n    source.controller().enqueue(createFrame(1));\n    await nextTick();\n\n    expect(Reflect.get(input, 'publication')).toBeNull();\n    expect(Reflect.get(input, 'track')).toBeNull();\n    expect(Reflect.get(input, 'multiStream').inputCount).toBe(0);\n\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('keeps an owned frame processor across track replacement and closes it once', async () => {\n    const frameProcessor = {\n      symbol: Symbol.for('lk.frame-processor'),\n      close: vi.fn(),\n    } as unknown as FrameProcessor<AudioFrame>;\n    const { input, participant, publication, room } = createParticipantInput(frameProcessor);\n    input.setParticipant(participant.identity);\n    const replacement = createAudioStream();\n    const replacementTrack = {} as RemoteTrack;\n    audioStreams.push(replacement.stream);\n\n    publication.track = replacementTrack;\n    room.emit(RoomEvent.TrackSubscribed, replacementTrack, publication, participant);\n\n    expect(frameProcessor.close).not.toHaveBeenCalled();\n    await input.close();\n    expect(frameProcessor.close).toHaveBeenCalledOnce();\n  });\n\n  it('drops frames while detached and resumes forwarding when attached', async () => {\n    const { input, participant, source } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    const agentInput = new AgentInput(() => {});\n    agentInput.audio = input;\n\n    const reader = input.stream.getReader();\n    const initialFrame = createFrame(1);\n    source.controller().enqueue(initialFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: initialFrame });\n\n    agentInput.setAudioEnabled(false);\n    source.controller().enqueue(createFrame(2));\n    await nextTick();\n\n    agentInput.setAudioEnabled(true);\n    const resumedFrame = createFrame(3);\n    source.controller().enqueue(resumedFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: resumedFrame });\n\n    source.controller().close();\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('gates a track subscribed after input is disabled', async () => {\n    const { input, participant, source } = createParticipantInput();\n    const onDetached = vi.spyOn(input, 'onDetached');\n    const agentInput = new AgentInput(() => {});\n    agentInput.setAudioEnabled(false);\n    agentInput.audio = input;\n\n    expect(onDetached).toHaveBeenCalledOnce();\n\n    input.setParticipant(participant.identity);\n    const reader = input.stream.getReader();\n    source.controller().enqueue(createFrame(1));\n    await nextTick();\n\n    agentInput.setAudioEnabled(true);\n    const attachedFrame = createFrame(2);\n    source.controller().enqueue(attachedFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: attachedFrame });\n\n    source.controller().close();\n    reader.releaseLock();\n    await input.close();\n  });\n\n  it('keeps mute when onDetached override omits attach-state updates', async () => {\n    const { input, participant, source } = createParticipantInput();\n    input.setParticipant(participant.identity);\n    // Simulate a subclass/wrapper that overrides the hook without updating gate state.\n    input.onDetached = () => {};\n\n    const agentInput = new AgentInput(() => {});\n    agentInput.audio = input;\n\n    const reader = input.stream.getReader();\n    const initialFrame = createFrame(1);\n    source.controller().enqueue(initialFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: initialFrame });\n\n    agentInput.setAudioEnabled(false);\n    source.controller().enqueue(createFrame(2));\n    await nextTick();\n\n    agentInput.setAudioEnabled(true);\n    const resumedFrame = createFrame(3);\n    source.controller().enqueue(resumedFrame);\n    await expect(reader.read()).resolves.toMatchObject({ done: false, value: resumedFrame });\n\n    source.controller().close();\n    reader.releaseLock();\n    await input.close();\n  });\n});\n"],"mappings":"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","names":[]}