diff --git a/tests/components/generic_thermostat/test_climate.py b/tests/components/generic_thermostat/test_climate.py index c7b6c03a2c5..fdcad219d93 100644 --- a/tests/components/generic_thermostat/test_climate.py +++ b/tests/components/generic_thermostat/test_climate.py @@ -755,8 +755,9 @@ async def test_no_state_change_when_operation_mode_off_2( assert len(calls) == 0 -@pytest.fixture -async def setup_comp_4(hass): +async def _setup_thermostat_with_min_cycle_duration( + hass: HomeAssistant, ac_mode: bool, initial_hvac_mode: HVACMode +): """Initialize components.""" hass.config.temperature_unit = UnitOfTemperature.CELSIUS assert await async_setup_component( @@ -770,102 +771,141 @@ async def setup_comp_4(hass): "hot_tolerance": 0.3, "heater": ENT_SWITCH, "target_sensor": ENT_SENSOR, - "ac_mode": True, + "ac_mode": ac_mode, "min_cycle_duration": datetime.timedelta(minutes=10), - "initial_hvac_mode": HVACMode.COOL, + "initial_hvac_mode": initial_hvac_mode, } }, ) await hass.async_block_till_done() -async def test_temp_change_ac_trigger_on_not_long_enough( - hass: HomeAssistant, setup_comp_4 +@pytest.mark.parametrize( + ( + "ac_mode", + "initial_hvac_mode", + "initial_switch_state", + "sensor_temperature", + "target_temperature", + ), + [ + (True, HVACMode.COOL, False, 30, 25), + (True, HVACMode.COOL, True, 25, 30), + (False, HVACMode.HEAT, True, 25, 30), + (False, HVACMode.HEAT, False, 30, 25), + ], +) +async def test_heating_cooling_switch_does_not_toggle_when_within_min_cycle_duration( + hass: HomeAssistant, + ac_mode: bool, + initial_hvac_mode: HVACMode, + initial_switch_state: bool, + sensor_temperature: int, + target_temperature: int, ) -> None: - """Test if temperature change turn ac on.""" - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) + """Test if heating/cooling does not toggle when inside minimum cycle.""" + # Given + await _setup_thermostat_with_min_cycle_duration(hass, ac_mode, initial_hvac_mode) + calls = _setup_switch(hass, initial_switch_state) + _setup_sensor(hass, sensor_temperature) + + # When + await common.async_set_temperature(hass, target_temperature) await hass.async_block_till_done() + + # Then assert len(calls) == 0 -async def test_temp_change_ac_trigger_on_long_enough( - hass: HomeAssistant, setup_comp_4 +@pytest.mark.parametrize( + ( + "ac_mode", + "initial_hvac_mode", + "initial_switch_state", + "sensor_temperature", + "target_temperature", + "expected_triggered_service_call", + ), + [ + (True, HVACMode.COOL, False, 30, 25, SERVICE_TURN_ON), + (True, HVACMode.COOL, True, 25, 30, SERVICE_TURN_OFF), + (False, HVACMode.HEAT, False, 25, 30, SERVICE_TURN_ON), + (False, HVACMode.HEAT, True, 30, 25, SERVICE_TURN_OFF), + ], +) +async def test_heating_cooling_switch_toggles_when_outside_min_cycle_duration( + hass: HomeAssistant, + ac_mode: bool, + initial_hvac_mode: HVACMode, + initial_switch_state: bool, + sensor_temperature: int, + target_temperature: int, + expected_triggered_service_call: str, ) -> None: - """Test if temperature change turn ac on.""" + """Test if heating/cooling toggles when outside minimum cycle.""" + # Given + await _setup_thermostat_with_min_cycle_duration(hass, ac_mode, initial_hvac_mode) fake_changed = datetime.datetime(1970, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC) with freeze_time(fake_changed): - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) + calls = _setup_switch(hass, initial_switch_state) + _setup_sensor(hass, sensor_temperature) + + # When + await common.async_set_temperature(hass, target_temperature) await hass.async_block_till_done() + + # Then assert len(calls) == 1 call = calls[0] assert call.domain == HASS_DOMAIN - assert call.service == SERVICE_TURN_ON + assert call.service == expected_triggered_service_call assert call.data["entity_id"] == ENT_SWITCH -async def test_temp_change_ac_trigger_off_not_long_enough( - hass: HomeAssistant, setup_comp_4 +@pytest.mark.parametrize( + ( + "ac_mode", + "initial_hvac_mode", + "initial_switch_state", + "sensor_temperature", + "target_temperature", + "changed_hvac_mode", + "expected_triggered_service_call", + ), + [ + (True, HVACMode.COOL, False, 30, 25, HVACMode.HEAT, SERVICE_TURN_ON), + (True, HVACMode.COOL, True, 25, 30, HVACMode.OFF, SERVICE_TURN_OFF), + (False, HVACMode.HEAT, False, 25, 30, HVACMode.HEAT, SERVICE_TURN_ON), + (False, HVACMode.HEAT, True, 30, 25, HVACMode.OFF, SERVICE_TURN_OFF), + ], +) +async def test_hvac_mode_change_toggles_heating_cooling_switch_even_when_within_min_cycle_duration( + hass: HomeAssistant, + ac_mode: bool, + initial_hvac_mode: HVACMode, + initial_switch_state: bool, + sensor_temperature: int, + target_temperature: int, + changed_hvac_mode: HVACMode, + expected_triggered_service_call: str, ) -> None: - """Test if temperature change turn ac on.""" - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) + """Test if mode change toggles heating/cooling despite minimum cycle.""" + # Given + await _setup_thermostat_with_min_cycle_duration(hass, ac_mode, initial_hvac_mode) + calls = _setup_switch(hass, initial_switch_state) + _setup_sensor(hass, sensor_temperature) + + # When + await common.async_set_temperature(hass, target_temperature) await hass.async_block_till_done() + + # Then assert len(calls) == 0 - - -async def test_temp_change_ac_trigger_off_long_enough( - hass: HomeAssistant, setup_comp_4 -) -> None: - """Test if temperature change turn ac on.""" - fake_changed = datetime.datetime(1970, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC) - with freeze_time(fake_changed): - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) - await hass.async_block_till_done() - assert len(calls) == 1 - call = calls[0] - assert call.domain == HASS_DOMAIN - assert call.service == SERVICE_TURN_OFF - assert call.data["entity_id"] == ENT_SWITCH - - -async def test_mode_change_ac_trigger_off_not_long_enough( - hass: HomeAssistant, setup_comp_4 -) -> None: - """Test if mode change turns ac off despite minimum cycle.""" - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) - await hass.async_block_till_done() - assert len(calls) == 0 - await common.async_set_hvac_mode(hass, HVACMode.OFF) + await common.async_set_hvac_mode(hass, changed_hvac_mode) assert len(calls) == 1 call = calls[0] assert call.domain == "homeassistant" - assert call.service == SERVICE_TURN_OFF - assert call.data["entity_id"] == ENT_SWITCH - - -async def test_mode_change_ac_trigger_on_not_long_enough( - hass: HomeAssistant, setup_comp_4 -) -> None: - """Test if mode change turns ac on despite minimum cycle.""" - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) - await hass.async_block_till_done() - assert len(calls) == 0 - await common.async_set_hvac_mode(hass, HVACMode.HEAT) - assert len(calls) == 1 - call = calls[0] - assert call.domain == "homeassistant" - assert call.service == SERVICE_TURN_ON + assert call.service == expected_triggered_service_call assert call.data["entity_id"] == ENT_SWITCH @@ -983,119 +1023,6 @@ async def test_mode_change_ac_trigger_on_not_long_enough_2( assert call.data["entity_id"] == ENT_SWITCH -@pytest.fixture -async def setup_comp_6(hass): - """Initialize components.""" - hass.config.temperature_unit = UnitOfTemperature.CELSIUS - assert await async_setup_component( - hass, - DOMAIN, - { - "climate": { - "platform": "generic_thermostat", - "name": "test", - "cold_tolerance": 0.3, - "hot_tolerance": 0.3, - "heater": ENT_SWITCH, - "target_sensor": ENT_SENSOR, - "min_cycle_duration": datetime.timedelta(minutes=10), - "initial_hvac_mode": HVACMode.HEAT, - } - }, - ) - await hass.async_block_till_done() - - -async def test_temp_change_heater_trigger_off_not_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if temp change doesn't turn heater off because of time.""" - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) - await hass.async_block_till_done() - assert len(calls) == 0 - - -async def test_temp_change_heater_trigger_on_not_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if temp change doesn't turn heater on because of time.""" - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) - await hass.async_block_till_done() - assert len(calls) == 0 - - -async def test_temp_change_heater_trigger_on_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if temperature change turn heater on after min cycle.""" - fake_changed = datetime.datetime(1970, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC) - with freeze_time(fake_changed): - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) - await hass.async_block_till_done() - assert len(calls) == 1 - call = calls[0] - assert call.domain == HASS_DOMAIN - assert call.service == SERVICE_TURN_ON - assert call.data["entity_id"] == ENT_SWITCH - - -async def test_temp_change_heater_trigger_off_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if temperature change turn heater off after min cycle.""" - fake_changed = datetime.datetime(1970, 11, 11, 11, 11, 11, tzinfo=dt_util.UTC) - with freeze_time(fake_changed): - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) - await hass.async_block_till_done() - assert len(calls) == 1 - call = calls[0] - assert call.domain == HASS_DOMAIN - assert call.service == SERVICE_TURN_OFF - assert call.data["entity_id"] == ENT_SWITCH - - -async def test_mode_change_heater_trigger_off_not_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if mode change turns heater off despite minimum cycle.""" - calls = _setup_switch(hass, True) - await common.async_set_temperature(hass, 25) - _setup_sensor(hass, 30) - await hass.async_block_till_done() - assert len(calls) == 0 - await common.async_set_hvac_mode(hass, HVACMode.OFF) - assert len(calls) == 1 - call = calls[0] - assert call.domain == "homeassistant" - assert call.service == SERVICE_TURN_OFF - assert call.data["entity_id"] == ENT_SWITCH - - -async def test_mode_change_heater_trigger_on_not_long_enough( - hass: HomeAssistant, setup_comp_6 -) -> None: - """Test if mode change turns heater on despite minimum cycle.""" - calls = _setup_switch(hass, False) - await common.async_set_temperature(hass, 30) - _setup_sensor(hass, 25) - await hass.async_block_till_done() - assert len(calls) == 0 - await common.async_set_hvac_mode(hass, HVACMode.HEAT) - assert len(calls) == 1 - call = calls[0] - assert call.domain == "homeassistant" - assert call.service == SERVICE_TURN_ON - assert call.data["entity_id"] == ENT_SWITCH - - @pytest.fixture async def setup_comp_7(hass): """Initialize components."""