mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 09:38:58 +01:00
Fix optimistic set to false for template entities (#150421)
This commit is contained in:
@@ -34,16 +34,20 @@ class AbstractTemplateEntity(Entity):
|
||||
self._action_scripts: dict[str, Script] = {}
|
||||
|
||||
if self._optimistic_entity:
|
||||
optimistic = config.get(CONF_OPTIMISTIC)
|
||||
|
||||
self._template = config.get(CONF_STATE)
|
||||
|
||||
optimistic = self._template is None
|
||||
assumed_optimistic = self._template is None
|
||||
if self._extra_optimistic_options:
|
||||
optimistic = optimistic and all(
|
||||
assumed_optimistic = assumed_optimistic and all(
|
||||
config.get(option) is None
|
||||
for option in self._extra_optimistic_options
|
||||
)
|
||||
|
||||
self._attr_assumed_state = optimistic or config.get(CONF_OPTIMISTIC, False)
|
||||
self._attr_assumed_state = optimistic or (
|
||||
optimistic is None and assumed_optimistic
|
||||
)
|
||||
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
|
||||
@@ -102,7 +102,7 @@ TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA = vol.Schema(
|
||||
|
||||
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA = {
|
||||
vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -973,3 +973,35 @@ async def test_optimistic(hass: HomeAssistant) -> None:
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == AlarmControlPanelState.ARMED_HOME
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "panel_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ states('alarm_control_panel.test') }}",
|
||||
**OPTIMISTIC_TEMPLATE_ALARM_CONFIG,
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_panel")
|
||||
async def test_not_optimistic(hass: HomeAssistant) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
ALARM_DOMAIN,
|
||||
"alarm_arm_away",
|
||||
{"entity_id": TEST_ENTITY_ID, "code": "1234"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
@@ -628,11 +628,38 @@ async def test_template_position(
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_cover")
|
||||
async def test_template_not_optimistic(hass: HomeAssistant) -> None:
|
||||
async def test_template_not_optimistic(
|
||||
hass: HomeAssistant,
|
||||
calls: list[ServiceCall],
|
||||
) -> None:
|
||||
"""Test the is_closed attribute."""
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test to make sure optimistic is not set with only a position template.
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test to make sure optimistic is not set with only a position template.
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{ATTR_ENTITY_ID: TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("count", "state_template"), [(1, "{{ 1 == 1 }}")])
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1885,6 +1885,39 @@ async def test_optimistic_option(hass: HomeAssistant) -> None:
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "fan_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ is_state('sensor.test_sensor', 'on') }}",
|
||||
"turn_on": [],
|
||||
"turn_off": [],
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_fan")
|
||||
async def test_not_optimistic(hass: HomeAssistant) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
fan.DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
@@ -2795,6 +2795,42 @@ async def test_optimistic_option(hass: HomeAssistant) -> None:
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "light_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ is_state('light.test_state', 'on') }}",
|
||||
"turn_on": [],
|
||||
"turn_off": [],
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("style", "expected"),
|
||||
[
|
||||
(ConfigurationStyle.MODERN, STATE_OFF),
|
||||
(ConfigurationStyle.TRIGGER, STATE_UNKNOWN),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_light")
|
||||
async def test_not_optimistic(hass: HomeAssistant, expected: str) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
light.DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == expected
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
@@ -1190,6 +1190,39 @@ async def test_optimistic(hass: HomeAssistant) -> None:
|
||||
assert state.state == LockState.UNLOCKED
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "lock_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ is_state('sensor.test_state', 'on') }}",
|
||||
"lock": [],
|
||||
"unlock": [],
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_lock")
|
||||
async def test_not_optimistic(hass: HomeAssistant) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
lock.DOMAIN,
|
||||
lock.SERVICE_LOCK,
|
||||
{ATTR_ENTITY_ID: TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == LockState.UNLOCKED
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
@@ -605,6 +605,37 @@ async def test_optimistic(hass: HomeAssistant) -> None:
|
||||
assert float(state.state) == 2
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "number_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"state": "{{ states('sensor.test_state') }}",
|
||||
"optimistic": False,
|
||||
"set_value": [],
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_number")
|
||||
async def test_not_optimistic(hass: HomeAssistant) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
number.DOMAIN,
|
||||
number.SERVICE_SET_VALUE,
|
||||
{ATTR_ENTITY_ID: _TEST_NUMBER, "value": 4},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(_TEST_NUMBER)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "number_config"),
|
||||
[
|
||||
|
||||
@@ -601,6 +601,42 @@ async def test_optimistic(hass: HomeAssistant) -> None:
|
||||
assert state.state == "yes"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "select_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"state": "{{ states('select.test_state') }}",
|
||||
"optimistic": False,
|
||||
"options": "{{ ['test', 'yes', 'no'] }}",
|
||||
"select_option": [],
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_select")
|
||||
async def test_not_optimistic(hass: HomeAssistant) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
# Ensure Trigger template entities update the options list
|
||||
hass.states.async_set(TEST_STATE_ENTITY_ID, "anything")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
select.DOMAIN,
|
||||
select.SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: _TEST_SELECT, "option": "test"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(_TEST_SELECT)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "select_config"),
|
||||
[
|
||||
|
||||
@@ -14,6 +14,7 @@ from homeassistant.const import (
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
from homeassistant.core import CoreState, HomeAssistant, ServiceCall, State
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
@@ -1267,3 +1268,39 @@ async def test_optimistic_option(hass: HomeAssistant) -> None:
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "switch_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ is_state('switch.test_state', 'on') }}",
|
||||
"turn_on": [],
|
||||
"turn_off": [],
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("style", "expected"),
|
||||
[
|
||||
(ConfigurationStyle.MODERN, STATE_OFF),
|
||||
(ConfigurationStyle.TRIGGER, STATE_UNKNOWN),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_switch")
|
||||
async def test_not_optimistic(hass: HomeAssistant, expected: str) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
switch.DOMAIN,
|
||||
"turn_on",
|
||||
{"entity_id": TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == expected
|
||||
|
||||
@@ -1299,6 +1299,54 @@ async def test_optimistic_option(
|
||||
assert state.state == VacuumActivity.DOCKED
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("count", "vacuum_config"),
|
||||
[
|
||||
(
|
||||
1,
|
||||
{
|
||||
"name": TEST_OBJECT_ID,
|
||||
"state": "{{ states('sensor.test_state') }}",
|
||||
"start": [],
|
||||
**TEMPLATE_VACUUM_ACTIONS,
|
||||
"optimistic": False,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"style",
|
||||
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"service",
|
||||
[
|
||||
vacuum.SERVICE_START,
|
||||
vacuum.SERVICE_PAUSE,
|
||||
vacuum.SERVICE_STOP,
|
||||
vacuum.SERVICE_RETURN_TO_BASE,
|
||||
vacuum.SERVICE_CLEAN_SPOT,
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("setup_vacuum")
|
||||
async def test_not_optimistic(
|
||||
hass: HomeAssistant,
|
||||
service: str,
|
||||
calls: list[ServiceCall],
|
||||
) -> None:
|
||||
"""Test optimistic yaml option set to false."""
|
||||
await hass.services.async_call(
|
||||
vacuum.DOMAIN,
|
||||
service,
|
||||
{"entity_id": TEST_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
Reference in New Issue
Block a user