From ca469750ac85506bae907e4577c1c0a4fce23e4b Mon Sep 17 00:00:00 2001 From: alim4r <7687869+alim4r@users.noreply.github.com> Date: Thu, 27 Jan 2022 15:56:12 +0100 Subject: [PATCH] Prometheus tests simulate entities (#64916) --- tests/components/prometheus/test_init.py | 1088 +++++++++++++--------- 1 file changed, 666 insertions(+), 422 deletions(-) diff --git a/tests/components/prometheus/test_init.py b/tests/components/prometheus/test_init.py index d1b0c7c2130..096f1405168 100644 --- a/tests/components/prometheus/test_init.py +++ b/tests/components/prometheus/test_init.py @@ -2,24 +2,56 @@ from dataclasses import dataclass import datetime from http import HTTPStatus -import unittest.mock as mock +from unittest import mock import prometheus_client import pytest -from homeassistant.components import climate, counter, humidifier, lock, sensor -from homeassistant.components.demo.binary_sensor import DemoBinarySensor -from homeassistant.components.demo.light import DemoLight -from homeassistant.components.demo.number import DemoNumber -from homeassistant.components.demo.sensor import DemoSensor -import homeassistant.components.prometheus as prometheus +from homeassistant.components import ( + binary_sensor, + climate, + counter, + device_tracker, + humidifier, + input_boolean, + input_number, + light, + lock, + person, + prometheus, + sensor, + switch, +) +from homeassistant.components.climate.const import ( + ATTR_CURRENT_TEMPERATURE, + ATTR_HUMIDITY, + ATTR_HVAC_ACTION, + ATTR_TARGET_TEMP_HIGH, + ATTR_TARGET_TEMP_LOW, + CURRENT_HVAC_COOL, + CURRENT_HVAC_HEAT, +) +from homeassistant.components.humidifier.const import ATTR_AVAILABLE_MODES from homeassistant.components.sensor import SensorDeviceClass from homeassistant.const import ( + ATTR_BATTERY_LEVEL, + ATTR_DEVICE_CLASS, + ATTR_FRIENDLY_NAME, + ATTR_MODE, + ATTR_TEMPERATURE, + ATTR_UNIT_OF_MEASUREMENT, CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, CONTENT_TYPE_TEXT_PLAIN, DEGREE, ENERGY_KILO_WATT_HOUR, EVENT_STATE_CHANGED, + PERCENTAGE, + STATE_HOME, + STATE_LOCKED, + STATE_NOT_HOME, + STATE_OFF, + STATE_ON, + STATE_UNLOCKED, TEMP_CELSIUS, TEMP_FAHRENHEIT, ) @@ -39,6 +71,7 @@ class FilterTest: should_pass: bool +@pytest.fixture(name="client") async def setup_prometheus_client(hass, hass_client, namespace): """Initialize an hass_client with Prometheus component.""" # Reset registry @@ -71,28 +104,9 @@ async def generate_latest_metrics(client): return body -async def test_view_empty_namespace(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_view_empty_namespace(client, sensor_entities): """Test prometheus metrics view.""" - client = await setup_prometheus_client(hass, hass_client, "") - - sensor2 = DemoSensor( - None, - "Radio Energy", - 14, - SensorDeviceClass.POWER, - None, - ENERGY_KILO_WATT_HOUR, - None, - ) - sensor2.hass = hass - sensor2.entity_id = "sensor.radio_energy" - with mock.patch( - "homeassistant.util.dt.utcnow", - return_value=datetime.datetime(1970, 1, 2, tzinfo=dt_util.UTC), - ): - await sensor2.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert "# HELP python_info Python platform information" in body @@ -114,21 +128,9 @@ async def test_view_empty_namespace(hass, hass_client): ) -async def test_view_default_namespace(hass, hass_client): +@pytest.mark.parametrize("namespace", [None]) +async def test_view_default_namespace(client, sensor_entities): """Test prometheus metrics view.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, None) - - assert await async_setup_component( - hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]} - ) - await hass.async_block_till_done() - body = await generate_latest_metrics(client) assert "# HELP python_info Python platform information" in body @@ -144,73 +146,9 @@ async def test_view_default_namespace(hass, hass_client): ) -async def test_sensor_unit(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_sensor_unit(client, sensor_entities): """Test prometheus metrics for sensors with a unit.""" - client = await setup_prometheus_client(hass, hass_client, "") - - sensor1 = DemoSensor( - None, "Television Energy", 74, None, None, ENERGY_KILO_WATT_HOUR, None - ) - sensor1.hass = hass - sensor1.entity_id = "sensor.television_energy" - await sensor1.async_update_ha_state() - - sensor2 = DemoSensor( - None, - "Radio Energy", - 14, - SensorDeviceClass.POWER, - None, - ENERGY_KILO_WATT_HOUR, - None, - ) - sensor2.hass = hass - sensor2.entity_id = "sensor.radio_energy" - with mock.patch( - "homeassistant.util.dt.utcnow", - return_value=datetime.datetime(1970, 1, 2, tzinfo=dt_util.UTC), - ): - await sensor2.async_update_ha_state() - - sensor3 = DemoSensor( - None, - "Electricity price", - 0.123, - None, - None, - f"SEK/{ENERGY_KILO_WATT_HOUR}", - None, - ) - sensor3.hass = hass - sensor3.entity_id = "sensor.electricity_price" - await sensor3.async_update_ha_state() - - sensor4 = DemoSensor(None, "Wind Direction", 25, None, None, DEGREE, None) - sensor4.hass = hass - sensor4.entity_id = "sensor.wind_direction" - await sensor4.async_update_ha_state() - - sensor5 = DemoSensor( - None, - "SPS30 PM <1µm Weight concentration", - 3.7069, - None, - None, - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - None, - ) - sensor5.hass = hass - sensor5.entity_id = "sensor.sps30_pm_1um_weight_concentration" - await sensor5.async_update_ha_state() - - sensor6 = DemoSensor( - None, "Target temperature", 22.7, None, None, TEMP_CELSIUS, None - ) - sensor6.hass = hass - sensor6.entity_id = "input_number.target_temperature" - await sensor6.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -237,32 +175,10 @@ async def test_sensor_unit(hass, hass_client): 'friendly_name="SPS30 PM <1µm Weight concentration"} 3.7069' in body ) - assert ( - 'input_number_state_celsius{domain="input_number",' - 'entity="input_number.target_temperature",' - 'friendly_name="Target temperature"} 22.7' in body - ) - -async def test_sensor_without_unit(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_sensor_without_unit(client, sensor_entities): """Test prometheus metrics for sensors without a unit.""" - client = await setup_prometheus_client(hass, hass_client, "") - - sensor6 = DemoSensor(None, "Trend Gradient", 0.002, None, None, None, None) - sensor6.hass = hass - sensor6.entity_id = "sensor.trend_gradient" - await sensor6.async_update_ha_state() - - sensor7 = DemoSensor(None, "Text", "should_not_work", None, None, None, None) - sensor7.hass = hass - sensor7.entity_id = "sensor.text" - await sensor7.async_update_ha_state() - - sensor8 = DemoSensor(None, "Text Unit", "should_not_work", None, None, "Text", None) - sensor8.hass = hass - sensor8.entity_id = "sensor.text_unit" - await sensor8.async_update_ha_state() - body = await generate_latest_metrics(client) assert ( @@ -284,50 +200,9 @@ async def test_sensor_without_unit(hass, hass_client): ) -async def test_sensor_device_class(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_sensor_device_class(client, sensor_entities): """Test prometheus metrics for sensor with a device_class.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component(hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]}) - await hass.async_block_till_done() - - sensor1 = DemoSensor( - None, - "Fahrenheit", - 50, - SensorDeviceClass.TEMPERATURE, - None, - TEMP_FAHRENHEIT, - None, - ) - sensor1.hass = hass - sensor1.entity_id = "sensor.fahrenheit" - await sensor1.async_update_ha_state() - - sensor2 = DemoSensor( - None, - "Radio Energy", - 14, - SensorDeviceClass.POWER, - None, - ENERGY_KILO_WATT_HOUR, - None, - ) - sensor2.hass = hass - sensor2.entity_id = "sensor.radio_energy" - with mock.patch( - "homeassistant.util.dt.utcnow", - return_value=datetime.datetime(1970, 1, 2, tzinfo=dt_util.UTC), - ): - await sensor2.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -355,27 +230,9 @@ async def test_sensor_device_class(hass, hass_client): ) -async def test_input_number(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_input_number(client, input_number_entities): """Test prometheus metrics for input_number.""" - client = await setup_prometheus_client(hass, hass_client, "") - - number1 = DemoNumber(None, "Threshold", 5.2, None, False, 0, 10, 0.1) - number1.hass = hass - number1.entity_id = "input_number.threshold" - await number1.async_update_ha_state() - - number2 = DemoNumber(None, None, 60, None, False, 0, 100) - number2.hass = hass - number2.entity_id = "input_number.brightness" - number2._attr_name = None - await number2.async_update_ha_state() - - number3 = DemoSensor(None, "Retry count", 5, None, None, None, None) - number3.hass = hass - number3.entity_id = "input_number.retry_count" - await number3.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -391,25 +248,15 @@ async def test_input_number(hass, hass_client): ) assert ( - 'input_number_state{domain="input_number",' - 'entity="input_number.retry_count",' - 'friendly_name="Retry count"} 5.0' in body + 'input_number_state_celsius{domain="input_number",' + 'entity="input_number.target_temperature",' + 'friendly_name="Target temperature"} 22.7' in body ) -async def test_battery(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_battery(client, sensor_entities): """Test prometheus metrics for battery.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component(hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]}) - await hass.async_block_till_done() - body = await generate_latest_metrics(client) assert ( @@ -419,21 +266,9 @@ async def test_battery(hass, hass_client): ) -async def test_climate(hass, hass_client): - """Test prometheus metrics for climate.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component( - hass, climate.DOMAIN, {"climate": [{"platform": "demo"}]} - ) - - await hass.async_block_till_done() +@pytest.mark.parametrize("namespace", [""]) +async def test_climate(client, climate_entities): + """Test prometheus metrics for climate entities.""" body = await generate_latest_metrics(client) assert ( @@ -460,36 +295,10 @@ async def test_climate(hass, hass_client): 'friendly_name="Ecobee"} 24.0' in body ) - assert ( - 'climate_mode{domain="climate",' - 'entity="climate.heatpump",' - 'friendly_name="HeatPump",' - 'mode="heat"} 1.0' in body - ) - assert ( - 'climate_mode{domain="climate",' - 'entity="climate.heatpump",' - 'friendly_name="HeatPump",' - 'mode="off"} 0.0' in body - ) - - -async def test_humidifier(hass, hass_client): - """Test prometheus metrics for battery.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component( - hass, humidifier.DOMAIN, {"humidifier": [{"platform": "demo"}]} - ) - - await hass.async_block_till_done() +@pytest.mark.parametrize("namespace", [""]) +async def test_humidifier(client, humidifier_entities): + """Test prometheus metrics for humidifier entities.""" body = await generate_latest_metrics(client) assert ( @@ -518,29 +327,15 @@ async def test_humidifier(hass, hass_client): ) -async def test_attributes(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_attributes(client, switch_entities): """Test prometheus metrics for entity attributes.""" - client = await setup_prometheus_client(hass, hass_client, "") - - switch1 = DemoSensor(None, "Boolean", 74, None, None, None, None) - switch1.hass = hass - switch1.entity_id = "switch.boolean" - switch1._attr_extra_state_attributes = {"boolean": True} - await switch1.async_update_ha_state() - - switch2 = DemoSensor(None, "Number", 42, None, None, None, None) - switch2.hass = hass - switch2.entity_id = "switch.number" - switch2._attr_extra_state_attributes = {"Number": 10.2} - await switch2.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( 'switch_state{domain="switch",' 'entity="switch.boolean",' - 'friendly_name="Boolean"} 74.0' in body + 'friendly_name="Boolean"} 1.0' in body ) assert ( @@ -552,7 +347,7 @@ async def test_attributes(hass, hass_client): assert ( 'switch_state{domain="switch",' 'entity="switch.number",' - 'friendly_name="Number"} 42.0' in body + 'friendly_name="Number"} 0.0' in body ) assert ( @@ -562,21 +357,9 @@ async def test_attributes(hass, hass_client): ) -async def test_binary_sensor(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_binary_sensor(client, binary_sensor_entities): """Test prometheus metrics for binary_sensor.""" - client = await setup_prometheus_client(hass, hass_client, "") - - binary_sensor1 = DemoBinarySensor(None, "Door", True, None) - binary_sensor1.hass = hass - binary_sensor1.entity_id = "binary_sensor.door" - await binary_sensor1.async_update_ha_state() - - binary_sensor1 = DemoBinarySensor(None, "Window", False, None) - binary_sensor1.hass = hass - binary_sensor1.entity_id = "binary_sensor.window" - await binary_sensor1.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -592,21 +375,9 @@ async def test_binary_sensor(hass, hass_client): ) -async def test_input_boolean(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_input_boolean(client, input_boolean_entities): """Test prometheus metrics for input_boolean.""" - client = await setup_prometheus_client(hass, hass_client, "") - - input_boolean1 = DemoSensor(None, "Test", 1, None, None, None, None) - input_boolean1.hass = hass - input_boolean1.entity_id = "input_boolean.test" - await input_boolean1.async_update_ha_state() - - input_boolean2 = DemoSensor(None, "Helper", 0, None, None, None, None) - input_boolean2.hass = hass - input_boolean2.entity_id = "input_boolean.helper" - await input_boolean2.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -622,31 +393,9 @@ async def test_input_boolean(hass, hass_client): ) -async def test_light(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_light(client, light_entities): """Test prometheus metrics for lights.""" - client = await setup_prometheus_client(hass, hass_client, "") - - light1 = DemoSensor(None, "Desk", 1, None, None, None, None) - light1.hass = hass - light1.entity_id = "light.desk" - await light1.async_update_ha_state() - - light2 = DemoSensor(None, "Wall", 0, None, None, None, None) - light2.hass = hass - light2.entity_id = "light.wall" - await light2.async_update_ha_state() - - light3 = DemoLight(None, "TV", True, True, 255, None, None) - light3.hass = hass - light3.entity_id = "light.tv" - await light3.async_update_ha_state() - - light4 = DemoLight(None, "PC", True, True, 180, None, None) - light4.hass = hass - light4.entity_id = "light.pc" - await light4.async_update_ha_state() - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -674,19 +423,9 @@ async def test_light(hass, hass_client): ) -async def test_lock(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_lock(client, lock_entities): """Test prometheus metrics for lock.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component(hass, lock.DOMAIN, {"lock": [{"platform": "demo"}]}) - - await hass.async_block_till_done() body = await generate_latest_metrics(client) assert ( @@ -702,22 +441,9 @@ async def test_lock(hass, hass_client): ) -async def test_counter(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_counter(client, counter_entities): """Test prometheus metrics for counter.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component( - hass, counter.DOMAIN, {"counter": {"counter": {"initial": "2"}}} - ) - - await hass.async_block_till_done() - body = await generate_latest_metrics(client) assert ( @@ -727,24 +453,12 @@ async def test_counter(hass, hass_client): ) -async def test_renaming_entity_name(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_renaming_entity_name( + hass, registry, client, sensor_entities, climate_entities +): """Test renaming entity name.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - client = await setup_prometheus_client(hass, hass_client, "") - - assert await async_setup_component( - hass, climate.DOMAIN, {"climate": [{"platform": "demo"}]} - ) - - assert await async_setup_component( - hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]} - ) - - await hass.async_block_till_done() + data = {**sensor_entities, **climate_entities} body = await generate_latest_metrics(client) assert ( @@ -785,17 +499,29 @@ async def test_renaming_entity_name(hass, hass_client): 'friendly_name="HeatPump"} 0.0' in body ) - registry = entity_registry.async_get(hass) assert "sensor.outside_temperature" in registry.entities assert "climate.heatpump" in registry.entities registry.async_update_entity( - entity_id="sensor.outside_temperature", + entity_id=data["sensor_1"].entity_id, name="Outside Temperature Renamed", ) + set_state_with_entry( + hass, + data["sensor_1"], + 15.6, + {ATTR_FRIENDLY_NAME: "Outside Temperature Renamed"}, + ) registry.async_update_entity( - entity_id="climate.heatpump", + entity_id=data["climate_1"].entity_id, name="HeatPump Renamed", ) + data["climate_1_attributes"] = { + **data["climate_1_attributes"], + ATTR_FRIENDLY_NAME: "HeatPump Renamed", + } + set_state_with_entry( + hass, data["climate_1"], CURRENT_HVAC_HEAT, data["climate_1_attributes"] + ) await hass.async_block_till_done() body = await generate_latest_metrics(client) @@ -846,20 +572,12 @@ async def test_renaming_entity_name(hass, hass_client): ) -async def test_renaming_entity_id(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_renaming_entity_id( + hass, registry, client, sensor_entities, climate_entities +): """Test renaming entity id.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - client = await setup_prometheus_client(hass, hass_client, "") - - assert await async_setup_component( - hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]} - ) - - await hass.async_block_till_done() + data = {**sensor_entities, **climate_entities} body = await generate_latest_metrics(client) assert ( @@ -886,12 +604,15 @@ async def test_renaming_entity_id(hass, hass_client): 'friendly_name="Outside Humidity"} 1.0' in body ) - registry = entity_registry.async_get(hass) assert "sensor.outside_temperature" in registry.entities + assert "climate.heatpump" in registry.entities registry.async_update_entity( entity_id="sensor.outside_temperature", new_entity_id="sensor.outside_temperature_renamed", ) + set_state_with_entry( + hass, data["sensor_1"], 15.6, None, "sensor.outside_temperature_renamed" + ) await hass.async_block_till_done() body = await generate_latest_metrics(client) @@ -927,24 +648,12 @@ async def test_renaming_entity_id(hass, hass_client): ) -async def test_deleting_entity(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_deleting_entity( + hass, registry, client, sensor_entities, climate_entities +): """Test deleting a entity.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component( - hass, climate.DOMAIN, {"climate": [{"platform": "demo"}]} - ) - - assert await async_setup_component( - hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]} - ) - - await hass.async_block_till_done() + data = {**sensor_entities, **climate_entities} body = await generate_latest_metrics(client) assert ( @@ -985,11 +694,10 @@ async def test_deleting_entity(hass, hass_client): 'friendly_name="HeatPump"} 0.0' in body ) - registry = entity_registry.async_get(hass) assert "sensor.outside_temperature" in registry.entities assert "climate.heatpump" in registry.entities - registry.async_remove("sensor.outside_temperature") - registry.async_remove("climate.heatpump") + registry.async_remove(data["sensor_1"].entity_id) + registry.async_remove(data["climate_1"].entity_id) await hass.async_block_till_done() body = await generate_latest_metrics(client) @@ -1015,22 +723,12 @@ async def test_deleting_entity(hass, hass_client): ) -async def test_disabling_entity(hass, hass_client): +@pytest.mark.parametrize("namespace", [""]) +async def test_disabling_entity( + hass, registry, client, sensor_entities, climate_entities +): """Test disabling a entity.""" - assert await async_setup_component( - hass, - "conversation", - {}, - ) - client = await setup_prometheus_client(hass, hass_client, "") - - await async_setup_component( - hass, climate.DOMAIN, {"climate": [{"platform": "demo"}]} - ) - - assert await async_setup_component( - hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]} - ) + data = {**sensor_entities, **climate_entities} await hass.async_block_till_done() body = await generate_latest_metrics(client) @@ -1080,11 +778,10 @@ async def test_disabling_entity(hass, hass_client): 'friendly_name="HeatPump"} 0.0' in body ) - registry = entity_registry.async_get(hass) assert "sensor.outside_temperature" in registry.entities assert "climate.heatpump" in registry.entities registry.async_update_entity( - entity_id="sensor.outside_temperature", + entity_id=data["sensor_1"].entity_id, disabled_by="user", ) registry.async_update_entity(entity_id="climate.heatpump", disabled_by="user") @@ -1113,6 +810,553 @@ async def test_disabling_entity(hass, hass_client): ) +@pytest.fixture(name="registry") +def entity_registry_fixture(hass): + """Provide entity registry.""" + return entity_registry.async_get(hass) + + +@pytest.fixture(name="sensor_entities") +async def sensor_fixture(hass, registry): + """Simulate sensor entities.""" + data = {} + sensor_1 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_1", + unit_of_measurement=TEMP_CELSIUS, + original_device_class=SensorDeviceClass.TEMPERATURE, + suggested_object_id="outside_temperature", + original_name="Outside Temperature", + ) + sensor_1_attributes = {ATTR_BATTERY_LEVEL: 12} + set_state_with_entry(hass, sensor_1, 15.6, sensor_1_attributes) + data["sensor_1"] = sensor_1 + data["sensor_1_attributes"] = sensor_1_attributes + + sensor_2 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_2", + unit_of_measurement=PERCENTAGE, + original_device_class=SensorDeviceClass.HUMIDITY, + suggested_object_id="outside_humidity", + original_name="Outside Humidity", + ) + set_state_with_entry(hass, sensor_2, 54.0) + data["sensor_2"] = sensor_2 + + sensor_3 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_3", + unit_of_measurement=ENERGY_KILO_WATT_HOUR, + original_device_class=SensorDeviceClass.POWER, + suggested_object_id="radio_energy", + original_name="Radio Energy", + ) + with mock.patch( + "homeassistant.util.dt.utcnow", + return_value=datetime.datetime(1970, 1, 2, tzinfo=dt_util.UTC), + ): + set_state_with_entry(hass, sensor_3, 14) + data["sensor_3"] = sensor_3 + + sensor_4 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_4", + unit_of_measurement=ENERGY_KILO_WATT_HOUR, + suggested_object_id="television_energy", + original_name="Television Energy", + ) + set_state_with_entry(hass, sensor_4, 74) + data["sensor_4"] = sensor_4 + + sensor_5 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_5", + unit_of_measurement=f"SEK/{ENERGY_KILO_WATT_HOUR}", + suggested_object_id="electricity_price", + original_name="Electricity price", + ) + set_state_with_entry(hass, sensor_5, 0.123) + data["sensor_5"] = sensor_5 + + sensor_6 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_6", + unit_of_measurement=DEGREE, + suggested_object_id="wind_direction", + original_name="Wind Direction", + ) + set_state_with_entry(hass, sensor_6, 25) + data["sensor_6"] = sensor_6 + + sensor_7 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_7", + unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + suggested_object_id="sps30_pm_1um_weight_concentration", + original_name="SPS30 PM <1µm Weight concentration", + ) + set_state_with_entry(hass, sensor_7, 3.7069) + data["sensor_7"] = sensor_7 + + sensor_8 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_8", + suggested_object_id="trend_gradient", + original_name="Trend Gradient", + ) + set_state_with_entry(hass, sensor_8, 0.002) + data["sensor_8"] = sensor_8 + + sensor_9 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_9", + suggested_object_id="text", + original_name="Text", + ) + set_state_with_entry(hass, sensor_9, "should_not_work") + data["sensor_9"] = sensor_9 + + sensor_10 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_10", + unit_of_measurement="Text", + suggested_object_id="text_unit", + original_name="Text Unit", + ) + set_state_with_entry(hass, sensor_10, "should_not_work") + data["sensor_10"] = sensor_10 + + sensor_11 = registry.async_get_or_create( + domain=sensor.DOMAIN, + platform="test", + unique_id="sensor_11", + unit_of_measurement=TEMP_FAHRENHEIT, + original_device_class=SensorDeviceClass.TEMPERATURE, + suggested_object_id="fahrenheit", + original_name="Fahrenheit", + ) + set_state_with_entry(hass, sensor_11, 50) + data["sensor_11"] = sensor_11 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="climate_entities") +async def climate_fixture(hass, registry): + """Simulate climate entities.""" + data = {} + climate_1 = registry.async_get_or_create( + domain=climate.DOMAIN, + platform="test", + unique_id="climate_1", + unit_of_measurement=TEMP_CELSIUS, + suggested_object_id="heatpump", + original_name="HeatPump", + ) + climate_1_attributes = { + ATTR_TEMPERATURE: 20, + ATTR_CURRENT_TEMPERATURE: 25, + ATTR_HVAC_ACTION: CURRENT_HVAC_HEAT, + } + set_state_with_entry(hass, climate_1, CURRENT_HVAC_HEAT, climate_1_attributes) + data["climate_1"] = climate_1 + data["climate_1_attributes"] = climate_1_attributes + + climate_2 = registry.async_get_or_create( + domain=climate.DOMAIN, + platform="test", + unique_id="climate_2", + unit_of_measurement=TEMP_CELSIUS, + suggested_object_id="ecobee", + original_name="Ecobee", + ) + climate_2_attributes = { + ATTR_TEMPERATURE: 21, + ATTR_CURRENT_TEMPERATURE: 22, + ATTR_TARGET_TEMP_LOW: 21, + ATTR_TARGET_TEMP_HIGH: 24, + ATTR_HVAC_ACTION: CURRENT_HVAC_COOL, + } + set_state_with_entry(hass, climate_2, CURRENT_HVAC_HEAT, climate_2_attributes) + data["climate_2"] = climate_2 + data["climate_2_attributes"] = climate_2_attributes + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="humidifier_entities") +async def humidifier_fixture(hass, registry): + """Simulate humidifier entities.""" + data = {} + humidifier_1 = registry.async_get_or_create( + domain=humidifier.DOMAIN, + platform="test", + unique_id="humidifier_1", + original_device_class=humidifier.HumidifierDeviceClass.HUMIDIFIER, + suggested_object_id="humidifier", + original_name="Humidifier", + ) + humidifier_1_attributes = { + ATTR_HUMIDITY: 68, + } + set_state_with_entry(hass, humidifier_1, STATE_ON, humidifier_1_attributes) + data["humidifier_1"] = humidifier_1 + data["humidifier_1_attributes"] = humidifier_1_attributes + + humidifier_2 = registry.async_get_or_create( + domain=humidifier.DOMAIN, + platform="test", + unique_id="humidifier_2", + original_device_class=humidifier.HumidifierDeviceClass.DEHUMIDIFIER, + suggested_object_id="dehumidifier", + original_name="Dehumidifier", + ) + humidifier_2_attributes = { + ATTR_HUMIDITY: 54, + } + set_state_with_entry(hass, humidifier_2, STATE_ON, humidifier_2_attributes) + data["humidifier_2"] = humidifier_2 + data["humidifier_2_attributes"] = humidifier_2_attributes + + humidifier_3 = registry.async_get_or_create( + domain=humidifier.DOMAIN, + platform="test", + unique_id="humidifier_3", + suggested_object_id="hygrostat", + original_name="Hygrostat", + ) + humidifier_3_attributes = { + ATTR_HUMIDITY: 50, + ATTR_MODE: "home", + ATTR_AVAILABLE_MODES: ["home", "eco"], + } + set_state_with_entry(hass, humidifier_3, STATE_ON, humidifier_3_attributes) + data["humidifier_3"] = humidifier_3 + data["humidifier_3_attributes"] = humidifier_3_attributes + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="lock_entities") +async def lock_fixture(hass, registry): + """Simulate lock entities.""" + data = {} + lock_1 = registry.async_get_or_create( + domain=lock.DOMAIN, + platform="test", + unique_id="lock_1", + suggested_object_id="front_door", + original_name="Front Door", + ) + set_state_with_entry(hass, lock_1, STATE_LOCKED) + data["lock_1"] = lock_1 + + lock_2 = registry.async_get_or_create( + domain=lock.DOMAIN, + platform="test", + unique_id="lock_2", + suggested_object_id="kitchen_door", + original_name="Kitchen Door", + ) + set_state_with_entry(hass, lock_2, STATE_UNLOCKED) + data["lock_2"] = lock_2 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="input_number_entities") +async def input_number_fixture(hass, registry): + """Simulate input_number entities.""" + data = {} + input_number_1 = registry.async_get_or_create( + domain=input_number.DOMAIN, + platform="test", + unique_id="input_number_1", + suggested_object_id="threshold", + original_name="Threshold", + ) + set_state_with_entry(hass, input_number_1, 5.2) + data["input_number_1"] = input_number_1 + + input_number_2 = registry.async_get_or_create( + domain=input_number.DOMAIN, + platform="test", + unique_id="input_number_2", + suggested_object_id="brightness", + ) + set_state_with_entry(hass, input_number_2, 60) + data["input_number_2"] = input_number_2 + + input_number_3 = registry.async_get_or_create( + domain=input_number.DOMAIN, + platform="test", + unique_id="input_number_3", + suggested_object_id="target_temperature", + original_name="Target temperature", + unit_of_measurement=TEMP_CELSIUS, + ) + set_state_with_entry(hass, input_number_3, 22.7) + data["input_number_3"] = input_number_3 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="input_boolean_entities") +async def input_boolean_fixture(hass, registry): + """Simulate input_boolean entities.""" + data = {} + input_boolean_1 = registry.async_get_or_create( + domain=input_boolean.DOMAIN, + platform="test", + unique_id="input_boolean_1", + suggested_object_id="test", + original_name="Test", + ) + set_state_with_entry(hass, input_boolean_1, STATE_ON) + data["input_boolean_1"] = input_boolean_1 + + input_boolean_2 = registry.async_get_or_create( + domain=input_boolean.DOMAIN, + platform="test", + unique_id="input_boolean_2", + suggested_object_id="helper", + original_name="Helper", + ) + set_state_with_entry(hass, input_boolean_2, STATE_OFF) + data["input_boolean_2"] = input_boolean_2 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="binary_sensor_entities") +async def binary_sensor_fixture(hass, registry): + """Simulate binary_sensor entities.""" + data = {} + binary_sensor_1 = registry.async_get_or_create( + domain=binary_sensor.DOMAIN, + platform="test", + unique_id="binary_sensor_1", + suggested_object_id="door", + original_name="Door", + ) + set_state_with_entry(hass, binary_sensor_1, STATE_ON) + data["binary_sensor_1"] = binary_sensor_1 + + binary_sensor_2 = registry.async_get_or_create( + domain=binary_sensor.DOMAIN, + platform="test", + unique_id="binary_sensor_2", + suggested_object_id="window", + original_name="Window", + ) + set_state_with_entry(hass, binary_sensor_2, STATE_OFF) + data["binary_sensor_2"] = binary_sensor_2 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="light_entities") +async def light_fixture(hass, registry): + """Simulate light entities.""" + data = {} + light_1 = registry.async_get_or_create( + domain=light.DOMAIN, + platform="test", + unique_id="light_1", + suggested_object_id="desk", + original_name="Desk", + ) + set_state_with_entry(hass, light_1, STATE_ON) + data["light_1"] = light_1 + + light_2 = registry.async_get_or_create( + domain=light.DOMAIN, + platform="test", + unique_id="light_2", + suggested_object_id="wall", + original_name="Wall", + ) + set_state_with_entry(hass, light_2, STATE_OFF) + data["light_2"] = light_2 + + light_3 = registry.async_get_or_create( + domain=light.DOMAIN, + platform="test", + unique_id="light_3", + suggested_object_id="tv", + original_name="TV", + ) + light_3_attributes = {light.ATTR_BRIGHTNESS: 255} + set_state_with_entry(hass, light_3, STATE_ON, light_3_attributes) + data["light_3"] = light_3 + data["light_3_attributes"] = light_3_attributes + + light_4 = registry.async_get_or_create( + domain=light.DOMAIN, + platform="test", + unique_id="light_4", + suggested_object_id="pc", + original_name="PC", + ) + light_4_attributes = {light.ATTR_BRIGHTNESS: 180} + set_state_with_entry(hass, light_4, STATE_ON, light_4_attributes) + data["light_4"] = light_4 + data["light_4_attributes"] = light_4_attributes + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="switch_entities") +async def switch_fixture(hass, registry): + """Simulate switch entities.""" + data = {} + switch_1 = registry.async_get_or_create( + domain=switch.DOMAIN, + platform="test", + unique_id="switch_1", + suggested_object_id="boolean", + original_name="Boolean", + ) + switch_1_attributes = {"boolean": True} + set_state_with_entry(hass, switch_1, STATE_ON, switch_1_attributes) + data["switch_1"] = switch_1 + data["switch_1_attributes"] = switch_1_attributes + + switch_2 = registry.async_get_or_create( + domain=switch.DOMAIN, + platform="test", + unique_id="switch_2", + suggested_object_id="number", + original_name="Number", + ) + switch_2_attributes = {"Number": 10.2} + set_state_with_entry(hass, switch_2, STATE_OFF, switch_2_attributes) + data["switch_2"] = switch_2 + data["switch_2_attributes"] = switch_2_attributes + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="person_entities") +async def person_fixture(hass, registry): + """Simulate person entities.""" + data = {} + person_1 = registry.async_get_or_create( + domain=person.DOMAIN, + platform="test", + unique_id="person_1", + suggested_object_id="bob", + original_name="Bob", + ) + set_state_with_entry(hass, person_1, STATE_HOME) + data["person_1"] = person_1 + + person_2 = registry.async_get_or_create( + domain=person.DOMAIN, + platform="test", + unique_id="person_2", + suggested_object_id="alice", + original_name="Alice", + ) + set_state_with_entry(hass, person_2, STATE_NOT_HOME) + data["person_2"] = person_2 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="device_tracker_entities") +async def device_tracker_fixture(hass, registry): + """Simulate device_tracker entities.""" + data = {} + device_tracker_1 = registry.async_get_or_create( + domain=device_tracker.DOMAIN, + platform="test", + unique_id="device_tracker_1", + suggested_object_id="phone", + original_name="Phone", + ) + set_state_with_entry(hass, device_tracker_1, STATE_HOME) + data["device_tracker_1"] = device_tracker_1 + + device_tracker_2 = registry.async_get_or_create( + domain=device_tracker.DOMAIN, + platform="test", + unique_id="device_tracker_2", + suggested_object_id="watch", + original_name="Watch", + ) + set_state_with_entry(hass, device_tracker_2, STATE_NOT_HOME) + data["device_tracker_2"] = device_tracker_2 + + await hass.async_block_till_done() + return data + + +@pytest.fixture(name="counter_entities") +async def counter_fixture(hass, registry): + """Simulate counter entities.""" + data = {} + counter_1 = registry.async_get_or_create( + domain=counter.DOMAIN, + platform="test", + unique_id="counter_1", + suggested_object_id="counter", + ) + set_state_with_entry(hass, counter_1, 2) + data["counter_1"] = counter_1 + + await hass.async_block_till_done() + return data + + +def set_state_with_entry( + hass, + entry: entity_registry.RegistryEntry, + state, + additional_attributes=None, + new_entity_id=None, +): + """Set the state of an entity with an Entity Registry entry.""" + attributes = {} + + if entry.original_name: + attributes[ATTR_FRIENDLY_NAME] = entry.original_name + if entry.unit_of_measurement: + attributes[ATTR_UNIT_OF_MEASUREMENT] = entry.unit_of_measurement + if entry.original_device_class: + attributes[ATTR_DEVICE_CLASS] = entry.original_device_class + + if additional_attributes: + attributes = {**attributes, **additional_attributes} + + hass.states.async_set( + entity_id=new_entity_id if new_entity_id else entry.entity_id, + new_state=state, + attributes=attributes, + ) + + @pytest.fixture(name="mock_client") def mock_client_fixture(): """Mock the prometheus client."""