core/tests/components/tplink/test_siren.py
Steven B. c12fa34e33
Add support for tplink siren turn on parameters (#136642)
Add support for tplink siren parameters - Allow passing tone, volume, and duration for siren's play action.

---------

Co-authored-by: Teemu Rytilahti <tpr@iki.fi>
2025-01-27 21:27:29 +01:00

169 lines
4.8 KiB
Python

"""Tests for siren platform."""
from __future__ import annotations
from kasa import Device, Module
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.siren import (
ATTR_DURATION,
ATTR_TONE,
ATTR_VOLUME_LEVEL,
DOMAIN as SIREN_DOMAIN,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import _mocked_device, setup_platform_for_device, snapshot_platform
from tests.common import MockConfigEntry
ENTITY_ID = "siren.hub"
@pytest.fixture
async def mocked_hub(hass: HomeAssistant) -> Device:
"""Return mocked tplink hub with an alarm module."""
return _mocked_device(
alias="hub",
modules=[Module.Alarm],
device_type=Device.Type.Hub,
)
async def test_states(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
mocked_hub: Device,
) -> None:
"""Snapshot test."""
await setup_platform_for_device(hass, mock_config_entry, Platform.SIREN, mocked_hub)
await snapshot_platform(
hass, entity_registry, device_registry, snapshot, mock_config_entry.entry_id
)
async def test_turn_on_and_off(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mocked_hub: Device
) -> None:
"""Test that turn_on and turn_off services work as expected."""
await setup_platform_for_device(hass, mock_config_entry, Platform.SIREN, mocked_hub)
alarm_module = mocked_hub.modules[Module.Alarm]
await hass.services.async_call(
SIREN_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: [ENTITY_ID]},
blocking=True,
)
alarm_module.stop.assert_called()
await hass.services.async_call(
SIREN_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: [ENTITY_ID]},
blocking=True,
)
alarm_module.play.assert_called()
@pytest.mark.parametrize(
("max_volume", "volume_level", "expected_volume"),
[
pytest.param(3, 0.1, 1, id="smart-10%"),
pytest.param(3, 0.3, 1, id="smart-30%"),
pytest.param(3, 0.99, 3, id="smart-99%"),
pytest.param(3, 1, 3, id="smart-100%"),
pytest.param(10, 0.1, 1, id="smartcam-10%"),
pytest.param(10, 0.3, 3, id="smartcam-30%"),
pytest.param(10, 0.99, 10, id="smartcam-99%"),
pytest.param(10, 1, 10, id="smartcam-100%"),
],
)
async def test_turn_on_with_volume(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mocked_hub: Device,
max_volume: int,
volume_level: float,
expected_volume: int,
) -> None:
"""Test that turn_on volume parameters work as expected."""
alarm_module = mocked_hub.modules[Module.Alarm]
alarm_volume_feat = alarm_module.get_feature("alarm_volume")
assert alarm_volume_feat
alarm_volume_feat.maximum_value = max_volume
await setup_platform_for_device(hass, mock_config_entry, Platform.SIREN, mocked_hub)
await hass.services.async_call(
SIREN_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: [ENTITY_ID], ATTR_VOLUME_LEVEL: volume_level},
blocking=True,
)
alarm_module.play.assert_called_with(
volume=expected_volume, duration=None, sound=None
)
async def test_turn_on_with_duration_and_sound(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mocked_hub: Device,
) -> None:
"""Test that turn_on tone and duration parameters work as expected."""
alarm_module = mocked_hub.modules[Module.Alarm]
await setup_platform_for_device(hass, mock_config_entry, Platform.SIREN, mocked_hub)
await hass.services.async_call(
SIREN_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: [ENTITY_ID], ATTR_DURATION: 5, ATTR_TONE: "Foo"},
blocking=True,
)
alarm_module.play.assert_called_with(volume=None, duration=5, sound="Foo")
@pytest.mark.parametrize(("duration"), [0, 301])
async def test_turn_on_with_invalid_duration(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mocked_hub: Device,
duration: int,
) -> None:
"""Test that turn_on with invalid_duration raises an error."""
await setup_platform_for_device(hass, mock_config_entry, Platform.SIREN, mocked_hub)
msg = f"Invalid duration {duration} available: 1-300s"
with pytest.raises(ServiceValidationError, match=msg):
await hass.services.async_call(
SIREN_DOMAIN,
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: [ENTITY_ID],
ATTR_DURATION: duration,
},
blocking=True,
)