Improve Whirlpool component code quality (#57357)

* Improve Whirlpool component code

This implements a few suggestions given in
https://github.com/home-assistant/core/pull/48346#pullrequestreview-773552670

* Add return typing

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Add reason assertion to config_flow test

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Abílio Costa 2021-10-10 07:49:02 +01:00 committed by GitHub
parent 80ee583418
commit 49d97e13de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 31 deletions

View File

@ -48,6 +48,18 @@ AIRCON_FANSPEED_MAP = {
FAN_MODE_TO_AIRCON_FANSPEED = {v: k for k, v in AIRCON_FANSPEED_MAP.items()} FAN_MODE_TO_AIRCON_FANSPEED = {v: k for k, v in AIRCON_FANSPEED_MAP.items()}
SUPPORTED_FAN_MODES = [FAN_AUTO, FAN_HIGH, FAN_MEDIUM, FAN_LOW, FAN_OFF]
SUPPORTED_HVAC_MODES = [
HVAC_MODE_COOL,
HVAC_MODE_HEAT,
HVAC_MODE_FAN_ONLY,
HVAC_MODE_OFF,
]
SUPPORTED_MAX_TEMP = 30
SUPPORTED_MIN_TEMP = 16
SUPPORTED_SWING_MODES = [SWING_HORIZONTAL, SWING_OFF]
SUPPORTED_TARGET_TEMPERATURE_STEP = 1
async def async_setup_entry(hass, config_entry, async_add_entities): async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up entry.""" """Set up entry."""
@ -66,20 +78,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class AirConEntity(ClimateEntity): class AirConEntity(ClimateEntity):
"""Representation of an air conditioner.""" """Representation of an air conditioner."""
_attr_fan_modes = [FAN_AUTO, FAN_HIGH, FAN_MEDIUM, FAN_LOW, FAN_OFF] _attr_fan_modes = SUPPORTED_FAN_MODES
_attr_hvac_modes = [ _attr_hvac_modes = SUPPORTED_HVAC_MODES
HVAC_MODE_COOL, _attr_max_temp = SUPPORTED_MAX_TEMP
HVAC_MODE_HEAT, _attr_min_temp = SUPPORTED_MIN_TEMP
HVAC_MODE_FAN_ONLY,
HVAC_MODE_OFF,
]
_attr_max_temp = 30
_attr_min_temp = 16
_attr_supported_features = ( _attr_supported_features = (
SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE
) )
_attr_swing_modes = [SWING_HORIZONTAL, SWING_OFF] _attr_swing_modes = SUPPORTED_SWING_MODES
_attr_target_temperature_step = 1 _attr_target_temperature_step = SUPPORTED_TARGET_TEMPERATURE_STEP
_attr_temperature_unit = TEMP_CELSIUS _attr_temperature_unit = TEMP_CELSIUS
_attr_should_poll = False _attr_should_poll = False
@ -141,7 +148,7 @@ class AirConEntity(ClimateEntity):
return HVAC_MODE_OFF return HVAC_MODE_OFF
mode: AirconMode = self._aircon.get_mode() mode: AirconMode = self._aircon.get_mode()
return AIRCON_MODE_MAP.get(mode, None) return AIRCON_MODE_MAP.get(mode)
async def async_set_hvac_mode(self, hvac_mode): async def async_set_hvac_mode(self, hvac_mode):
"""Set HVAC mode.""" """Set HVAC mode."""
@ -151,8 +158,7 @@ class AirConEntity(ClimateEntity):
mode = HVAC_MODE_TO_AIRCON_MODE.get(hvac_mode) mode = HVAC_MODE_TO_AIRCON_MODE.get(hvac_mode)
if not mode: if not mode:
_LOGGER.warning("Unexpected hvac mode: %s", hvac_mode) raise ValueError(f"Invalid hvac mode {hvac_mode}")
return
await self._aircon.set_mode(mode) await self._aircon.set_mode(mode)
if not self._aircon.get_power_on(): if not self._aircon.get_power_on():
@ -168,7 +174,7 @@ class AirConEntity(ClimateEntity):
"""Set fan mode.""" """Set fan mode."""
fanspeed = FAN_MODE_TO_AIRCON_FANSPEED.get(fan_mode) fanspeed = FAN_MODE_TO_AIRCON_FANSPEED.get(fan_mode)
if not fanspeed: if not fanspeed:
return raise ValueError(f"Invalid fan mode {fan_mode}")
await self._aircon.set_fanspeed(fanspeed) await self._aircon.set_fanspeed(fanspeed)
@property @property

View File

@ -1,4 +1,6 @@
"""Config flow for Whirlpool Sixth Sense integration.""" """Config flow for Whirlpool Sixth Sense integration."""
from __future__ import annotations
import asyncio import asyncio
import logging import logging
@ -13,10 +15,14 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
STEP_USER_DATA_SCHEMA = vol.Schema({CONF_USERNAME: str, CONF_PASSWORD: str}) STEP_USER_DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
)
async def validate_input(hass: core.HomeAssistant, data): async def validate_input(
hass: core.HomeAssistant, data: dict[str, str]
) -> dict[str, str]:
"""Validate the user input allows us to connect. """Validate the user input allows us to connect.
Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user. Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user.

View File

@ -2,6 +2,7 @@
from unittest.mock import AsyncMock, MagicMock from unittest.mock import AsyncMock, MagicMock
import aiohttp import aiohttp
import pytest
import whirlpool import whirlpool
from homeassistant.components.climate.const import ( from homeassistant.components.climate.const import (
@ -271,7 +272,8 @@ async def test_service_calls(hass: HomeAssistant, mock_aircon_api: MagicMock):
) )
mock_aircon_api.return_value.set_mode.reset_mock() mock_aircon_api.return_value.set_mode.reset_mock()
# HVAC_MODE_DRY should be ignored # HVAC_MODE_DRY is not supported
with pytest.raises(ValueError):
await hass.services.async_call( await hass.services.async_call(
CLIMATE_DOMAIN, CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE, SERVICE_SET_HVAC_MODE,
@ -325,7 +327,8 @@ async def test_service_calls(hass: HomeAssistant, mock_aircon_api: MagicMock):
) )
mock_aircon_api.return_value.set_fanspeed.reset_mock() mock_aircon_api.return_value.set_fanspeed.reset_mock()
# FAN_MIDDLE should be ignored # FAN_MIDDLE is not supported
with pytest.raises(ValueError):
await hass.services.async_call( await hass.services.async_call(
CLIMATE_DOMAIN, CLIMATE_DOMAIN,
SERVICE_SET_FAN_MODE, SERVICE_SET_FAN_MODE,

View File

@ -7,6 +7,8 @@ import aiohttp
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.whirlpool.const import DOMAIN from homeassistant.components.whirlpool.const import DOMAIN
from tests.common import MockConfigEntry
async def test_form(hass): async def test_form(hass):
"""Test we get the form.""" """Test we get the form."""
@ -120,3 +122,36 @@ async def test_form_generic_auth_exception(hass):
) )
assert result2["type"] == "form" assert result2["type"] == "form"
assert result2["errors"] == {"base": "unknown"} assert result2["errors"] == {"base": "unknown"}
async def test_form_already_configured(hass):
"""Test we handle cannot connect error."""
mock_entry = MockConfigEntry(
domain=DOMAIN,
data={"username": "test-username", "password": "test-password"},
unique_id="test-username",
)
mock_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["step_id"] == config_entries.SOURCE_USER
with patch("homeassistant.components.whirlpool.config_flow.Auth.do_auth"), patch(
"homeassistant.components.whirlpool.config_flow.Auth.is_access_token_valid",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"username": "test-username",
"password": "test-password",
},
)
await hass.async_block_till_done()
assert result2["type"] == "abort"
assert result2["reason"] == "already_configured"