From c97acf87137ddc28beabd10362a834f2d19628bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ab=C3=ADlio=20Costa?= Date: Wed, 13 Oct 2021 14:45:02 +0100 Subject: [PATCH] Add support for multiple Whirlpool airconditioners (#57588) --- homeassistant/components/whirlpool/climate.py | 4 +- tests/components/whirlpool/conftest.py | 63 +- tests/components/whirlpool/test_climate.py | 588 ++++++++++-------- 3 files changed, 365 insertions(+), 290 deletions(-) diff --git a/homeassistant/components/whirlpool/climate.py b/homeassistant/components/whirlpool/climate.py index bd8cb0505fa6f2..ccfa11b3ee46bc 100644 --- a/homeassistant/components/whirlpool/climate.py +++ b/homeassistant/components/whirlpool/climate.py @@ -71,8 +71,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities): # the whirlpool library needs to be updated to be able to support more # than one device, so we use only the first one for now - aircon = AirConEntity(said_list[0], auth) - async_add_entities([aircon], True) + aircons = [AirConEntity(said, auth) for said in said_list] + async_add_entities(aircons, True) class AirConEntity(ClimateEntity): diff --git a/tests/components/whirlpool/conftest.py b/tests/components/whirlpool/conftest.py index e3919c118e286f..3a5fd0e3d2e962 100644 --- a/tests/components/whirlpool/conftest.py +++ b/tests/components/whirlpool/conftest.py @@ -4,8 +4,10 @@ import pytest import whirlpool +import whirlpool.aircon -MOCK_SAID = "said1" +MOCK_SAID1 = "said1" +MOCK_SAID2 = "said2" @pytest.fixture(name="mock_auth_api") @@ -14,28 +16,53 @@ def fixture_mock_auth_api(): with mock.patch("homeassistant.components.whirlpool.Auth") as mock_auth: mock_auth.return_value.do_auth = AsyncMock() mock_auth.return_value.is_access_token_valid.return_value = True - mock_auth.return_value.get_said_list.return_value = [MOCK_SAID] + mock_auth.return_value.get_said_list.return_value = [MOCK_SAID1, MOCK_SAID2] yield mock_auth -@pytest.fixture(name="mock_aircon_api", autouse=True) -def fixture_mock_aircon_api(mock_auth_api): +def get_aircon_mock(said): + """Get a mock of an air conditioner.""" + mock_aircon = mock.Mock(said=said) + mock_aircon.connect = AsyncMock() + mock_aircon.fetch_name = AsyncMock(return_value="TestZone") + mock_aircon.get_online.return_value = True + mock_aircon.get_power_on.return_value = True + mock_aircon.get_mode.return_value = whirlpool.aircon.Mode.Cool + mock_aircon.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.Auto + mock_aircon.get_current_temp.return_value = 15 + mock_aircon.get_temp.return_value = 20 + mock_aircon.get_current_humidity.return_value = 80 + mock_aircon.get_humidity.return_value = 50 + mock_aircon.get_h_louver_swing.return_value = True + + mock_aircon.set_power_on = AsyncMock() + mock_aircon.set_mode = AsyncMock() + mock_aircon.set_temp = AsyncMock() + mock_aircon.set_humidity = AsyncMock() + mock_aircon.set_mode = AsyncMock() + mock_aircon.set_fanspeed = AsyncMock() + mock_aircon.set_h_louver_swing = AsyncMock() + + return mock_aircon + + +@pytest.fixture(name="mock_aircon1_api", autouse=True) +def fixture_mock_aircon1_api(mock_auth_api): + """Set up air conditioner API fixture.""" + yield get_aircon_mock(MOCK_SAID1) + + +@pytest.fixture(name="mock_aircon2_api", autouse=True) +def fixture_mock_aircon2_api(mock_auth_api): + """Set up air conditioner API fixture.""" + yield get_aircon_mock(MOCK_SAID2) + + +@pytest.fixture(name="mock_aircon_api_instances", autouse=True) +def fixture_mock_aircon_api_instances(mock_aircon1_api, mock_aircon2_api): """Set up air conditioner API fixture.""" with mock.patch( "homeassistant.components.whirlpool.climate.Aircon" ) as mock_aircon_api: - mock_aircon_api.return_value.connect = AsyncMock() - mock_aircon_api.return_value.fetch_name = AsyncMock(return_value="TestZone") - mock_aircon_api.return_value.said = MOCK_SAID - mock_aircon_api.return_value.get_online.return_value = True - mock_aircon_api.return_value.get_power_on.return_value = True - mock_aircon_api.return_value.get_mode.return_value = whirlpool.aircon.Mode.Cool - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.Auto - ) - mock_aircon_api.return_value.get_current_temp.return_value = 15 - mock_aircon_api.return_value.get_temp.return_value = 20 - mock_aircon_api.return_value.get_current_humidity.return_value = 80 - mock_aircon_api.return_value.get_humidity.return_value = 50 - mock_aircon_api.return_value.get_h_louver_swing.return_value = True + mock_aircon_api.side_effect = [mock_aircon1_api, mock_aircon2_api] yield mock_aircon_api diff --git a/tests/components/whirlpool/test_climate.py b/tests/components/whirlpool/test_climate.py index 314c6c2685bad9..befcd650b644cf 100644 --- a/tests/components/whirlpool/test_climate.py +++ b/tests/components/whirlpool/test_climate.py @@ -2,6 +2,7 @@ from unittest.mock import AsyncMock, MagicMock import aiohttp +from attr import dataclass import pytest import whirlpool @@ -55,12 +56,19 @@ from . import init_integration -async def update_ac_state(hass: HomeAssistant, mock_aircon_api: MagicMock): +async def update_ac_state( + hass: HomeAssistant, + entity_id: str, + mock_aircon_api_instances: MagicMock, + mock_instance_idx: int, +): """Simulate an update trigger from the API.""" - update_ha_state_cb = mock_aircon_api.call_args.args[2] + update_ha_state_cb = mock_aircon_api_instances.call_args_list[ + mock_instance_idx + ].args[2] update_ha_state_cb() await hass.async_block_till_done() - return hass.states.get("climate.said1") + return hass.states.get(entity_id) async def test_no_appliances(hass: HomeAssistant, mock_auth_api: MagicMock): @@ -71,297 +79,337 @@ async def test_no_appliances(hass: HomeAssistant, mock_auth_api: MagicMock): async def test_name_fallback_on_exception( - hass: HomeAssistant, mock_aircon_api: MagicMock + hass: HomeAssistant, mock_aircon1_api: MagicMock ): """Test name property.""" - mock_aircon_api.return_value.fetch_name = AsyncMock( - side_effect=aiohttp.ClientError() - ) + mock_aircon1_api.fetch_name = AsyncMock(side_effect=aiohttp.ClientError()) await init_integration(hass) state = hass.states.get("climate.said1") assert state.attributes[ATTR_FRIENDLY_NAME] == "said1" -async def test_static_attributes(hass: HomeAssistant, mock_aircon_api: MagicMock): +async def test_static_attributes(hass: HomeAssistant, mock_aircon1_api: MagicMock): """Test static climate attributes.""" await init_integration(hass) - entry = er.async_get(hass).async_get("climate.said1") - assert entry - assert entry.unique_id == "said1" + for entity_id in ("climate.said1", "climate.said2"): + entry = er.async_get(hass).async_get(entity_id) + assert entry + assert entry.unique_id == entity_id.split(".")[1] - state = hass.states.get("climate.said1") - assert state is not None - assert state.state != STATE_UNAVAILABLE - assert state.state == HVAC_MODE_COOL - - attributes = state.attributes - assert attributes[ATTR_FRIENDLY_NAME] == "TestZone" - - assert ( - attributes[ATTR_SUPPORTED_FEATURES] - == SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE - ) - assert attributes[ATTR_HVAC_MODES] == [ - HVAC_MODE_COOL, - HVAC_MODE_HEAT, - HVAC_MODE_FAN_ONLY, - HVAC_MODE_OFF, - ] - assert attributes[ATTR_FAN_MODES] == [ - FAN_AUTO, - FAN_HIGH, - FAN_MEDIUM, - FAN_LOW, - FAN_OFF, - ] - assert attributes[ATTR_SWING_MODES] == [SWING_HORIZONTAL, SWING_OFF] - assert attributes[ATTR_TARGET_TEMP_STEP] == 1 - assert attributes[ATTR_MIN_TEMP] == 16 - assert attributes[ATTR_MAX_TEMP] == 30 - - -async def test_dynamic_attributes(hass: HomeAssistant, mock_aircon_api: MagicMock): + state = hass.states.get(entity_id) + assert state is not None + assert state.state != STATE_UNAVAILABLE + assert state.state == HVAC_MODE_COOL + + attributes = state.attributes + assert attributes[ATTR_FRIENDLY_NAME] == "TestZone" + + assert ( + attributes[ATTR_SUPPORTED_FEATURES] + == SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE + ) + assert attributes[ATTR_HVAC_MODES] == [ + HVAC_MODE_COOL, + HVAC_MODE_HEAT, + HVAC_MODE_FAN_ONLY, + HVAC_MODE_OFF, + ] + assert attributes[ATTR_FAN_MODES] == [ + FAN_AUTO, + FAN_HIGH, + FAN_MEDIUM, + FAN_LOW, + FAN_OFF, + ] + assert attributes[ATTR_SWING_MODES] == [SWING_HORIZONTAL, SWING_OFF] + assert attributes[ATTR_TARGET_TEMP_STEP] == 1 + assert attributes[ATTR_MIN_TEMP] == 16 + assert attributes[ATTR_MAX_TEMP] == 30 + + +async def test_dynamic_attributes( + hass: HomeAssistant, + mock_aircon_api_instances: MagicMock, + mock_aircon1_api: MagicMock, + mock_aircon2_api: MagicMock, +): """Test dynamic attributes.""" await init_integration(hass) - state = hass.states.get("climate.said1") - assert state is not None - assert state.state == HVAC_MODE_COOL - - mock_aircon_api.return_value.get_power_on.return_value = False - state = await update_ac_state(hass, mock_aircon_api) - assert state.state == HVAC_MODE_OFF - - mock_aircon_api.return_value.get_online.return_value = False - state = await update_ac_state(hass, mock_aircon_api) - assert state.state == STATE_UNAVAILABLE - - mock_aircon_api.return_value.get_power_on.return_value = True - mock_aircon_api.return_value.get_online.return_value = True - state = await update_ac_state(hass, mock_aircon_api) - assert state.state == HVAC_MODE_COOL - - mock_aircon_api.return_value.get_mode.return_value = whirlpool.aircon.Mode.Heat - state = await update_ac_state(hass, mock_aircon_api) - assert state.state == HVAC_MODE_HEAT - - mock_aircon_api.return_value.get_mode.return_value = whirlpool.aircon.Mode.Fan - state = await update_ac_state(hass, mock_aircon_api) - assert state.state == HVAC_MODE_FAN_ONLY - - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.Auto - ) - state = await update_ac_state(hass, mock_aircon_api) - assert state.attributes[ATTR_FAN_MODE] == HVAC_MODE_AUTO - - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.Low - ) - state = await update_ac_state(hass, mock_aircon_api) - assert state.attributes[ATTR_FAN_MODE] == FAN_LOW - - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.Medium - ) - state = await update_ac_state(hass, mock_aircon_api) - assert state.attributes[ATTR_FAN_MODE] == FAN_MEDIUM - - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.High - ) - state = await update_ac_state(hass, mock_aircon_api) - assert state.attributes[ATTR_FAN_MODE] == FAN_HIGH - - mock_aircon_api.return_value.get_fanspeed.return_value = ( - whirlpool.aircon.FanSpeed.Off - ) - state = await update_ac_state(hass, mock_aircon_api) - assert state.attributes[ATTR_FAN_MODE] == FAN_OFF - - mock_aircon_api.return_value.get_current_temp.return_value = 15 - mock_aircon_api.return_value.get_temp.return_value = 20 - mock_aircon_api.return_value.get_current_humidity.return_value = 80 - mock_aircon_api.return_value.get_h_louver_swing.return_value = True - attributes = (await update_ac_state(hass, mock_aircon_api)).attributes - assert attributes[ATTR_CURRENT_TEMPERATURE] == 15 - assert attributes[ATTR_TEMPERATURE] == 20 - assert attributes[ATTR_CURRENT_HUMIDITY] == 80 - assert attributes[ATTR_SWING_MODE] == SWING_HORIZONTAL - - mock_aircon_api.return_value.get_current_temp.return_value = 16 - mock_aircon_api.return_value.get_temp.return_value = 21 - mock_aircon_api.return_value.get_current_humidity.return_value = 70 - mock_aircon_api.return_value.get_h_louver_swing.return_value = False - attributes = (await update_ac_state(hass, mock_aircon_api)).attributes - assert attributes[ATTR_CURRENT_TEMPERATURE] == 16 - assert attributes[ATTR_TEMPERATURE] == 21 - assert attributes[ATTR_CURRENT_HUMIDITY] == 70 - assert attributes[ATTR_SWING_MODE] == SWING_OFF - - -async def test_service_calls(hass: HomeAssistant, mock_aircon_api: MagicMock): + @dataclass + class ClimateTestInstance: + """Helper class for multiple climate and mock instances.""" + + entity_id: str + mock_instance: MagicMock + mock_instance_idx: int + + for clim_test_instance in ( + ClimateTestInstance("climate.said1", mock_aircon1_api, 0), + ClimateTestInstance("climate.said2", mock_aircon2_api, 1), + ): + entity_id = clim_test_instance.entity_id + mock_instance = clim_test_instance.mock_instance + mock_instance_idx = clim_test_instance.mock_instance_idx + state = hass.states.get(entity_id) + assert state is not None + assert state.state == HVAC_MODE_COOL + + mock_instance.get_power_on.return_value = False + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.state == HVAC_MODE_OFF + + mock_instance.get_online.return_value = False + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.state == STATE_UNAVAILABLE + + mock_instance.get_power_on.return_value = True + mock_instance.get_online.return_value = True + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.state == HVAC_MODE_COOL + + mock_instance.get_mode.return_value = whirlpool.aircon.Mode.Heat + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.state == HVAC_MODE_HEAT + + mock_instance.get_mode.return_value = whirlpool.aircon.Mode.Fan + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.state == HVAC_MODE_FAN_ONLY + + mock_instance.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.Auto + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.attributes[ATTR_FAN_MODE] == HVAC_MODE_AUTO + + mock_instance.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.Low + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.attributes[ATTR_FAN_MODE] == FAN_LOW + + mock_instance.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.Medium + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.attributes[ATTR_FAN_MODE] == FAN_MEDIUM + + mock_instance.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.High + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.attributes[ATTR_FAN_MODE] == FAN_HIGH + + mock_instance.get_fanspeed.return_value = whirlpool.aircon.FanSpeed.Off + state = await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + assert state.attributes[ATTR_FAN_MODE] == FAN_OFF + + mock_instance.get_current_temp.return_value = 15 + mock_instance.get_temp.return_value = 20 + mock_instance.get_current_humidity.return_value = 80 + mock_instance.get_h_louver_swing.return_value = True + attributes = ( + await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + ).attributes + assert attributes[ATTR_CURRENT_TEMPERATURE] == 15 + assert attributes[ATTR_TEMPERATURE] == 20 + assert attributes[ATTR_CURRENT_HUMIDITY] == 80 + assert attributes[ATTR_SWING_MODE] == SWING_HORIZONTAL + + mock_instance.get_current_temp.return_value = 16 + mock_instance.get_temp.return_value = 21 + mock_instance.get_current_humidity.return_value = 70 + mock_instance.get_h_louver_swing.return_value = False + attributes = ( + await update_ac_state( + hass, entity_id, mock_aircon_api_instances, mock_instance_idx + ) + ).attributes + assert attributes[ATTR_CURRENT_TEMPERATURE] == 16 + assert attributes[ATTR_TEMPERATURE] == 21 + assert attributes[ATTR_CURRENT_HUMIDITY] == 70 + assert attributes[ATTR_SWING_MODE] == SWING_OFF + + +async def test_service_calls( + hass: HomeAssistant, mock_aircon1_api: MagicMock, mock_aircon2_api: MagicMock +): """Test controlling the entity through service calls.""" await init_integration(hass) - mock_aircon_api.return_value.set_power_on = AsyncMock() - mock_aircon_api.return_value.set_mode = AsyncMock() - mock_aircon_api.return_value.set_temp = AsyncMock() - mock_aircon_api.return_value.set_humidity = AsyncMock() - mock_aircon_api.return_value.set_mode = AsyncMock() - mock_aircon_api.return_value.set_fanspeed = AsyncMock() - mock_aircon_api.return_value.set_h_louver_swing = AsyncMock() - - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "climate.said1"}, - blocking=True, - ) - mock_aircon_api.return_value.set_power_on.assert_called_once_with(False) - - mock_aircon_api.return_value.set_power_on.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "climate.said1"}, - blocking=True, - ) - mock_aircon_api.return_value.set_power_on.assert_called_once_with(True) - - mock_aircon_api.return_value.set_power_on.reset_mock() - mock_aircon_api.return_value.get_power_on.return_value = False - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_HVAC_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_HVAC_MODE: HVAC_MODE_COOL}, - blocking=True, - ) - mock_aircon_api.return_value.set_power_on.assert_called_once_with(True) - - mock_aircon_api.return_value.set_temp.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_TEMPERATURE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_TEMPERATURE: 15}, - blocking=True, - ) - mock_aircon_api.return_value.set_temp.assert_called_once_with(15) - - mock_aircon_api.return_value.set_mode.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_HVAC_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_HVAC_MODE: HVAC_MODE_COOL}, - blocking=True, - ) - mock_aircon_api.return_value.set_mode.assert_called_once_with( - whirlpool.aircon.Mode.Cool - ) - - mock_aircon_api.return_value.set_mode.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_HVAC_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_HVAC_MODE: HVAC_MODE_HEAT}, - blocking=True, - ) - mock_aircon_api.return_value.set_mode.assert_called_once_with( - whirlpool.aircon.Mode.Heat - ) - - mock_aircon_api.return_value.set_mode.reset_mock() - # HVAC_MODE_DRY is not supported - with pytest.raises(ValueError): + + @dataclass + class ClimateInstancesData: + """Helper class for multiple climate and mock instances.""" + + entity_id: str + mock_instance: MagicMock + + for clim_test_instance in ( + ClimateInstancesData("climate.said1", mock_aircon1_api), + ClimateInstancesData("climate.said2", mock_aircon2_api), + ): + mock_instance = clim_test_instance.mock_instance + entity_id = clim_test_instance.entity_id + + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + mock_instance.set_power_on.assert_called_once_with(False) + + mock_instance.set_power_on.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + mock_instance.set_power_on.assert_called_once_with(True) + + mock_instance.set_power_on.reset_mock() + mock_instance.get_power_on.return_value = False + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_HVAC_MODE: HVAC_MODE_COOL}, + blocking=True, + ) + mock_instance.set_power_on.assert_called_once_with(True) + + mock_instance.set_temp.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_TEMPERATURE, + {ATTR_ENTITY_ID: entity_id, ATTR_TEMPERATURE: 15}, + blocking=True, + ) + mock_instance.set_temp.assert_called_once_with(15) + + mock_instance.set_mode.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_HVAC_MODE: HVAC_MODE_COOL}, + blocking=True, + ) + mock_instance.set_mode.assert_called_once_with(whirlpool.aircon.Mode.Cool) + + mock_instance.set_mode.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_HVAC_MODE: HVAC_MODE_HEAT}, + blocking=True, + ) + mock_instance.set_mode.assert_called_once_with(whirlpool.aircon.Mode.Heat) + + mock_instance.set_mode.reset_mock() + # HVAC_MODE_DRY is not supported + with pytest.raises(ValueError): + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_HVAC_MODE: HVAC_MODE_DRY}, + blocking=True, + ) + mock_instance.set_mode.assert_not_called() + + mock_instance.set_mode.reset_mock() await hass.services.async_call( CLIMATE_DOMAIN, SERVICE_SET_HVAC_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_HVAC_MODE: HVAC_MODE_DRY}, + {ATTR_ENTITY_ID: entity_id, ATTR_HVAC_MODE: HVAC_MODE_FAN_ONLY}, + blocking=True, + ) + mock_instance.set_mode.assert_called_once_with(whirlpool.aircon.Mode.Fan) + + mock_instance.set_fanspeed.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_FAN_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_AUTO}, + blocking=True, + ) + mock_instance.set_fanspeed.assert_called_once_with( + whirlpool.aircon.FanSpeed.Auto + ) + + mock_instance.set_fanspeed.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_FAN_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_LOW}, + blocking=True, + ) + mock_instance.set_fanspeed.assert_called_once_with( + whirlpool.aircon.FanSpeed.Low + ) + + mock_instance.set_fanspeed.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_FAN_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_MEDIUM}, blocking=True, ) - mock_aircon_api.return_value.set_mode.assert_not_called() - - mock_aircon_api.return_value.set_mode.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_HVAC_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_HVAC_MODE: HVAC_MODE_FAN_ONLY}, - blocking=True, - ) - mock_aircon_api.return_value.set_mode.assert_called_once_with( - whirlpool.aircon.Mode.Fan - ) - - mock_aircon_api.return_value.set_fanspeed.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_FAN_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_FAN_MODE: FAN_AUTO}, - blocking=True, - ) - mock_aircon_api.return_value.set_fanspeed.assert_called_once_with( - whirlpool.aircon.FanSpeed.Auto - ) - - mock_aircon_api.return_value.set_fanspeed.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_FAN_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_FAN_MODE: FAN_LOW}, - blocking=True, - ) - mock_aircon_api.return_value.set_fanspeed.assert_called_once_with( - whirlpool.aircon.FanSpeed.Low - ) - - mock_aircon_api.return_value.set_fanspeed.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_FAN_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_FAN_MODE: FAN_MEDIUM}, - blocking=True, - ) - mock_aircon_api.return_value.set_fanspeed.assert_called_once_with( - whirlpool.aircon.FanSpeed.Medium - ) - - mock_aircon_api.return_value.set_fanspeed.reset_mock() - # FAN_MIDDLE is not supported - with pytest.raises(ValueError): + mock_instance.set_fanspeed.assert_called_once_with( + whirlpool.aircon.FanSpeed.Medium + ) + + mock_instance.set_fanspeed.reset_mock() + # FAN_MIDDLE is not supported + with pytest.raises(ValueError): + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_FAN_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_MIDDLE}, + blocking=True, + ) + mock_instance.set_fanspeed.assert_not_called() + + mock_instance.set_fanspeed.reset_mock() await hass.services.async_call( CLIMATE_DOMAIN, SERVICE_SET_FAN_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_FAN_MODE: FAN_MIDDLE}, + {ATTR_ENTITY_ID: entity_id, ATTR_FAN_MODE: FAN_HIGH}, + blocking=True, + ) + mock_instance.set_fanspeed.assert_called_once_with( + whirlpool.aircon.FanSpeed.High + ) + + mock_instance.set_h_louver_swing.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_SWING_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_SWING_MODE: SWING_HORIZONTAL}, + blocking=True, + ) + mock_instance.set_h_louver_swing.assert_called_with(True) + + mock_instance.set_h_louver_swing.reset_mock() + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_SWING_MODE, + {ATTR_ENTITY_ID: entity_id, ATTR_SWING_MODE: SWING_OFF}, blocking=True, ) - mock_aircon_api.return_value.set_fanspeed.assert_not_called() - - mock_aircon_api.return_value.set_fanspeed.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_FAN_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_FAN_MODE: FAN_HIGH}, - blocking=True, - ) - mock_aircon_api.return_value.set_fanspeed.assert_called_once_with( - whirlpool.aircon.FanSpeed.High - ) - - mock_aircon_api.return_value.set_h_louver_swing.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_SWING_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_SWING_MODE: SWING_HORIZONTAL}, - blocking=True, - ) - mock_aircon_api.return_value.set_h_louver_swing.assert_called_with(True) - - mock_aircon_api.return_value.set_h_louver_swing.reset_mock() - await hass.services.async_call( - CLIMATE_DOMAIN, - SERVICE_SET_SWING_MODE, - {ATTR_ENTITY_ID: "climate.said1", ATTR_SWING_MODE: SWING_OFF}, - blocking=True, - ) - mock_aircon_api.return_value.set_h_louver_swing.assert_called_with(False) + mock_instance.set_h_louver_swing.assert_called_with(False)