Fix template fan default speed count (#48389)

* Fix template fan default speed count

The default speed count was defaulting to 3 when percentage
was implemented instead of the documented value of 100

* Increase coverage

* remove unreachable code
This commit is contained in:
J. Nick Koston 2021-03-28 21:33:56 -10:00 committed by GitHub
parent 7063306cd8
commit 564688af25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 267 additions and 7 deletions

View file

@ -422,21 +422,21 @@ class FanEntity(ToggleEntity):
return self.speed not in [SPEED_OFF, None]
@property
def _implemented_percentage(self):
def _implemented_percentage(self) -> bool:
"""Return true if percentage has been implemented."""
return not hasattr(self.set_percentage, _FAN_NATIVE) or not hasattr(
self.async_set_percentage, _FAN_NATIVE
)
@property
def _implemented_preset_mode(self):
def _implemented_preset_mode(self) -> bool:
"""Return true if preset_mode has been implemented."""
return not hasattr(self.set_preset_mode, _FAN_NATIVE) or not hasattr(
self.async_set_preset_mode, _FAN_NATIVE
)
@property
def _implemented_speed(self):
def _implemented_speed(self) -> bool:
"""Return true if speed has been implemented."""
return not hasattr(self.set_speed, _FAN_NATIVE) or not hasattr(
self.async_set_speed, _FAN_NATIVE

View file

@ -272,6 +272,11 @@ class TemplateFan(TemplateEntity, FanEntity):
# List of valid preset modes
self._preset_modes = preset_modes
@property
def _implemented_speed(self):
"""Return true if speed has been implemented."""
return bool(self._set_speed_script or self._speed_template)
@property
def name(self):
"""Return the display name of this fan."""
@ -290,7 +295,7 @@ class TemplateFan(TemplateEntity, FanEntity):
@property
def speed_count(self) -> int:
"""Return the number of speeds the fan supports."""
return self._speed_count or super().speed_count
return self._speed_count or 100
@property
def speed_list(self) -> list:

View file

@ -654,8 +654,8 @@ async def test_set_percentage(hass, calls):
async def test_increase_decrease_speed(hass, calls):
"""Test set valid increase and derease speed."""
await _register_components(hass)
"""Test set valid increase and decrease speed."""
await _register_components(hass, speed_count=3)
# Turn on fan
await common.async_turn_on(hass, _TEST_FAN)
@ -693,6 +693,42 @@ async def test_increase_decrease_speed(hass, calls):
_verify(hass, STATE_ON, SPEED_LOW, 33, None, None, None)
async def test_increase_decrease_speed_default_speed_count(hass, calls):
"""Test set valid increase and decrease speed."""
await _register_components(
hass,
)
# Turn on fan
await common.async_turn_on(hass, _TEST_FAN)
# Set fan's percentage speed to 100
await common.async_set_percentage(hass, _TEST_FAN, 100)
# verify
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 100
_verify(hass, STATE_ON, SPEED_HIGH, 100, None, None, None)
# Set fan's percentage speed to 99
await common.async_decrease_speed(hass, _TEST_FAN)
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 99
_verify(hass, STATE_ON, SPEED_HIGH, 99, None, None, None)
# Set fan's percentage speed to 98
await common.async_decrease_speed(hass, _TEST_FAN)
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 98
_verify(hass, STATE_ON, SPEED_HIGH, 98, None, None, None)
for _ in range(32):
await common.async_decrease_speed(hass, _TEST_FAN)
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 66
_verify(hass, STATE_ON, SPEED_MEDIUM, 66, None, None, None)
async def test_set_invalid_speed_from_initial_stage(hass, calls):
"""Test set invalid speed when fan is in initial state."""
await _register_components(hass)
@ -926,7 +962,9 @@ def _verify(
assert attributes.get(ATTR_PRESET_MODE) == expected_preset_mode
async def _register_components(hass, speed_list=None, preset_modes=None):
async def _register_components(
hass, speed_list=None, preset_modes=None, speed_count=None
):
"""Register basic components for testing."""
with assert_setup_component(1, "input_boolean"):
assert await setup.async_setup_component(
@ -1051,6 +1089,9 @@ async def _register_components(hass, speed_list=None, preset_modes=None):
if preset_modes:
test_fan_config["preset_modes"] = preset_modes
if speed_count:
test_fan_config["speed_count"] = speed_count
assert await setup.async_setup_component(
hass,
"fan",
@ -1105,3 +1146,217 @@ async def test_unique_id(hass):
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
@pytest.mark.parametrize(
"speed_count, percentage_step", [(0, 1), (100, 1), (3, 100 / 3)]
)
async def test_implemented_percentage(hass, speed_count, percentage_step):
"""Test a fan that implements percentage."""
await setup.async_setup_component(
hass,
"fan",
{
"fan": {
"platform": "template",
"fans": {
"mechanical_ventilation": {
"friendly_name": "Mechanische ventilatie",
"unique_id": "a2fd2e38-674b-4b47-b5ef-cc2362211a72",
"value_template": "{{ states('light.mv_snelheid') }}",
"percentage_template": "{{ (state_attr('light.mv_snelheid','brightness') | int / 255 * 100) | int }}",
"turn_on": [
{
"service": "switch.turn_off",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": 40},
},
],
"turn_off": [
{
"service": "light.turn_off",
"target": {
"entity_id": "light.mv_snelheid",
},
},
{
"service": "switch.turn_on",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
],
"set_percentage": [
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": "{{ percentage }}"},
}
],
"speed_count": speed_count,
},
},
},
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
state = hass.states.get("fan.mechanical_ventilation")
attributes = state.attributes
assert attributes["percentage_step"] == percentage_step
async def test_implemented_preset_mode(hass):
"""Test a fan that implements preset_mode."""
await setup.async_setup_component(
hass,
"fan",
{
"fan": {
"platform": "template",
"fans": {
"mechanical_ventilation": {
"friendly_name": "Mechanische ventilatie",
"unique_id": "a2fd2e38-674b-4b47-b5ef-cc2362211a72",
"value_template": "{{ states('light.mv_snelheid') }}",
"preset_mode_template": "{{ 'any' }}",
"preset_modes": ["any"],
"set_preset_mode": [
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": "{{ percentage }}"},
}
],
"turn_on": [
{
"service": "switch.turn_off",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": 40},
},
],
"turn_off": [
{
"service": "light.turn_off",
"target": {
"entity_id": "light.mv_snelheid",
},
},
{
"service": "switch.turn_on",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
],
},
},
},
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
state = hass.states.get("fan.mechanical_ventilation")
attributes = state.attributes
assert attributes["percentage"] is None
async def test_implemented_speed(hass):
"""Test a fan that implements speed."""
await setup.async_setup_component(
hass,
"fan",
{
"fan": {
"platform": "template",
"fans": {
"mechanical_ventilation": {
"friendly_name": "Mechanische ventilatie",
"unique_id": "a2fd2e38-674b-4b47-b5ef-cc2362211a72",
"value_template": "{{ states('light.mv_snelheid') }}",
"speed_template": "{{ 'fast' }}",
"speeds": ["slow", "fast"],
"set_preset_mode": [
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": "{{ percentage }}"},
}
],
"turn_on": [
{
"service": "switch.turn_off",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
{
"service": "light.turn_on",
"target": {
"entity_id": "light.mv_snelheid",
},
"data": {"brightness_pct": 40},
},
],
"turn_off": [
{
"service": "light.turn_off",
"target": {
"entity_id": "light.mv_snelheid",
},
},
{
"service": "switch.turn_on",
"target": {
"entity_id": "switch.mv_automatisch",
},
},
],
},
},
},
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
state = hass.states.get("fan.mechanical_ventilation")
attributes = state.attributes
assert attributes["percentage"] == 100
assert attributes["speed"] == "fast"