From 2314d15761e751dcc5fe8b590e71f720bfba4a7c Mon Sep 17 00:00:00 2001 From: Yann Le Moigne Date: Wed, 22 Feb 2023 15:54:18 +0100 Subject: [PATCH] Fix cover template: optimistic mode is ignored (#87925) * Fix cover template: optimistic mode is ignored (#84334) * Fix invalid check in is_closed (make test pass) * Add test for non optimistic cover * Update homeassistant/components/template/cover.py Co-authored-by: Erik Montnemery * Update test_cover.py * Fix format * Fix tests --------- Co-authored-by: Erik Montnemery --- homeassistant/components/template/cover.py | 7 +++-- tests/components/template/test_cover.py | 36 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/template/cover.py b/homeassistant/components/template/cover.py index e36ca75ed01..9aafc719f1b 100644 --- a/homeassistant/components/template/cover.py +++ b/homeassistant/components/template/cover.py @@ -172,7 +172,7 @@ class CoverTemplate(TemplateEntity, CoverEntity): self._tilt_script = Script(hass, tilt_action, friendly_name, DOMAIN) optimistic = config.get(CONF_OPTIMISTIC) self._optimistic = optimistic or ( - not self._template and not self._position_template + optimistic is None and not self._template and not self._position_template ) tilt_optimistic = config.get(CONF_TILT_OPTIMISTIC) self._tilt_optimistic = tilt_optimistic or not self._tilt_template @@ -270,8 +270,11 @@ class CoverTemplate(TemplateEntity, CoverEntity): self._tilt_value = state @property - def is_closed(self) -> bool: + def is_closed(self) -> bool | None: """Return if the cover is closed.""" + if self._position is None: + return None + return self._position == 0 @property diff --git a/tests/components/template/test_cover.py b/tests/components/template/test_cover.py index 8520fe9cc83..e89773d9988 100644 --- a/tests/components/template/test_cover.py +++ b/tests/components/template/test_cover.py @@ -21,6 +21,7 @@ from homeassistant.const import ( STATE_OPEN, STATE_OPENING, STATE_UNAVAILABLE, + STATE_UNKNOWN, ) from homeassistant.core import HomeAssistant @@ -80,7 +81,7 @@ OPEN_CLOSE_COVER_CONFIG = { ( "cover.test_state", "cat", - STATE_OPEN, + STATE_UNKNOWN, {}, -1, "Received invalid cover is_on state: cat", @@ -89,7 +90,7 @@ OPEN_CLOSE_COVER_CONFIG = { ( "cover.test_state", "bear", - STATE_OPEN, + STATE_UNKNOWN, {}, -1, "Received invalid cover is_on state: bear", @@ -112,8 +113,8 @@ OPEN_CLOSE_COVER_CONFIG = { } }, [ - ("cover.test_state", STATE_OPEN, STATE_OPEN, {}, -1, ""), - ("cover.test_state", STATE_CLOSED, STATE_OPEN, {}, -1, ""), + ("cover.test_state", STATE_OPEN, STATE_UNKNOWN, {}, -1, ""), + ("cover.test_state", STATE_CLOSED, STATE_UNKNOWN, {}, -1, ""), ("cover.test_state", STATE_OPENING, STATE_OPENING, {}, -1, ""), ("cover.test_state", STATE_CLOSING, STATE_CLOSING, {}, -1, ""), ("cover.test", STATE_CLOSED, STATE_CLOSING, {"position": 0}, 0, ""), @@ -136,7 +137,7 @@ async def test_template_state_text( ) -> None: """Test the state text of a template.""" state = hass.states.get("cover.test_template_cover") - assert state.state == STATE_OPEN + assert state.state == STATE_UNKNOWN for entity, set_state, test_state, attr, pos, text in states: hass.states.async_set(entity, set_state, attributes=attr) @@ -207,6 +208,29 @@ async def test_template_position(hass: HomeAssistant, start_ha) -> None: assert state.state == test_state +@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)]) +@pytest.mark.parametrize( + "config", + [ + { + DOMAIN: { + "platform": "template", + "covers": { + "test_template_cover": { + **OPEN_CLOSE_COVER_CONFIG, + "optimistic": False, + } + }, + } + }, + ], +) +async def test_template_not_optimistic(hass, start_ha): + """Test the is_closed attribute.""" + state = hass.states.get("cover.test_template_cover") + assert state.state == STATE_UNKNOWN + + @pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)]) @pytest.mark.parametrize( "config", @@ -428,7 +452,7 @@ async def test_set_position(hass: HomeAssistant, start_ha, calls) -> None: state = hass.states.async_set("input_number.test", 42) await hass.async_block_till_done() state = hass.states.get("cover.test_template_cover") - assert state.state == STATE_OPEN + assert state.state == STATE_UNKNOWN await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True