core/tests/components/gree/test_climate.py

931 lines
28 KiB
Python

"""Tests for gree component."""
from datetime import timedelta
from unittest.mock import DEFAULT as DEFAULT_MOCK, AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
from greeclimate.device import (
TEMP_MAX,
TEMP_MAX_F,
TEMP_MIN,
TEMP_MIN_F,
HorizontalSwing,
VerticalSwing,
)
from greeclimate.exceptions import DeviceNotBoundError, DeviceTimeoutError
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.climate import (
ATTR_FAN_MODE,
ATTR_HVAC_MODE,
ATTR_PRESET_MODE,
ATTR_SWING_MODE,
DOMAIN as CLIMATE_DOMAIN,
FAN_AUTO,
FAN_HIGH,
FAN_LOW,
FAN_MEDIUM,
PRESET_AWAY,
PRESET_BOOST,
PRESET_ECO,
PRESET_NONE,
PRESET_SLEEP,
SERVICE_SET_FAN_MODE,
SERVICE_SET_HVAC_MODE,
SERVICE_SET_PRESET_MODE,
SERVICE_SET_SWING_MODE,
SERVICE_SET_TEMPERATURE,
SWING_BOTH,
SWING_HORIZONTAL,
SWING_OFF,
SWING_VERTICAL,
HVACMode,
)
from homeassistant.components.gree.climate import (
FAN_MODES_REVERSE,
HVAC_MODES,
HVAC_MODES_REVERSE,
GreeClimateEntity,
)
from homeassistant.components.gree.const import (
DISCOVERY_SCAN_INTERVAL,
FAN_MEDIUM_HIGH,
FAN_MEDIUM_LOW,
UPDATE_INTERVAL,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_TEMPERATURE,
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
STATE_UNAVAILABLE,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import entity_registry as er
from .common import async_setup_gree, build_device_mock
from tests.common import async_fire_time_changed
ENTITY_ID = f"{CLIMATE_DOMAIN}.fake_device_1"
async def test_discovery_called_once(hass: HomeAssistant, discovery, device) -> None:
"""Test discovery is only ever called once."""
await async_setup_gree(hass)
assert discovery.call_count == 1
await async_setup_gree(hass)
assert discovery.call_count == 1
async def test_discovery_setup(hass: HomeAssistant, discovery, device) -> None:
"""Test setup of platform."""
MockDevice1 = build_device_mock(
name="fake-device-1", ipAddress="1.1.1.1", mac="aabbcc112233"
)
MockDevice2 = build_device_mock(
name="fake-device-2", ipAddress="2.2.2.2", mac="bbccdd223344"
)
discovery.return_value.mock_devices = [MockDevice1, MockDevice2]
device.side_effect = [MockDevice1, MockDevice2]
await async_setup_gree(hass)
await hass.async_block_till_done()
assert discovery.call_count == 1
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
async def test_discovery_setup_connection_error(
hass: HomeAssistant, discovery, device
) -> None:
"""Test gree integration is setup."""
MockDevice1 = build_device_mock(
name="fake-device-1", ipAddress="1.1.1.1", mac="aabbcc112233"
)
MockDevice1.bind = AsyncMock(side_effect=DeviceNotBoundError)
MockDevice1.update_state = AsyncMock(side_effect=DeviceNotBoundError)
discovery.return_value.mock_devices = [MockDevice1]
device.return_value = MockDevice1
await async_setup_gree(hass)
await hass.async_block_till_done()
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 1
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
async def test_discovery_after_setup(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Test gree devices don't change after multiple discoveries."""
MockDevice1 = build_device_mock(
name="fake-device-1", ipAddress="1.1.1.1", mac="aabbcc112233"
)
MockDevice1.bind = AsyncMock(side_effect=DeviceNotBoundError)
MockDevice2 = build_device_mock(
name="fake-device-2", ipAddress="2.2.2.2", mac="bbccdd223344"
)
MockDevice2.bind = AsyncMock(side_effect=DeviceTimeoutError)
discovery.return_value.mock_devices = [MockDevice1, MockDevice2]
device.side_effect = [MockDevice1, MockDevice2]
await async_setup_gree(hass) # Update 1
assert discovery.return_value.scan_count == 1
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
# rediscover the same devices shouldn't change anything
discovery.return_value.mock_devices = [MockDevice1, MockDevice2]
device.side_effect = [MockDevice1, MockDevice2]
freezer.tick(timedelta(seconds=DISCOVERY_SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert discovery.return_value.scan_count == 2
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
async def test_discovery_add_device_after_setup(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Test gree devices can be added after initial setup."""
MockDevice1 = build_device_mock(
name="fake-device-1", ipAddress="1.1.1.1", mac="aabbcc112233"
)
MockDevice1.bind = AsyncMock(side_effect=DeviceNotBoundError)
MockDevice2 = build_device_mock(
name="fake-device-2", ipAddress="2.2.2.2", mac="bbccdd223344"
)
MockDevice2.bind = AsyncMock(side_effect=DeviceTimeoutError)
discovery.return_value.mock_devices = [MockDevice1]
device.side_effect = [MockDevice1]
await async_setup_gree(hass) # Update 1
await async_setup_gree(hass)
await hass.async_block_till_done()
assert discovery.return_value.scan_count == 1
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 1
# rediscover the same devices shouldn't change anything
discovery.return_value.mock_devices = [MockDevice2]
device.side_effect = [MockDevice2]
freezer.tick(timedelta(seconds=DISCOVERY_SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert discovery.return_value.scan_count == 2
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
async def test_discovery_device_bind_after_setup(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Test gree devices can be added after a late device bind."""
MockDevice1 = build_device_mock(
name="fake-device-1", ipAddress="1.1.1.1", mac="aabbcc112233"
)
MockDevice1.bind = AsyncMock(side_effect=DeviceNotBoundError)
MockDevice1.update_state = AsyncMock(side_effect=DeviceNotBoundError)
discovery.return_value.mock_devices = [MockDevice1]
device.return_value = MockDevice1
await async_setup_gree(hass) # Update 1
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 1
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
# Now the device becomes available
MockDevice1.bind.side_effect = None
MockDevice1.update_state.side_effect = None
freezer.tick(timedelta(seconds=DISCOVERY_SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state.state != STATE_UNAVAILABLE
async def test_update_connection_failure(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Testing update hvac connection failure exception."""
device().update_state.side_effect = [
DEFAULT_MOCK,
DeviceTimeoutError,
DeviceTimeoutError,
]
await async_setup_gree(hass) # Update 1
async def run_update():
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
# Update 2
await run_update()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
# Update 3
await run_update()
# Update 4
await run_update()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
async def test_update_connection_send_failure_recovery(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Testing update hvac connection failure recovery."""
device().update_state.side_effect = [
DeviceTimeoutError,
DeviceTimeoutError,
DEFAULT_MOCK,
]
await async_setup_gree(hass) # Update 1
async def run_update():
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
await run_update() # Update 2
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
await run_update() # Update 3
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
async def test_update_unhandled_exception(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Testing update hvac connection unhandled response exception."""
device().update_state.side_effect = [DEFAULT_MOCK, Exception]
await async_setup_gree(hass)
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
async def test_send_command_device_timeout(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Test for sending power on command to the device with a device timeout."""
await async_setup_gree(hass)
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
device().push_state_update.side_effect = DeviceTimeoutError
# Send failure should not raise exceptions or change device state
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state != STATE_UNAVAILABLE
async def test_unresponsive_device(
hass: HomeAssistant, freezer: FrozenDateTimeFactory, discovery, device
) -> None:
"""Test for unresponsive device."""
await async_setup_gree(hass)
async def run_update():
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
# Update 2
await run_update()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
# Update 3, 4, 5
await run_update()
await run_update()
await run_update()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state == STATE_UNAVAILABLE
# Receiving update from device will reset the state to available again
device().device_state_updated("test")
await run_update()
state = hass.states.get(ENTITY_ID)
assert state.name == "fake-device-1"
assert state.state != STATE_UNAVAILABLE
async def test_send_power_on(hass: HomeAssistant, discovery, device) -> None:
"""Test for sending power on command to the device."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state == HVACMode.OFF
async def test_send_power_off_device_timeout(
hass: HomeAssistant, discovery, device
) -> None:
"""Test for sending power off command to the device with a device timeout."""
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: ENTITY_ID},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state == HVACMode.OFF
@pytest.mark.parametrize(
("units", "temperature"),
[(UnitOfTemperature.CELSIUS, 26), (UnitOfTemperature.FAHRENHEIT, 73)],
)
async def test_send_target_temperature(
hass: HomeAssistant, discovery, device, units, temperature
) -> None:
"""Test for sending target temperature command to the device."""
hass.config.units.temperature_unit = units
device().power = True
device().mode = HVAC_MODES_REVERSE.get(HVACMode.AUTO)
fake_device = device()
if units == UnitOfTemperature.FAHRENHEIT:
fake_device.temperature_units = 1
await async_setup_gree(hass)
# Make sure we're trying to test something that isn't the default
assert fake_device.current_temperature != temperature
hass.states.async_set(
ENTITY_ID,
"off",
{
ATTR_UNIT_OF_MEASUREMENT: units,
},
)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: temperature},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_TEMPERATURE) == temperature
assert state.state == HVAC_MODES.get(fake_device.mode)
# Reset config temperature_unit back to CELSIUS, required for
# additional tests outside this component.
hass.config.units.temperature_unit = UnitOfTemperature.CELSIUS
@pytest.mark.parametrize(
("temperature", "hvac_mode"),
[
(26, HVACMode.OFF),
(26, HVACMode.HEAT),
(26, HVACMode.COOL),
(26, HVACMode.AUTO),
(26, HVACMode.DRY),
(26, HVACMode.FAN_ONLY),
],
)
async def test_send_target_temperature_with_hvac_mode(
hass: HomeAssistant, discovery, device, temperature, hvac_mode
) -> None:
"""Test for sending target temperature command to the device alongside hvac mode."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{
ATTR_ENTITY_ID: ENTITY_ID,
ATTR_TEMPERATURE: temperature,
ATTR_HVAC_MODE: hvac_mode,
},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_TEMPERATURE) == temperature
assert state.state == hvac_mode
@pytest.mark.parametrize(
("units", "temperature"),
[
(UnitOfTemperature.CELSIUS, 25),
(UnitOfTemperature.FAHRENHEIT, 73),
(UnitOfTemperature.FAHRENHEIT, 74),
],
)
async def test_send_target_temperature_device_timeout(
hass: HomeAssistant, discovery, device, units, temperature
) -> None:
"""Test for sending target temperature command to the device with a device timeout."""
hass.config.units.temperature_unit = units
if units == UnitOfTemperature.FAHRENHEIT:
device().temperature_units = 1
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: temperature},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_TEMPERATURE) == temperature
# Reset config temperature_unit back to CELSIUS, required for additional tests outside this component.
hass.config.units.temperature_unit = UnitOfTemperature.CELSIUS
@pytest.mark.parametrize(
("units", "temperature"),
[
(UnitOfTemperature.CELSIUS, 25),
(UnitOfTemperature.FAHRENHEIT, 73),
(UnitOfTemperature.FAHRENHEIT, 74),
],
)
async def test_update_target_temperature(
hass: HomeAssistant, discovery, device, units, temperature
) -> None:
"""Test for updating target temperature from the device."""
hass.config.units.temperature_unit = units
if units == UnitOfTemperature.FAHRENHEIT:
device().temperature_units = 1
device().target_temperature = temperature
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_TEMPERATURE: temperature},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_TEMPERATURE) == temperature
# Reset config temperature_unit back to CELSIUS, required for additional tests outside this component.
hass.config.units.temperature_unit = UnitOfTemperature.CELSIUS
@pytest.mark.parametrize(
"preset", [PRESET_AWAY, PRESET_ECO, PRESET_SLEEP, PRESET_BOOST, PRESET_NONE]
)
async def test_send_preset_mode(hass: HomeAssistant, discovery, device, preset) -> None:
"""Test for sending preset mode command to the device."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: preset},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_PRESET_MODE) == preset
async def test_send_invalid_preset_mode(hass: HomeAssistant, discovery, device) -> None:
"""Test for sending preset mode command to the device."""
await async_setup_gree(hass)
with pytest.raises(ServiceValidationError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: "invalid"},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_PRESET_MODE) != "invalid"
@pytest.mark.parametrize(
"preset", [PRESET_AWAY, PRESET_ECO, PRESET_SLEEP, PRESET_BOOST, PRESET_NONE]
)
async def test_send_preset_mode_device_timeout(
hass: HomeAssistant, discovery, device, preset
) -> None:
"""Test for sending preset mode command to the device with a device timeout."""
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: preset},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_PRESET_MODE) == preset
@pytest.mark.parametrize(
"preset", [PRESET_AWAY, PRESET_ECO, PRESET_SLEEP, PRESET_BOOST, PRESET_NONE]
)
async def test_update_preset_mode(
hass: HomeAssistant, discovery, device, preset
) -> None:
"""Test for updating preset mode from the device."""
device().steady_heat = preset == PRESET_AWAY
device().power_save = preset == PRESET_ECO
device().sleep = preset == PRESET_SLEEP
device().turbo = preset == PRESET_BOOST
await async_setup_gree(hass)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_PRESET_MODE) == preset
@pytest.mark.parametrize(
"hvac_mode",
[
HVACMode.OFF,
HVACMode.AUTO,
HVACMode.COOL,
HVACMode.DRY,
HVACMode.FAN_ONLY,
HVACMode.HEAT,
],
)
async def test_send_hvac_mode(
hass: HomeAssistant, discovery, device, hvac_mode
) -> None:
"""Test for sending hvac mode command to the device."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: hvac_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state == hvac_mode
@pytest.mark.parametrize(
"hvac_mode",
[HVACMode.AUTO, HVACMode.COOL, HVACMode.DRY, HVACMode.FAN_ONLY, HVACMode.HEAT],
)
async def test_send_hvac_mode_device_timeout(
hass: HomeAssistant, discovery, device, hvac_mode
) -> None:
"""Test for sending hvac mode command to the device with a device timeout."""
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: hvac_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state == hvac_mode
@pytest.mark.parametrize(
"hvac_mode",
[
HVACMode.OFF,
HVACMode.AUTO,
HVACMode.COOL,
HVACMode.DRY,
HVACMode.FAN_ONLY,
HVACMode.HEAT,
],
)
async def test_update_hvac_mode(
hass: HomeAssistant, discovery, device, hvac_mode
) -> None:
"""Test for updating hvac mode from the device."""
device().power = hvac_mode != HVACMode.OFF
device().mode = HVAC_MODES_REVERSE.get(hvac_mode)
await async_setup_gree(hass)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.state == hvac_mode
@pytest.mark.parametrize(
"fan_mode",
[FAN_AUTO, FAN_LOW, FAN_MEDIUM_LOW, FAN_MEDIUM, FAN_MEDIUM_HIGH, FAN_HIGH],
)
async def test_send_fan_mode(hass: HomeAssistant, discovery, device, fan_mode) -> None:
"""Test for sending fan mode command to the device."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_FAN_MODE: fan_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_FAN_MODE) == fan_mode
async def test_send_invalid_fan_mode(hass: HomeAssistant, discovery, device) -> None:
"""Test for sending fan mode command to the device."""
await async_setup_gree(hass)
with pytest.raises(ServiceValidationError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_FAN_MODE: "invalid"},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_FAN_MODE) != "invalid"
@pytest.mark.parametrize(
"fan_mode",
[FAN_AUTO, FAN_LOW, FAN_MEDIUM_LOW, FAN_MEDIUM, FAN_MEDIUM_HIGH, FAN_HIGH],
)
async def test_send_fan_mode_device_timeout(
hass: HomeAssistant, discovery, device, fan_mode
) -> None:
"""Test for sending fan mode command to the device with a device timeout."""
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_FAN_MODE: fan_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_FAN_MODE) == fan_mode
@pytest.mark.parametrize(
"fan_mode",
[FAN_AUTO, FAN_LOW, FAN_MEDIUM_LOW, FAN_MEDIUM, FAN_MEDIUM_HIGH, FAN_HIGH],
)
async def test_update_fan_mode(
hass: HomeAssistant, discovery, device, fan_mode
) -> None:
"""Test for updating fan mode from the device."""
device().fan_speed = FAN_MODES_REVERSE.get(fan_mode)
await async_setup_gree(hass)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_FAN_MODE) == fan_mode
@pytest.mark.parametrize(
"swing_mode", [SWING_OFF, SWING_BOTH, SWING_VERTICAL, SWING_HORIZONTAL]
)
async def test_send_swing_mode(
hass: HomeAssistant, discovery, device, swing_mode
) -> None:
"""Test for sending swing mode command to the device."""
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_SWING_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_SWING_MODE: swing_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_SWING_MODE) == swing_mode
async def test_send_invalid_swing_mode(hass: HomeAssistant, discovery, device) -> None:
"""Test for sending swing mode command to the device."""
await async_setup_gree(hass)
with pytest.raises(ServiceValidationError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_SWING_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_SWING_MODE: "invalid"},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_SWING_MODE) != "invalid"
@pytest.mark.parametrize(
"swing_mode", [SWING_OFF, SWING_BOTH, SWING_VERTICAL, SWING_HORIZONTAL]
)
async def test_send_swing_mode_device_timeout(
hass: HomeAssistant, discovery, device, swing_mode
) -> None:
"""Test for sending swing mode command to the device with a device timeout."""
device().push_state_update.side_effect = DeviceTimeoutError
await async_setup_gree(hass)
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_SWING_MODE,
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_SWING_MODE: swing_mode},
blocking=True,
)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_SWING_MODE) == swing_mode
@pytest.mark.parametrize(
"swing_mode", [SWING_OFF, SWING_BOTH, SWING_VERTICAL, SWING_HORIZONTAL]
)
async def test_update_swing_mode(
hass: HomeAssistant, discovery, device, swing_mode
) -> None:
"""Test for updating swing mode from the device."""
device().horizontal_swing = (
HorizontalSwing.FullSwing
if swing_mode in (SWING_BOTH, SWING_HORIZONTAL)
else HorizontalSwing.Default
)
device().vertical_swing = (
VerticalSwing.FullSwing
if swing_mode in (SWING_BOTH, SWING_VERTICAL)
else VerticalSwing.Default
)
await async_setup_gree(hass)
state = hass.states.get(ENTITY_ID)
assert state is not None
assert state.attributes.get(ATTR_SWING_MODE) == swing_mode
async def test_coordinator_update_handler(
hass: HomeAssistant, discovery, device
) -> None:
"""Test for coordinator update handler."""
await async_setup_gree(hass)
await hass.async_block_till_done()
entity: GreeClimateEntity = hass.data[CLIMATE_DOMAIN].get_entity(ENTITY_ID)
assert entity is not None
# Initial state
assert entity.temperature_unit == UnitOfTemperature.CELSIUS
assert entity.min_temp == TEMP_MIN
assert entity.max_temp == TEMP_MAX
# Set unit to FAHRENHEIT
device().temperature_units = 1
entity.coordinator.async_set_updated_data(UnitOfTemperature.FAHRENHEIT)
await hass.async_block_till_done()
assert entity.temperature_unit == UnitOfTemperature.FAHRENHEIT
assert entity.min_temp == TEMP_MIN_F
assert entity.max_temp == TEMP_MAX_F
# Set unit back to CELSIUS
device().temperature_units = 0
entity.coordinator.async_set_updated_data(UnitOfTemperature.CELSIUS)
await hass.async_block_till_done()
assert entity.temperature_unit == UnitOfTemperature.CELSIUS
assert entity.min_temp == TEMP_MIN
assert entity.max_temp == TEMP_MAX
@patch("homeassistant.components.gree.PLATFORMS", [CLIMATE_DOMAIN])
async def test_registry_settings(
hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion
) -> None:
"""Test for entity registry settings (unique_id)."""
entry = await async_setup_gree(hass)
entries = er.async_entries_for_config_entry(entity_registry, entry.entry_id)
assert entries == snapshot
@patch("homeassistant.components.gree.PLATFORMS", [CLIMATE_DOMAIN])
async def test_entity_states(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
"""Test for entity registry settings (unique_id)."""
await async_setup_gree(hass)
states = hass.states.async_all()
assert states == snapshot