Files

313 lines
12 KiB
Python

"""Tests for the nexia sensor platform."""
from datetime import timedelta
import inspect
from unittest.mock import NonCallableMock
from freezegun.api import FrozenDateTimeFactory
from nexia.home import NexiaHome
from nexia.sensor import NexiaSensor
import pytest
from homeassistant.components.nexia.coordinator import (
DEFAULT_UPDATE_RATE as COORDINATOR_UPDATE_RATE,
)
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import PERCENTAGE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceRegistry
from homeassistant.helpers.entity_registry import EntityRegistry
from .conftest import setup_integration
from tests.common import async_fire_time_changed
async def test_create_sensors(hass: HomeAssistant, patch_nexia_home: NexiaHome) -> None:
"""Test creation of sensors."""
await setup_integration(hass, patch_nexia_home)
state = hass.states.get("sensor.nick_office_nick_office_temperature")
assert state is not None
assert round(float(state.state)) == 23
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"device_class": "temperature",
"friendly_name": "Nick Office Temperature",
"unit_of_measurement": UnitOfTemperature.CELSIUS,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.nick_office_nick_office_zone_setpoint_status")
assert state is not None
assert state.state == "Permanent Hold"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Nick Office Zone setpoint status",
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.nick_office_nick_office_zone_status")
assert state is not None
assert state.state == "Relieving Air"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Nick Office Zone status",
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_air_cleaner_mode")
assert state is not None
assert state.state == "auto"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Master Suite Air cleaner mode",
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_current_compressor_speed")
assert state is not None
assert round(float(state.state)) == 69
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Master Suite Current compressor speed",
"unit_of_measurement": PERCENTAGE,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_outdoor_temperature")
assert state is not None
assert round(float(state.state), 1) == 30.6
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"device_class": "temperature",
"friendly_name": "Master Suite Outdoor temperature",
"unit_of_measurement": UnitOfTemperature.CELSIUS,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_humidity")
assert state is not None
assert state.state == "52.0"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"device_class": "humidity",
"friendly_name": "Master Suite Humidity",
"unit_of_measurement": PERCENTAGE,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_requested_compressor_speed")
assert state is not None
assert state.state == "69.0"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Master Suite Requested compressor speed",
"unit_of_measurement": PERCENTAGE,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
state = hass.states.get("sensor.master_suite_system_status")
assert state is not None
assert state.state == "Cooling"
expected_attributes = {
"attribution": "Data provided by Trane Technologies",
"friendly_name": "Master Suite System status",
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
assert all(
state.attributes[key] == value for key, value in expected_attributes.items()
)
async def test_room_iq_sensor_disabled_by_default(
hass: HomeAssistant, patch_nexia_home: NonCallableMock[NexiaHome]
) -> None:
"""Test NexiaRoomIQSensor is disabled by default."""
await setup_integration(hass, patch_nexia_home)
assert patch_nexia_home.any_room_iq_monitors() is False
assert patch_nexia_home.update.await_count == 1
state = hass.states.get("sensor.zone3_zone3_roomiq_temperature")
assert state is None
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_room_iq_sensors(
hass: HomeAssistant,
patch_nexia_home: NonCallableMock[NexiaHome],
entity_registry: EntityRegistry,
device_registry: DeviceRegistry,
) -> None:
"""Test NexiaRoomIQSensor."""
await setup_integration(hass, patch_nexia_home)
assert patch_nexia_home.any_room_iq_monitors() is True
assert patch_nexia_home.update.await_count == 2
state = hass.states.get("sensor.zone3_zone3_roomiq_temperature")
assert state is not None
entry = entity_registry.async_get(state.entity_id)
device = device_registry.async_get(entry.device_id)
assert device is not None
assert device.model == "XL1050"
assert device.sw_version == "5.9.1"
assert state.state == "25.0"
assert state.attributes["device_class"] == SensorDeviceClass.TEMPERATURE
assert state.attributes["friendly_name"] == "Zone3 RoomIQ temperature"
assert state.attributes["unit_of_measurement"] == UnitOfTemperature.CELSIUS
state = hass.states.get("sensor.zone3_zone3_roomiq_humidity")
assert state is not None
assert state.state == "45"
assert state.attributes["device_class"] == SensorDeviceClass.HUMIDITY
assert state.attributes["friendly_name"] == "Zone3 RoomIQ humidity"
assert state.attributes["unit_of_measurement"] == PERCENTAGE
state = hass.states.get("sensor.zone3_zone3_roomiq_battery")
assert state is None
state = hass.states.get("sensor.upstairs_upstairs_roomiq_temperature")
assert state is not None
entry = entity_registry.async_get(state.entity_id)
device = device_registry.async_get(entry.device_id)
assert device is not None
assert device.model is None
assert device.sw_version is None
assert state.state == "22.5"
assert state.attributes["device_class"] == SensorDeviceClass.TEMPERATURE
assert state.attributes["friendly_name"] == "Upstairs RoomIQ temperature"
assert state.attributes["unit_of_measurement"] == UnitOfTemperature.CELSIUS
state = hass.states.get("sensor.upstairs_upstairs_roomiq_humidity")
assert state is not None
assert state.state == "45"
assert state.attributes["device_class"] == SensorDeviceClass.HUMIDITY
assert state.attributes["friendly_name"] == "Upstairs RoomIQ humidity"
assert state.attributes["unit_of_measurement"] == PERCENTAGE
state = hass.states.get("sensor.upstairs_upstairs_roomiq_battery")
assert state is not None
assert state.state == "93"
assert state.attributes["device_class"] == SensorDeviceClass.BATTERY
assert state.attributes["friendly_name"] == "Upstairs RoomIQ battery"
assert state.attributes["unit_of_measurement"] == PERCENTAGE
state = hass.states.get("sensor.downstairs_downstairs_roomiq_temperature")
assert state is not None
assert state.state == "unavailable"
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_any_room_iq_monitors(
hass: HomeAssistant, patch_nexia_home: NexiaHome
) -> None:
"""Test any_room_iq_monitors after unload."""
config_entry = await setup_integration(hass, patch_nexia_home)
assert patch_nexia_home.any_room_iq_monitors() is True
await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.NOT_LOADED
assert patch_nexia_home.any_room_iq_monitors() is False
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_room_iq_sensor_no_longer_present(
hass: HomeAssistant, patch_nexia_home: NexiaHome, freezer: FrozenDateTimeFactory
) -> None:
"""Test RoomIQ sensor no longer present."""
zone = patch_nexia_home.get_thermostat_by_id(2000004).get_zone_by_id(500)
get_item = zone.get_sensor_by_id.side_effect
zone.get_sensor_by_id.side_effect = KeyError
await setup_integration(hass, patch_nexia_home)
state = hass.states.get("sensor.upstairs_upstairs_roomiq_humidity")
assert state is not None
assert state.state == "unavailable"
def get_sensor_raise_from_native_value(sensor_id: int) -> NexiaSensor:
for caller_frame in inspect.stack():
if caller_frame.function == "native_value":
raise KeyError
return get_item(sensor_id)
# The state machine won't call NexiaRoomIQSensor.native_value() when unavailable, so only
# raise when called from native_value() & return something new to coordinator so it updates
zone.get_sensor_by_id.side_effect = get_sensor_raise_from_native_value
patch_nexia_home.update.return_value = {"key": "different value"}
freezer.tick(timedelta(seconds=COORDINATOR_UPDATE_RATE))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("sensor.upstairs_upstairs_roomiq_humidity")
assert state is not None
assert state.state == "unknown"
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_1_room_iq_sensor(
hass: HomeAssistant, patch_nexia_home: NexiaHome
) -> None:
"""Test one-RoomIQ sensor case."""
zone = patch_nexia_home.get_thermostat_by_id(2000003).get_zone_by_id(400)
assert len(zone.get_sensors()) == 1
await setup_integration(hass, patch_nexia_home)
state = hass.states.get("sensor.kitchen_kitchen_roomiq_temperature")
assert state is None