mirror of https://github.com/home-assistant/core
277 lines
8.4 KiB
Python
277 lines
8.4 KiB
Python
"""Tests for the BSB-Lan climate platform."""
|
|
|
|
from datetime import timedelta
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
from bsblan import BSBLANError
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
import pytest
|
|
from syrupy.assertion import SnapshotAssertion
|
|
|
|
from homeassistant.components.climate import (
|
|
ATTR_HVAC_MODE,
|
|
ATTR_PRESET_MODE,
|
|
DOMAIN as CLIMATE_DOMAIN,
|
|
PRESET_ECO,
|
|
PRESET_NONE,
|
|
SERVICE_SET_HVAC_MODE,
|
|
SERVICE_SET_PRESET_MODE,
|
|
SERVICE_SET_TEMPERATURE,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, Platform
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
import homeassistant.helpers.entity_registry as er
|
|
|
|
from . import setup_with_selected_platforms
|
|
|
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
|
|
|
ENTITY_ID = "climate.bsb_lan"
|
|
|
|
|
|
async def test_celsius_fahrenheit(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
snapshot: SnapshotAssertion,
|
|
entity_registry: er.EntityRegistry,
|
|
) -> None:
|
|
"""Test Celsius and Fahrenheit temperature units."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
|
|
|
|
|
async def test_climate_entity_properties(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
snapshot: SnapshotAssertion,
|
|
entity_registry: er.EntityRegistry,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test the climate entity properties."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
|
|
|
# Test target_temperature
|
|
mock_target_temp = MagicMock()
|
|
mock_target_temp.value = 23.5
|
|
mock_bsblan.state.return_value.target_temperature = mock_target_temp
|
|
|
|
freezer.tick(timedelta(minutes=1))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state.attributes["temperature"] == 23.5
|
|
|
|
# Test hvac_mode
|
|
mock_hvac_mode = MagicMock()
|
|
mock_hvac_mode.value = HVACMode.AUTO
|
|
mock_bsblan.state.return_value.hvac_mode = mock_hvac_mode
|
|
|
|
freezer.tick(timedelta(minutes=1))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state.state == HVACMode.AUTO
|
|
|
|
# Test preset_mode
|
|
mock_hvac_mode.value = PRESET_ECO
|
|
|
|
freezer.tick(timedelta(minutes=1))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state.attributes["preset_mode"] == PRESET_ECO
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mode",
|
|
[HVACMode.HEAT, HVACMode.AUTO, HVACMode.OFF],
|
|
)
|
|
async def test_async_set_hvac_mode(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
mode: HVACMode,
|
|
) -> None:
|
|
"""Test setting HVAC mode via service call."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
# Call the service to set HVAC mode
|
|
await hass.services.async_call(
|
|
domain=CLIMATE_DOMAIN,
|
|
service=SERVICE_SET_HVAC_MODE,
|
|
service_data={ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: mode},
|
|
blocking=True,
|
|
)
|
|
|
|
# Assert that the thermostat method was called
|
|
mock_bsblan.thermostat.assert_called_once_with(hvac_mode=mode)
|
|
mock_bsblan.thermostat.reset_mock()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("hvac_mode", "preset_mode"),
|
|
[
|
|
(HVACMode.AUTO, PRESET_ECO),
|
|
(HVACMode.AUTO, PRESET_NONE),
|
|
],
|
|
)
|
|
async def test_async_set_preset_mode_succes(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
hvac_mode: HVACMode,
|
|
preset_mode: str,
|
|
) -> None:
|
|
"""Test setting preset mode via service call."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
# patch hvac_mode
|
|
mock_hvac_mode = MagicMock()
|
|
mock_hvac_mode.value = hvac_mode
|
|
mock_bsblan.state.return_value.hvac_mode = mock_hvac_mode
|
|
|
|
# Attempt to set the preset mode
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: preset_mode},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("hvac_mode", "preset_mode"),
|
|
[
|
|
(
|
|
HVACMode.HEAT,
|
|
PRESET_ECO,
|
|
)
|
|
],
|
|
)
|
|
async def test_async_set_preset_mode_error(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
hvac_mode: HVACMode,
|
|
preset_mode: str,
|
|
) -> None:
|
|
"""Test setting preset mode via service call."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
# patch hvac_mode
|
|
mock_hvac_mode = MagicMock()
|
|
mock_hvac_mode.value = hvac_mode
|
|
mock_bsblan.state.return_value.hvac_mode = mock_hvac_mode
|
|
|
|
# Attempt to set the preset mode
|
|
error_message = "Preset mode can only be set when HVAC mode is set to 'auto'"
|
|
with pytest.raises(HomeAssistantError, match=error_message):
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: preset_mode},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("target_temp"),
|
|
[
|
|
(8.0), # Min temperature
|
|
(15.0), # Mid-range temperature
|
|
(20.0), # Max temperature
|
|
],
|
|
)
|
|
async def test_async_set_temperature(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
target_temp: float,
|
|
) -> None:
|
|
"""Test setting temperature via service call."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
await hass.services.async_call(
|
|
domain=CLIMATE_DOMAIN,
|
|
service=SERVICE_SET_TEMPERATURE,
|
|
service_data={ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: target_temp},
|
|
blocking=True,
|
|
)
|
|
# Assert that the thermostat method was called with the correct temperature
|
|
mock_bsblan.thermostat.assert_called_once_with(target_temperature=target_temp)
|
|
|
|
|
|
async def test_async_set_data(
|
|
hass: HomeAssistant,
|
|
mock_bsblan: AsyncMock,
|
|
mock_config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Test setting data via service calls."""
|
|
await setup_with_selected_platforms(hass, mock_config_entry, [Platform.CLIMATE])
|
|
|
|
# Test setting temperature
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_TEMPERATURE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 19},
|
|
blocking=True,
|
|
)
|
|
mock_bsblan.thermostat.assert_called_once_with(target_temperature=19)
|
|
mock_bsblan.thermostat.reset_mock()
|
|
|
|
# Test setting HVAC mode
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_HVAC_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
blocking=True,
|
|
)
|
|
mock_bsblan.thermostat.assert_called_once_with(hvac_mode=HVACMode.HEAT)
|
|
mock_bsblan.thermostat.reset_mock()
|
|
|
|
# Patch HVAC mode to AUTO
|
|
mock_hvac_mode = MagicMock()
|
|
mock_hvac_mode.value = HVACMode.AUTO
|
|
mock_bsblan.state.return_value.hvac_mode = mock_hvac_mode
|
|
|
|
# Test setting preset mode to ECO
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_ECO},
|
|
blocking=True,
|
|
)
|
|
mock_bsblan.thermostat.assert_called_once_with(hvac_mode=PRESET_ECO)
|
|
mock_bsblan.thermostat.reset_mock()
|
|
|
|
# Test setting preset mode to NONE
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_NONE},
|
|
blocking=True,
|
|
)
|
|
mock_bsblan.thermostat.assert_called_once()
|
|
mock_bsblan.thermostat.reset_mock()
|
|
|
|
# Test error handling
|
|
mock_bsblan.thermostat.side_effect = BSBLANError("Test error")
|
|
error_message = "An error occurred while updating the BSBLAN device"
|
|
with pytest.raises(HomeAssistantError, match=error_message):
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_TEMPERATURE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: 20},
|
|
blocking=True,
|
|
)
|