mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 16:36:08 +01:00
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Joostlek <joostlek@outlook.com>
210 lines
6.6 KiB
Python
210 lines
6.6 KiB
Python
"""Tests for ZoneMinder camera entities."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import timedelta
|
|
from unittest.mock import MagicMock, PropertyMock, patch
|
|
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
|
|
from homeassistant.components.camera import CameraState
|
|
from homeassistant.components.zoneminder.const import DOMAIN
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from .conftest import create_mock_monitor, create_mock_zm_client
|
|
|
|
from tests.common import async_fire_time_changed
|
|
|
|
|
|
async def _setup_zm_with_cameras(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
config: dict,
|
|
monitors: list,
|
|
freezer: FrozenDateTimeFactory,
|
|
verify_ssl: bool = True,
|
|
) -> None:
|
|
"""Set up ZM component with camera platform and given monitors."""
|
|
mock_zoneminder_client.get_monitors.return_value = monitors
|
|
type(mock_zoneminder_client).verify_ssl = PropertyMock(return_value=verify_ssl)
|
|
|
|
assert await async_setup_component(hass, DOMAIN, config)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
# Camera uses setup_platform (sync), add camera platform explicitly
|
|
assert await async_setup_component(
|
|
hass,
|
|
"camera",
|
|
{"camera": [{"platform": DOMAIN}]},
|
|
)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
# Trigger first poll to update entity state
|
|
freezer.tick(timedelta(seconds=60))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
|
|
async def test_one_camera_per_monitor(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
two_monitors: list,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test one camera entity is created per monitor."""
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, two_monitors, freezer
|
|
)
|
|
|
|
states = hass.states.async_all("camera")
|
|
assert len(states) == 2
|
|
|
|
|
|
async def test_camera_entity_name(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test camera entity name matches monitor name."""
|
|
monitors = [create_mock_monitor(name="Front Door")]
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, monitors, freezer
|
|
)
|
|
|
|
state = hass.states.get("camera.front_door")
|
|
assert state is not None
|
|
assert state.name == "Front Door"
|
|
|
|
|
|
async def test_camera_recording_state(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test camera recording state reflects monitor is_recording."""
|
|
monitors = [
|
|
create_mock_monitor(name="Recording Cam", is_recording=True, is_available=True)
|
|
]
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, monitors, freezer
|
|
)
|
|
|
|
state = hass.states.get("camera.recording_cam")
|
|
assert state is not None
|
|
assert state.state == CameraState.RECORDING
|
|
|
|
|
|
async def test_camera_idle_state(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test camera idle state when not recording."""
|
|
monitors = [
|
|
create_mock_monitor(name="Idle Cam", is_recording=False, is_available=True)
|
|
]
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, monitors, freezer
|
|
)
|
|
|
|
state = hass.states.get("camera.idle_cam")
|
|
assert state is not None
|
|
assert state.state == CameraState.IDLE
|
|
|
|
|
|
async def test_camera_unavailable_state(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test camera unavailable state tracking."""
|
|
monitors = [create_mock_monitor(name="Offline Cam", is_available=False)]
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, monitors, freezer
|
|
)
|
|
|
|
state = hass.states.get("camera.offline_cam")
|
|
assert state is not None
|
|
assert state.state == "unavailable"
|
|
|
|
|
|
async def test_no_monitors_raises_platform_not_ready(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
) -> None:
|
|
"""Test PlatformNotReady raised when no monitors returned."""
|
|
mock_zoneminder_client.get_monitors.return_value = []
|
|
|
|
assert await async_setup_component(hass, DOMAIN, single_server_config)
|
|
await hass.async_block_till_done()
|
|
await async_setup_component(
|
|
hass,
|
|
"camera",
|
|
{"camera": [{"platform": DOMAIN}]},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# No camera entities should exist
|
|
states = hass.states.async_all("camera")
|
|
assert len(states) == 0
|
|
|
|
|
|
async def test_multi_server_camera_creation(
|
|
hass: HomeAssistant,
|
|
multi_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test cameras created from multiple ZM servers."""
|
|
monitors1 = [create_mock_monitor(monitor_id=1, name="Front Door")]
|
|
monitors2 = [create_mock_monitor(monitor_id=2, name="Back Yard")]
|
|
|
|
clients = iter(
|
|
[
|
|
create_mock_zm_client(monitors=monitors1),
|
|
create_mock_zm_client(monitors=monitors2),
|
|
]
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.zoneminder.ZoneMinder",
|
|
side_effect=lambda *args, **kwargs: next(clients),
|
|
):
|
|
assert await async_setup_component(hass, DOMAIN, multi_server_config)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
assert await async_setup_component(
|
|
hass,
|
|
"camera",
|
|
{"camera": [{"platform": DOMAIN}]},
|
|
)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
freezer.tick(timedelta(seconds=60))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
states = hass.states.async_all("camera")
|
|
assert len(states) == 2
|
|
|
|
|
|
async def test_filter_urllib3_logging_called(
|
|
hass: HomeAssistant,
|
|
mock_zoneminder_client: MagicMock,
|
|
single_server_config: dict,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test filter_urllib3_logging() is called in setup_platform."""
|
|
monitors = [create_mock_monitor(name="Front Door")]
|
|
|
|
with patch(
|
|
"homeassistant.components.zoneminder.camera.filter_urllib3_logging"
|
|
) as mock_filter:
|
|
await _setup_zm_with_cameras(
|
|
hass, mock_zoneminder_client, single_server_config, monitors, freezer
|
|
)
|
|
|
|
mock_filter.assert_called_once()
|