MediaRouter / tests /test_diarization_service.py
basyx's picture
Test diarization adapter headers and response validation
d772075 verified
Raw History Blame Contribute Delete
4.08 kB
from __future__ import annotations
import asyncio
from pathlib import Path
import httpx
import pytest
from app.core.exceptions import InputError, ProcessingError
from app.services.diarization_service import DiarizationService
def _service() -> DiarizationService:
return DiarizationService(None) # type: ignore[arg-type]
def _path(tmp_path: Path) -> Path:
path = tmp_path / "sample.wav"
path.write_bytes(b"sample")
return path
def test_speaker_bounds_validation(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("DIARIZATION_URL", "http://localhost:9000/diarize")
with pytest.raises(InputError, match="between 1 and 32"):
asyncio.run(_service().diarize(_path(tmp_path), "audio/wav", "sample.wav", min_speakers=0))
def test_speaker_bounds_order_validation(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("DIARIZATION_URL", "http://localhost:9000/diarize")
with pytest.raises(InputError, match="cannot exceed"):
asyncio.run(
_service().diarize(
_path(tmp_path), "audio/wav", "sample.wav", min_speakers=4, max_speakers=2
)
)
def test_adapter_forwards_auth_and_speaker_headers(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("DIARIZATION_URL", "https://example.test/v1/diarization/diarize")
monkeypatch.setenv("DIARIZATION_API_KEY", "secret")
captured: dict = {}
async def handler(request: httpx.Request) -> httpx.Response:
captured["headers"] = request.headers
captured["body"] = await request.aread()
return httpx.Response(
200,
json={
"spans": [
{"speaker": "SPEAKER_00", "start": 0.0, "end": 1.25},
{"speaker": "SPEAKER_01", "start": 1.25, "end": 2.5},
]
},
)
async def run() -> list[dict]:
service = _service()
transport = httpx.MockTransport(handler)
original = httpx.AsyncClient
class Client:
def __init__(self, *args, **kwargs):
self._client = original(transport=transport, *args, **kwargs)
async def __aenter__(self):
return await self._client.__aenter__()
async def __aexit__(self, *args):
return await self._client.__aexit__(*args)
monkeypatch.setattr(httpx, "AsyncClient", Client)
return await service.diarize(
_path(tmp_path), "audio/wav", "sample.wav", min_speakers=2, max_speakers=4
)
result = asyncio.run(run())
assert result[0]["speaker"] == "SPEAKER_00"
assert captured["headers"]["authorization"] == "Bearer secret"
assert captured["headers"]["x-min-speakers"] == "2"
assert captured["headers"]["x-max-speakers"] == "4"
assert captured["headers"]["x-filename"] == "sample.wav"
assert captured["body"] == b"sample"
def test_adapter_rejects_invalid_span(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("DIARIZATION_URL", "https://example.test/v1/diarization/diarize")
monkeypatch.setenv("DIARIZATION_API_KEY", "secret")
async def handler(request: httpx.Request) -> httpx.Response:
return httpx.Response(200, json={"spans": [{"speaker": "A", "start": 2, "end": 2}]})
async def run() -> None:
transport = httpx.MockTransport(handler)
original = httpx.AsyncClient
class Client:
def __init__(self, *args, **kwargs):
self._client = original(transport=transport, *args, **kwargs)
async def __aenter__(self):
return await self._client.__aenter__()
async def __aexit__(self, *args):
return await self._client.__aexit__(*args)
monkeypatch.setattr(httpx, "AsyncClient", Client)
await _service().diarize(_path(tmp_path), "audio/wav", "sample.wav")
with pytest.raises(ProcessingError, match="invalid span"):
asyncio.run(run())