"""Die Felder aus device/state, die ninlight schon lange hat: Zeiten, Einschaltverhalten, Aufwecken - und die Uebergangszeit beim Schalten.""" from __future__ import annotations from typing import Any from unittest.mock import MagicMock from freezegun.api import FrozenDateTimeFactory from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON from homeassistant.core import HomeAssistant from homeassistant.exceptions import ServiceValidationError import pytest from pytest_homeassistant_custom_component.common import MockConfigEntry from tests.helpers import abfragen, entity_id_for @pytest.mark.parametrize( ("key", "wert", "grenze"), [("fade_in", 500, 10_000), ("fade_out", 500, 10_000), ("transition_default", 300, 60_000)], ) async def test_zeiten_zeigen_und_setzen( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock, key: str, wert: int, grenze: int, ) -> None: entity_id = entity_id_for(hass, "number", key) state = hass.states.get(entity_id) assert state.state == f"{float(wert)}" # Die Obergrenzen sind die der Firmware (nl_api_device.c); alles darueber # wiese sie mit 400 ab. assert state.attributes["max"] == grenze assert state.attributes["unit_of_measurement"] == "ms" await hass.services.async_call( "number", "set_value", {ATTR_ENTITY_ID: entity_id, "value": 1200}, blocking=True ) mock_client.set_state.assert_awaited_once_with(**{key: 1200}) @pytest.mark.parametrize("key", ["fade_in", "fade_out", "transition_default"]) async def test_zeiten_ueber_der_grenze_werden_abgelehnt( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock, key: str ) -> None: with pytest.raises(ServiceValidationError): await hass.services.async_call( "number", "set_value", {ATTR_ENTITY_ID: entity_id_for(hass, "number", key), "value": 60_001}, blocking=True, ) mock_client.set_state.assert_not_awaited() async def test_einschaltverhalten( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock ) -> None: entity_id = entity_id_for(hass, "select", "power_on_behaviour") state = hass.states.get(entity_id) assert state.state == "last" assert state.attributes["options"] == ["last", "on", "off"] await hass.services.async_call( "select", "select_option", {ATTR_ENTITY_ID: entity_id, "option": "off"}, blocking=True ) mock_client.set_state.assert_awaited_once_with(power_on_behaviour="off") assert hass.states.get(entity_id).state == "off" async def test_unbekanntes_einschaltverhalten_zeigt_nichts( hass: HomeAssistant, init_integration: MockConfigEntry, strip_state: dict[str, Any], freezer: FrozenDateTimeFactory, ) -> None: # Gemeint ist das Verhalten, nicht die Zeile Code: Home Assistant selbst # zeigt "unknown", sobald der Wert nicht in den Optionen steht. Die Pruefung # in der Entitaet ist derselbe Riemen doppelt - wie in ha-ninlight. strip_state["power_on_behaviour"] = "irgendwas" await abfragen(hass, freezer) assert hass.states.get(entity_id_for(hass, "select", "power_on_behaviour")).state == "unknown" async def test_aufwecken_bei_aenderung( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock ) -> None: entity_id = entity_id_for(hass, "switch", "wake_on_change") assert hass.states.get(entity_id).state == STATE_OFF await hass.services.async_call("switch", "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True) mock_client.set_state.assert_awaited_once_with(wake_on_change=True) assert hass.states.get(entity_id).state == STATE_ON await hass.services.async_call("switch", "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True) mock_client.set_state.assert_awaited_with(wake_on_change=False) @pytest.mark.parametrize( ("sekunden", "millisekunden"), [(0, 0), (2.5, 2500), (0.04, 40), (120, 60_000)] ) async def test_uebergangszeit_beim_einschalten( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock, sekunden: float, millisekunden: int, ) -> None: """HA rechnet in Sekunden, das Geraet in Millisekunden - und laengeres als 60 s weist es mit 400 ab, deshalb wird gekappt statt durchgereicht.""" await hass.services.async_call( "light", "turn_on", {ATTR_ENTITY_ID: entity_id_for(hass, "light", "light"), "transition": sekunden}, blocking=True, ) mock_client.set_state.assert_awaited_once_with(on=True, transition=millisekunden) async def test_uebergangszeit_beim_ausschalten( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock ) -> None: await hass.services.async_call( "light", "turn_off", {ATTR_ENTITY_ID: entity_id_for(hass, "light", "light"), "transition": 1.5}, blocking=True, ) mock_client.set_state.assert_awaited_once_with(on=False, transition=1500) async def test_ohne_uebergang_wird_kein_feld_geschickt( hass: HomeAssistant, init_integration: MockConfigEntry, mock_client: MagicMock ) -> None: """Sonst ueberschriebe jeder Schaltbefehl die Vorgabe des Geraets.""" await hass.services.async_call( "light", "turn_off", {ATTR_ENTITY_ID: entity_id_for(hass, "light", "light")}, blocking=True ) mock_client.set_state.assert_awaited_once_with(on=False) async def test_die_lichtentitaet_meldet_uebergaenge( hass: HomeAssistant, init_integration: MockConfigEntry ) -> None: state = hass.states.get(entity_id_for(hass, "light", "light")) assert state.attributes["supported_features"] == 32 # LightEntityFeature.TRANSITION