Files
PBandDev-comfyui-ping/tests/python/test_sound_routes.py
T

303 lines
8.6 KiB
Python

import sys
from asyncio import run
from io import BytesIO
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(REPO_ROOT))
from comfyui_ping.routes import (
SOUND_CATALOG_ROUTE,
SOUND_FILE_ROUTE,
SOUND_UPLOAD_ROUTE,
attach_sound_routes,
build_sound_catalog_payload,
resolve_sound_path,
save_uploaded_sound,
)
from comfyui_ping.sounds import MAX_UPLOAD_BYTES
def test_build_sound_catalog_payload_returns_sound_list():
payload = build_sound_catalog_payload(["ping-success.wav", "custom.wav"])
assert payload == {
"sounds": [
{"name": "ping-success.wav"},
{"name": "custom.wav"},
],
}
def test_list_sounds_route_payload_returns_structured_catalog(tmp_path: Path):
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "legacy"
sounds_dir.mkdir()
(sounds_dir / "ping-success.wav").write_bytes(b"bundled")
(sounds_dir / "custom.wav").write_bytes(b"custom")
from comfyui_ping.routes import list_sounds_route_payload
payload = list_sounds_route_payload(
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
assert payload == {
"sounds": [
{"name": "custom.wav"},
{"name": "ping-success.wav"},
],
}
def test_resolve_sound_path_uses_flat_directory():
sounds_dir = REPO_ROOT / "sounds"
legacy_custom_dir = REPO_ROOT / "input" / "ping-unused-test"
custom_file = sounds_dir / "temp-flat-route-test.wav"
custom_file.write_bytes(b"custom")
try:
custom_path = resolve_sound_path(
filename="temp-flat-route-test.wav",
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
finally:
custom_file.unlink(missing_ok=True)
assert custom_path == custom_file
def test_list_sounds_route_payload_migrates_legacy_custom_uploads(tmp_path: Path):
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "input" / "ping"
sounds_dir.mkdir(parents=True)
legacy_custom_dir.mkdir(parents=True)
(sounds_dir / "ping-success.wav").write_bytes(b"bundled")
(legacy_custom_dir / "ringtone5.mp3").write_bytes(b"legacy")
from comfyui_ping.routes import list_sounds_route_payload
payload = list_sounds_route_payload(
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
assert payload == {
"sounds": [
{"name": "ping-success.wav"},
{"name": "ringtone5.mp3"},
],
}
assert (sounds_dir / "ringtone5.mp3").read_bytes() == b"legacy"
assert (legacy_custom_dir / "ringtone5.mp3").exists() is False
def test_list_sounds_route_payload_skips_duplicate_legacy_files(
tmp_path: Path,
):
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "input" / "ping"
sounds_dir.mkdir(parents=True)
legacy_custom_dir.mkdir(parents=True)
(sounds_dir / "ping-ringtone.wav").write_bytes(b"bundled")
(legacy_custom_dir / "ping-ringtone.wav").write_bytes(b"legacy")
from comfyui_ping.routes import list_sounds_route_payload
payload = list_sounds_route_payload(
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
assert payload == {
"sounds": [{"name": "ping-ringtone.wav"}],
}
assert (sounds_dir / "ping-ringtone.wav").read_bytes() == b"bundled"
assert (legacy_custom_dir / "ping-ringtone.wav").exists() is False
def test_save_uploaded_sound_rejects_invalid_extension(tmp_path: Path):
try:
save_uploaded_sound(
filename="not-a-sound.txt",
data=b"bad",
sounds_dir=tmp_path,
legacy_custom_dir=tmp_path / "legacy",
)
except ValueError as exc:
assert str(exc) == "Invalid audio file format"
else:
raise AssertionError("save_uploaded_sound should reject invalid extensions")
def test_save_uploaded_sound_rejects_oversized_file(tmp_path: Path):
try:
save_uploaded_sound(
filename="too-large.wav",
data=b"0" * (MAX_UPLOAD_BYTES + 1),
sounds_dir=tmp_path / "sounds",
legacy_custom_dir=tmp_path / "legacy",
)
except ValueError as exc:
assert str(exc) == "Sound file exceeds 10 MiB limit"
else:
raise AssertionError("save_uploaded_sound should reject oversized files")
def test_save_uploaded_sound_rejects_existing_filename(tmp_path: Path):
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "legacy"
sounds_dir.mkdir()
(sounds_dir / "ping-success.wav").write_bytes(b"existing")
try:
save_uploaded_sound(
filename="ping-success.wav",
data=b"custom",
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
except ValueError as exc:
assert str(exc) == "Filename already exists"
else:
raise AssertionError("save_uploaded_sound should reject existing filenames")
def test_resolve_sound_path_rejects_non_files(tmp_path: Path):
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "legacy"
(sounds_dir / "ping-success.wav").mkdir(parents=True)
path = resolve_sound_path(
filename="ping-success.wav",
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
assert path is None
class FakeRoutes:
def __init__(self) -> None:
self.handlers: dict[tuple[str, str], object] = {}
def get(self, path: str):
def decorator(handler):
self.handlers[("GET", path)] = handler
return handler
return decorator
def post(self, path: str):
def decorator(handler):
self.handlers[("POST", path)] = handler
return handler
return decorator
class FakeWeb:
class HTTPNotFound(Exception):
pass
class Response:
def __init__(
self,
*,
payload: object | None = None,
path: Path | None = None,
status: int = 200,
) -> None:
self.payload = payload
self.path = path
self.status = status
@staticmethod
def json_response(payload: object, status: int = 200) -> "FakeWeb.Response":
return FakeWeb.Response(payload=payload, status=status)
@staticmethod
def FileResponse(path: Path) -> "FakeWeb.Response":
return FakeWeb.Response(path=path, status=200)
class FakeUploadField:
def __init__(self, *, filename: str, data: bytes) -> None:
self.filename = filename
self.file = BytesIO(data)
class FakeRequest:
def __init__(
self,
*,
post_data: dict[str, object] | None = None,
match_info: dict[str, str] | None = None,
) -> None:
self._post_data = post_data or {}
self.match_info = match_info or {}
async def post(self) -> dict[str, object]:
return self._post_data
def test_attach_sound_routes_registers_live_handlers(tmp_path: Path):
routes = FakeRoutes()
sounds_dir = tmp_path / "sounds"
legacy_custom_dir = tmp_path / "legacy"
sounds_dir.mkdir()
(sounds_dir / "ping-success.wav").write_bytes(b"bundled")
attach_sound_routes(
routes=routes,
web_module=FakeWeb,
sounds_dir=sounds_dir,
legacy_custom_dir=legacy_custom_dir,
)
assert ("GET", SOUND_CATALOG_ROUTE) in routes.handlers
assert ("GET", SOUND_FILE_ROUTE) in routes.handlers
assert ("POST", SOUND_UPLOAD_ROUTE) in routes.handlers
list_handler = routes.handlers[("GET", SOUND_CATALOG_ROUTE)]
list_response = run(list_handler(FakeRequest()))
assert list_response.payload == {
"sounds": [{"name": "ping-success.wav"}]
}
upload_handler = routes.handlers[("POST", SOUND_UPLOAD_ROUTE)]
upload_response = run(
upload_handler(
FakeRequest(
post_data={
"file": FakeUploadField(
filename="custom.wav",
data=b"custom",
)
}
)
)
)
assert upload_response.status == 201
assert upload_response.payload == {
"sounds": [
{"name": "custom.wav"},
{"name": "ping-success.wav"},
]
}
serve_handler = routes.handlers[("GET", SOUND_FILE_ROUTE)]
serve_response = run(
serve_handler(
FakeRequest(
match_info={
"filename": "custom.wav",
}
)
)
)
assert serve_response.path == sounds_dir / "custom.wav"