From dea513cdbd413e359bcfdaf6321a246c03ba32c2 Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Tue, 27 Dec 2022 15:25:22 +0100 Subject: [PATCH] Add mysensors light tests (#84606) --- .coveragerc | 1 - tests/components/mysensors/conftest.py | 42 +++ .../mysensors/fixtures/dimmer_node_state.json | 22 ++ .../mysensors/fixtures/rgb_node_state.json | 23 ++ .../mysensors/fixtures/rgbw_node_state.json | 23 ++ tests/components/mysensors/test_light.py | 348 ++++++++++++++++++ 6 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 tests/components/mysensors/fixtures/dimmer_node_state.json create mode 100644 tests/components/mysensors/fixtures/rgb_node_state.json create mode 100644 tests/components/mysensors/fixtures/rgbw_node_state.json create mode 100644 tests/components/mysensors/test_light.py diff --git a/.coveragerc b/.coveragerc index 4a01d103091..5141b4a7086 100644 --- a/.coveragerc +++ b/.coveragerc @@ -798,7 +798,6 @@ omit = homeassistant/components/myq/light.py homeassistant/components/mysensors/__init__.py homeassistant/components/mysensors/climate.py - homeassistant/components/mysensors/const.py homeassistant/components/mysensors/cover.py homeassistant/components/mysensors/device.py homeassistant/components/mysensors/gateway.py diff --git a/tests/components/mysensors/conftest.py b/tests/components/mysensors/conftest.py index aee4fab932d..0dad228f6d4 100644 --- a/tests/components/mysensors/conftest.py +++ b/tests/components/mysensors/conftest.py @@ -218,6 +218,20 @@ def gps_sensor(gateway_nodes: dict[int, Sensor], gps_sensor_state: dict) -> Sens return node +@pytest.fixture(name="dimmer_node_state", scope="session") +def dimmer_node_state_fixture() -> dict: + """Load the dimmer node state.""" + return load_nodes_state("mysensors/dimmer_node_state.json") + + +@pytest.fixture +def dimmer_node(gateway_nodes: dict[int, Sensor], dimmer_node_state: dict) -> Sensor: + """Load the dimmer child node.""" + nodes = update_gateway_nodes(gateway_nodes, deepcopy(dimmer_node_state)) + node = nodes[1] + return node + + @pytest.fixture(name="power_sensor_state", scope="session") def power_sensor_state_fixture() -> dict: """Load the power sensor state.""" @@ -232,6 +246,34 @@ def power_sensor(gateway_nodes: dict[int, Sensor], power_sensor_state: dict) -> return node +@pytest.fixture(name="rgb_node_state", scope="session") +def rgb_node_state_fixture() -> dict: + """Load the rgb node state.""" + return load_nodes_state("mysensors/rgb_node_state.json") + + +@pytest.fixture +def rgb_node(gateway_nodes: dict[int, Sensor], rgb_node_state: dict) -> Sensor: + """Load the rgb child node.""" + nodes = update_gateway_nodes(gateway_nodes, deepcopy(rgb_node_state)) + node = nodes[1] + return node + + +@pytest.fixture(name="rgbw_node_state", scope="session") +def rgbw_node_state_fixture() -> dict: + """Load the rgbw node state.""" + return load_nodes_state("mysensors/rgbw_node_state.json") + + +@pytest.fixture +def rgbw_node(gateway_nodes: dict[int, Sensor], rgbw_node_state: dict) -> Sensor: + """Load the rgbw child node.""" + nodes = update_gateway_nodes(gateway_nodes, deepcopy(rgbw_node_state)) + node = nodes[1] + return node + + @pytest.fixture(name="energy_sensor_state", scope="session") def energy_sensor_state_fixture() -> dict: """Load the energy sensor state.""" diff --git a/tests/components/mysensors/fixtures/dimmer_node_state.json b/tests/components/mysensors/fixtures/dimmer_node_state.json new file mode 100644 index 00000000000..25d4c1b6132 --- /dev/null +++ b/tests/components/mysensors/fixtures/dimmer_node_state.json @@ -0,0 +1,22 @@ +{ + "1": { + "sensor_id": 1, + "children": { + "1": { + "id": 1, + "type": 4, + "description": "", + "values": { + "2": "0", + "3": "0" + } + } + }, + "type": 17, + "sketch_name": "Dimmer Node", + "sketch_version": "1.0", + "battery_level": 0, + "protocol_version": "2.3.2", + "heartbeat": 0 + } +} diff --git a/tests/components/mysensors/fixtures/rgb_node_state.json b/tests/components/mysensors/fixtures/rgb_node_state.json new file mode 100644 index 00000000000..4495b407fa3 --- /dev/null +++ b/tests/components/mysensors/fixtures/rgb_node_state.json @@ -0,0 +1,23 @@ +{ + "1": { + "sensor_id": 1, + "children": { + "1": { + "id": 1, + "type": 26, + "description": "", + "values": { + "2": "0", + "3": "0", + "40": "ffffff" + } + } + }, + "type": 17, + "sketch_name": "RGB Node", + "sketch_version": "1.0", + "battery_level": 0, + "protocol_version": "2.3.2", + "heartbeat": 0 + } +} diff --git a/tests/components/mysensors/fixtures/rgbw_node_state.json b/tests/components/mysensors/fixtures/rgbw_node_state.json new file mode 100644 index 00000000000..7b9349d2f7f --- /dev/null +++ b/tests/components/mysensors/fixtures/rgbw_node_state.json @@ -0,0 +1,23 @@ +{ + "1": { + "sensor_id": 1, + "children": { + "1": { + "id": 1, + "type": 27, + "description": "", + "values": { + "2": "0", + "3": "0", + "41": "ffffffff" + } + } + }, + "type": 17, + "sketch_name": "RGBW Node", + "sketch_version": "1.0", + "battery_level": 0, + "protocol_version": "2.3.2", + "heartbeat": 0 + } +} diff --git a/tests/components/mysensors/test_light.py b/tests/components/mysensors/test_light.py new file mode 100644 index 00000000000..e4cf160684d --- /dev/null +++ b/tests/components/mysensors/test_light.py @@ -0,0 +1,348 @@ +"""Provide tests for mysensors light platform.""" +from __future__ import annotations + +from collections.abc import Callable +from unittest.mock import MagicMock, call + +from mysensors.sensor import Sensor + +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_RGB_COLOR, + ATTR_RGBW_COLOR, + DOMAIN as LIGHT_DOMAIN, +) +from homeassistant.core import HomeAssistant + + +async def test_dimmer_node( + hass: HomeAssistant, + dimmer_node: Sensor, + receive_message: Callable[[str], None], + transport_write: MagicMock, +) -> None: + """Test a dimmer node.""" + entity_id = "light.dimmer_node_1_1" + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + # Test turn on + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;1\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;100\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 255 + + transport_write.reset_mock() + + # Test turn on brightness + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id, "brightness": 128}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;3;50\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;50\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 128 + + transport_write.reset_mock() + + # Test turn off + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_off", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;0\n") + + receive_message("1;1;1;0;2;0\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + +async def test_rgb_node( + hass: HomeAssistant, + rgb_node: Sensor, + receive_message: Callable[[str], None], + transport_write: MagicMock, +) -> None: + """Test a rgb node.""" + entity_id = "light.rgb_node_1_1" + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + # Test turn on + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;1\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;100\n") + receive_message("1;1;1;0;40;ffffff\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 255 + assert state.attributes[ATTR_RGB_COLOR] == (255, 255, 255) + + transport_write.reset_mock() + + # Test turn on brightness + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id, "brightness": 128}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;3;50\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;50\n") + receive_message("1;1;1;0;40;ffffff\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 128 + assert state.attributes[ATTR_RGB_COLOR] == (255, 255, 255) + + transport_write.reset_mock() + + # Test turn off + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_off", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;0\n") + + receive_message("1;1;1;0;2;0\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + transport_write.reset_mock() + + # Test turn on rgb + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id, ATTR_RGB_COLOR: (255, 0, 0)}, + blocking=True, + ) + + assert transport_write.call_count == 2 + assert transport_write.call_args_list[0] == call("1;1;1;1;2;1\n") + assert transport_write.call_args_list[1] == call("1;1;1;1;40;ff0000\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;50\n") + receive_message("1;1;1;0;40;ff0000\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 128 + assert state.attributes[ATTR_RGB_COLOR] == (255, 0, 0) + + +async def test_rgbw_node( + hass: HomeAssistant, + rgbw_node: Sensor, + receive_message: Callable[[str], None], + transport_write: MagicMock, +) -> None: + """Test a rgbw node.""" + entity_id = "light.rgbw_node_1_1" + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + # Test turn on + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;1\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;100\n") + receive_message("1;1;1;0;41;ffffffff\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 255 + assert state.attributes[ATTR_RGBW_COLOR] == (255, 255, 255, 255) + + transport_write.reset_mock() + + # Test turn on brightness + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id, "brightness": 128}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;3;50\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;50\n") + receive_message("1;1;1;0;41;ffffffff\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 128 + assert state.attributes[ATTR_RGBW_COLOR] == (255, 255, 255, 255) + + transport_write.reset_mock() + + # Test turn off + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_off", + {"entity_id": entity_id}, + blocking=True, + ) + + assert transport_write.call_count == 1 + assert transport_write.call_args == call("1;1;1;1;2;0\n") + + receive_message("1;1;1;0;2;0\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "off" + + transport_write.reset_mock() + + # Test turn on rgbw + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": entity_id, ATTR_RGBW_COLOR: (255, 0, 0, 0)}, + blocking=True, + ) + + assert transport_write.call_count == 2 + assert transport_write.call_args_list[0] == call("1;1;1;1;2;1\n") + assert transport_write.call_args_list[1] == call("1;1;1;1;41;ff000000\n") + + receive_message("1;1;1;0;2;1\n") + receive_message("1;1;1;0;3;50\n") + receive_message("1;1;1;0;41;ff000000\n") + # the integration adds multiple jobs to do the update currently + await hass.async_block_till_done() + await hass.async_block_till_done() + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + + assert state + assert state.state == "on" + assert state.attributes[ATTR_BRIGHTNESS] == 128 + assert state.attributes[ATTR_RGBW_COLOR] == (255, 0, 0, 0)