Files
core/tests/components/proxy/test_camera.py
T

85 lines
2.7 KiB
Python

"""Tests for the Camera Proxy camera platform."""
from collections.abc import AsyncGenerator
import io
from unittest.mock import AsyncMock, patch
from PIL import Image as PilImage
import pytest
from homeassistant.components.camera import Image, async_get_image
from homeassistant.components.proxy.camera import ProxyCamera
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
CROP_CONFIG = {
"platform": "proxy",
"entity_id": "camera.source",
"name": "Cropped",
"mode": "crop",
"max_image_width": 400,
"max_image_height": 225,
"max_stream_width": 400,
"max_stream_height": 225,
"image_left": 550,
"image_top": 90,
}
def _jpeg(width: int, height: int) -> Image:
buffer = io.BytesIO()
PilImage.new("RGB", (width, height)).save(buffer, "JPEG")
return Image("image/jpeg", buffer.getvalue())
def _size(content: bytes) -> tuple[int, int]:
return PilImage.open(io.BytesIO(content)).size
@pytest.fixture
async def setup_proxy(hass: HomeAssistant) -> AsyncGenerator[None]:
"""Set up a cropping proxy camera with no delay between stream frames."""
with patch.object(ProxyCamera, "_attr_frame_interval", 0):
assert await async_setup_component(hass, "camera", {"camera": CROP_CONFIG})
await hass.async_block_till_done()
yield
@pytest.mark.usefixtures("setup_proxy")
async def test_crop_image_after_small_frame(hass: HomeAssistant) -> None:
"""Test a frame smaller than the crop area does not break later crops."""
small = _jpeg(320, 180)
with patch(
"homeassistant.components.proxy.camera.async_get_image",
AsyncMock(side_effect=[small, _jpeg(1536, 576)]),
):
first = await async_get_image(hass, "camera.cropped")
second = await async_get_image(hass, "camera.cropped")
assert first.content == small.content
assert _size(second.content) == (400, 225)
@pytest.mark.usefixtures("setup_proxy")
async def test_crop_stream_after_small_frame(
hass: HomeAssistant, hass_client: ClientSessionGenerator
) -> None:
"""Test a small frame does not break the cropped MJPEG stream."""
client = await hass_client()
with patch(
"homeassistant.components.proxy.camera.async_get_image",
AsyncMock(side_effect=[_jpeg(320, 180), _jpeg(1536, 576), None]),
):
response = await client.get("/api/camera_proxy_stream/camera.cropped")
body = await response.read()
assert response.status == 200
frames = [
part.split(b"\r\n\r\n", 1)[1].rstrip(b"\r\n")
for part in body.split(b"--frameboundary\r\n")
if b"\r\n\r\n" in part
]
assert _size(frames[-1]) == (400, 225)