mirror of
https://github.com/home-assistant/core.git
synced 2026-05-23 09:15:45 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 605f9d9086 | |||
| 74e40af4bb | |||
| 833e15d6f2 | |||
| ee56fd1eb0 | |||
| e6528bae8a | |||
| a17eb65498 | |||
| 912a839d66 |
@@ -39,7 +39,6 @@ from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CLOUD_NEVER_EXPOSED_ENTITIES,
|
||||
CONF_DESCRIPTION,
|
||||
CONF_NAME,
|
||||
UnitOfTemperature,
|
||||
@@ -373,9 +372,6 @@ def async_get_entities(
|
||||
"""Return all entities that are supported by Alexa."""
|
||||
entities: list[AlexaEntity] = []
|
||||
for state in hass.states.async_all():
|
||||
if state.entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
continue
|
||||
|
||||
if state.domain not in ENTITY_ADAPTERS:
|
||||
continue
|
||||
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
"bluetooth-auto-recovery==1.5.3",
|
||||
"bluetooth-data-tools==1.29.11",
|
||||
"dbus-fast==5.0.3",
|
||||
"habluetooth==6.2.0"
|
||||
"habluetooth==6.4.0"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ from homeassistant.components.homeassistant.exposed_entities import (
|
||||
async_should_expose,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import Event, HomeAssistant, callback, split_entity_id
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er, start
|
||||
@@ -275,9 +274,6 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
|
||||
|
||||
def _should_expose_legacy(self, entity_id: str) -> bool:
|
||||
"""If an entity should be exposed."""
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
|
||||
entity_configs = self._prefs.alexa_entity_configs
|
||||
entity_config = entity_configs.get(entity_id, {})
|
||||
entity_expose: bool | None = entity_config.get(PREF_SHOULD_EXPOSE)
|
||||
@@ -308,8 +304,6 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
|
||||
"""If an entity should be exposed."""
|
||||
entity_filter: EntityFilter = self._config[CONF_FILTER]
|
||||
if not entity_filter.empty_filter:
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
return entity_filter(entity_id)
|
||||
|
||||
return async_should_expose(self.hass, CLOUD_ALEXA, entity_id)
|
||||
|
||||
@@ -22,7 +22,6 @@ from homeassistant.components.homeassistant.exposed_entities import (
|
||||
async_should_expose,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import (
|
||||
CoreState,
|
||||
Event,
|
||||
@@ -282,9 +281,6 @@ class CloudGoogleConfig(AbstractConfig):
|
||||
|
||||
def _should_expose_legacy(self, entity_id: str) -> bool:
|
||||
"""If an entity ID should be exposed."""
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
|
||||
entity_configs = self._prefs.google_entity_configs
|
||||
entity_config = entity_configs.get(entity_id, {})
|
||||
entity_expose: bool | None = entity_config.get(PREF_SHOULD_EXPOSE)
|
||||
@@ -316,8 +312,6 @@ class CloudGoogleConfig(AbstractConfig):
|
||||
"""If an entity should be exposed."""
|
||||
entity_filter: EntityFilter = self._config[CONF_FILTER]
|
||||
if not entity_filter.empty_filter:
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
return entity_filter(entity_id)
|
||||
|
||||
return async_should_expose(self.hass, CLOUD_GOOGLE, entity_id)
|
||||
|
||||
@@ -29,7 +29,6 @@ from homeassistant.components.homeassistant import exposed_entities
|
||||
from homeassistant.components.http import KEY_HASS, HomeAssistantView, require_admin
|
||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||
from homeassistant.components.system_health import get_info as get_system_health_info
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
@@ -973,7 +972,7 @@ async def google_assistant_get(
|
||||
return
|
||||
|
||||
entity = google_helpers.GoogleEntity(hass, gconf, state)
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES or not entity.is_supported():
|
||||
if not entity.is_supported():
|
||||
connection.send_error(
|
||||
msg["id"],
|
||||
websocket_api.ERR_NOT_SUPPORTED,
|
||||
@@ -1075,9 +1074,7 @@ async def alexa_get(
|
||||
"""Get data for a single alexa entity."""
|
||||
entity_id: str = msg["entity_id"]
|
||||
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES or not entity_supported_by_alexa(
|
||||
hass, entity_id
|
||||
):
|
||||
if not entity_supported_by_alexa(hass, entity_id):
|
||||
connection.send_error(
|
||||
msg["id"],
|
||||
websocket_api.ERR_NOT_SUPPORTED,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"mqtt": ["esphome/discover/#"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": [
|
||||
"aioesphomeapi==45.0.4",
|
||||
"aioesphomeapi==45.1.0",
|
||||
"esphome-dashboard-api==1.3.0",
|
||||
"bleak-esphome==3.7.3"
|
||||
],
|
||||
|
||||
@@ -18,7 +18,6 @@ from homeassistant.components import webhook
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
CLOUD_NEVER_EXPOSED_ENTITIES,
|
||||
CONF_NAME,
|
||||
STATE_UNAVAILABLE,
|
||||
)
|
||||
@@ -803,8 +802,6 @@ def async_get_entities(
|
||||
is_supported_cache = config.is_supported_cache
|
||||
for state in hass.states.async_all():
|
||||
entity_id = state.entity_id
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
continue
|
||||
# Check check inlined for performance to avoid
|
||||
# function calls for every entity since we enumerate
|
||||
# the entire state machine here
|
||||
|
||||
@@ -12,7 +12,6 @@ import jwt
|
||||
|
||||
from homeassistant.components import webhook
|
||||
from homeassistant.components.http import KEY_HASS, HomeAssistantView
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@@ -167,9 +166,6 @@ class GoogleConfig(AbstractConfig):
|
||||
# Ignore entities that are views
|
||||
return False
|
||||
|
||||
if state.entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
|
||||
entity_registry = er.async_get(self.hass)
|
||||
registry_entry = entity_registry.async_get(state.entity_id)
|
||||
if registry_entry:
|
||||
|
||||
@@ -116,7 +116,7 @@ async def _validate_auth(
|
||||
|
||||
def _get_current_hosts(entry: HeosConfigEntry) -> set[str]:
|
||||
"""Get a set of current hosts from the entry."""
|
||||
hosts = set(entry.data[CONF_HOST])
|
||||
hosts = {entry.data[CONF_HOST]}
|
||||
if hasattr(entry, "runtime_data"):
|
||||
hosts.update(
|
||||
player.ip_address
|
||||
|
||||
@@ -473,6 +473,7 @@ class HeosMediaPlayer(CoordinatorEntity[HeosCoordinator], MediaPlayerEntity):
|
||||
await self.coordinator.heos.set_group(new_members)
|
||||
return
|
||||
|
||||
@catch_action_error("remove from queue")
|
||||
async def async_remove_from_queue(self, queue_ids: list[int]) -> None:
|
||||
"""Remove items from the queue."""
|
||||
await self._player.remove_from_queue(queue_ids)
|
||||
|
||||
@@ -10,7 +10,6 @@ import voluptuous as vol
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback, split_entity_id
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@@ -246,9 +245,6 @@ class ExposedEntities:
|
||||
"""Return True if an entity should be exposed to an assistant."""
|
||||
should_expose: bool
|
||||
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES:
|
||||
return False
|
||||
|
||||
entity_registry = er.async_get(self._hass)
|
||||
if not (registry_entry := entity_registry.async_get(entity_id)):
|
||||
return self._async_should_expose_legacy_entity(assistant, entity_id)
|
||||
@@ -406,19 +402,6 @@ def ws_expose_entity(
|
||||
"""Expose an entity to an assistant."""
|
||||
entity_ids: list[str] = msg["entity_ids"]
|
||||
|
||||
if blocked := next(
|
||||
(
|
||||
entity_id
|
||||
for entity_id in entity_ids
|
||||
if entity_id in CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
),
|
||||
None,
|
||||
):
|
||||
connection.send_error(
|
||||
msg["id"], websocket_api.ERR_NOT_ALLOWED, f"can't expose '{blocked}'"
|
||||
)
|
||||
return
|
||||
|
||||
for entity_id in entity_ids:
|
||||
for assistant in msg["assistants"]:
|
||||
async_expose_entity(hass, assistant, entity_id, msg["should_expose"])
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"cannot_connect": {
|
||||
"message": "Failed to connect to OpenRGB SDK server {server_address}: {error}"
|
||||
},
|
||||
"communication_error": {
|
||||
"message": "Failed to communicate with OpenRGB SDK server {server_address}: {error}"
|
||||
},
|
||||
|
||||
@@ -946,10 +946,6 @@ PRECISION_WHOLE: Final = 1
|
||||
PRECISION_HALVES: Final = 0.5
|
||||
PRECISION_TENTHS: Final = 0.1
|
||||
|
||||
# Static list of entities that will never be exposed to
|
||||
# cloud, alexa, or google_home components
|
||||
CLOUD_NEVER_EXPOSED_ENTITIES: Final[list[str]] = ["group.all_locks"]
|
||||
|
||||
|
||||
class EntityCategory(StrEnum):
|
||||
"""Category of an entity.
|
||||
|
||||
@@ -35,7 +35,7 @@ file-read-backwards==2.0.0
|
||||
fnv-hash-fast==2.0.2
|
||||
go2rtc-client==0.4.0
|
||||
ha-ffmpeg==3.2.2
|
||||
habluetooth==6.2.0
|
||||
habluetooth==6.4.0
|
||||
hass-nabucasa==2.2.0
|
||||
hassil==3.5.0
|
||||
home-assistant-bluetooth==2.0.0
|
||||
|
||||
Generated
+2
-2
@@ -254,7 +254,7 @@ aioelectricitymaps==1.1.1
|
||||
aioemonitor==1.0.5
|
||||
|
||||
# homeassistant.components.esphome
|
||||
aioesphomeapi==45.0.4
|
||||
aioesphomeapi==45.1.0
|
||||
|
||||
# homeassistant.components.matrix
|
||||
# homeassistant.components.slack
|
||||
@@ -1210,7 +1210,7 @@ ha-xthings-cloud==1.0.5
|
||||
habiticalib==0.4.7
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
habluetooth==6.2.0
|
||||
habluetooth==6.4.0
|
||||
|
||||
# homeassistant.components.hanna
|
||||
hanna-cloud==0.0.7
|
||||
|
||||
@@ -3662,31 +3662,6 @@ async def test_include_filters(hass: HomeAssistant) -> None:
|
||||
assert len(msg["payload"]["endpoints"]) == 3
|
||||
|
||||
|
||||
async def test_never_exposed_entities(hass: HomeAssistant) -> None:
|
||||
"""Test never exposed locks do not get discovered."""
|
||||
request = get_new_request("Alexa.Discovery", "Discover")
|
||||
|
||||
# setup test devices
|
||||
hass.states.async_set("group.all_locks", "on", {"friendly_name": "Blocked locks"})
|
||||
|
||||
hass.states.async_set("group.allow", "off", {"friendly_name": "Allowed group"})
|
||||
|
||||
alexa_config = MockConfig(hass)
|
||||
alexa_config.should_expose = entityfilter.generate_filter(
|
||||
include_domains=["group"],
|
||||
include_entities=[],
|
||||
exclude_domains=[],
|
||||
exclude_entities=[],
|
||||
)
|
||||
|
||||
msg = await smart_home.async_handle_message(hass, alexa_config, request)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
msg = msg["event"]
|
||||
|
||||
assert len(msg["payload"]["endpoints"]) == 1
|
||||
|
||||
|
||||
async def test_api_entity_not_exists(hass: HomeAssistant) -> None:
|
||||
"""Test api turn on process without entity."""
|
||||
request = get_new_request("Alexa.PowerController", "TurnOn", "switch#test")
|
||||
|
||||
@@ -104,7 +104,6 @@ async def test_handler_google_actions(hass: HomeAssistant) -> None:
|
||||
"""Test handler Google Actions."""
|
||||
hass.states.async_set("switch.test", "on", {"friendly_name": "Test switch"})
|
||||
hass.states.async_set("switch.test2", "on", {"friendly_name": "Test switch 2"})
|
||||
hass.states.async_set("group.all_locks", "on", {"friendly_name": "Evil locks"})
|
||||
|
||||
await mock_cloud(
|
||||
hass,
|
||||
|
||||
@@ -1418,23 +1418,6 @@ async def test_get_google_entity(
|
||||
"message": "light.kitchen unknown",
|
||||
}
|
||||
|
||||
# Test getting a blocked entity
|
||||
entity_registry.async_get_or_create(
|
||||
"group", "test", "unique", suggested_object_id="all_locks"
|
||||
)
|
||||
hass.states.async_set("group.all_locks", "bla")
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{"type": "cloud/google_assistant/entities/get", "entity_id": "group.all_locks"}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
|
||||
assert not response["success"]
|
||||
assert response["error"] == {
|
||||
"code": "not_supported",
|
||||
"message": "group.all_locks not supported by Google assistant",
|
||||
}
|
||||
|
||||
entity_registry.async_get_or_create(
|
||||
"light", "test", "unique", suggested_object_id="kitchen"
|
||||
)
|
||||
@@ -1617,23 +1600,6 @@ async def test_get_alexa_entity(
|
||||
"message": "sensor.temperature not supported by Alexa",
|
||||
}
|
||||
|
||||
# Test getting a blocked entity
|
||||
entity_registry.async_get_or_create(
|
||||
"group", "test", "unique", suggested_object_id="all_locks"
|
||||
)
|
||||
hass.states.async_set("group.all_locks", "bla")
|
||||
|
||||
await client.send_json_auto_id(
|
||||
{"type": "cloud/alexa/entities/get", "entity_id": "group.all_locks"}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
|
||||
assert not response["success"]
|
||||
assert response["error"] == {
|
||||
"code": "not_supported",
|
||||
"message": "group.all_locks not supported by Alexa",
|
||||
}
|
||||
|
||||
entity_registry.async_get_or_create(
|
||||
"light", "test", "unique", suggested_object_id="kitchen"
|
||||
)
|
||||
|
||||
@@ -626,15 +626,20 @@ async def test_migration_from_future_version(
|
||||
assert config_entry.state is ConfigEntryState.MIGRATION_ERROR
|
||||
|
||||
|
||||
async def test_migration_1_2(hass: HomeAssistant) -> None:
|
||||
@pytest.mark.usefixtures("sensor_device")
|
||||
async def test_migration_1_2(
|
||||
hass: HomeAssistant,
|
||||
sensor_entity_entry: er.RegistryEntry,
|
||||
switch_entity_entry: er.RegistryEntry,
|
||||
) -> None:
|
||||
"""Test migration from 1.2 to 1.3 copies CONF_MIN_DUR to CONF_DUR_COOLDOWN."""
|
||||
config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=DOMAIN,
|
||||
options={
|
||||
"name": "My generic thermostat",
|
||||
"heater": "switch.test",
|
||||
"target_sensor": "sensor.test",
|
||||
"heater": switch_entity_entry.entity_id,
|
||||
"target_sensor": sensor_entity_entry.entity_id,
|
||||
CONF_MIN_DUR: {"hours": 0, "minutes": 5, "seconds": 0},
|
||||
"ac_mode": False,
|
||||
"cold_tolerance": 0.3,
|
||||
@@ -646,9 +651,10 @@ async def test_migration_1_2(hass: HomeAssistant) -> None:
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
# Run migration
|
||||
result = await generic_thermostat.async_migrate_entry(hass, config_entry)
|
||||
assert result is True
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
# After migration, cooldown should be set to min_cycle_duration
|
||||
# and minor version bumped
|
||||
@@ -657,4 +663,5 @@ async def test_migration_1_2(hass: HomeAssistant) -> None:
|
||||
"minutes": 5,
|
||||
"seconds": 0,
|
||||
}
|
||||
assert config_entry.version == 1
|
||||
assert config_entry.minor_version == 3
|
||||
|
||||
@@ -15,7 +15,7 @@ from homeassistant.components import (
|
||||
light,
|
||||
media_player,
|
||||
)
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES, EntityCategory, Platform
|
||||
from homeassistant.const import EntityCategory, Platform
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||
|
||||
@@ -146,9 +146,6 @@ async def test_sync_request(
|
||||
dev["id"] for dev in DEMO_DEVICES
|
||||
)
|
||||
|
||||
for dev in devices:
|
||||
assert dev["id"] not in CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
|
||||
for dev, demo in zip(
|
||||
sorted(devices, key=lambda d: d["id"]),
|
||||
sorted(DEMO_DEVICES, key=lambda d: d["id"]),
|
||||
|
||||
@@ -28,11 +28,7 @@ from homeassistant.components.google_assistant.http import (
|
||||
_get_homegraph_token,
|
||||
async_get_users,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CLOUD_NEVER_EXPOSED_ENTITIES,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
)
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.core import CoreState, HomeAssistant, State
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
@@ -366,8 +362,6 @@ async def test_should_expose(hass: HomeAssistant) -> None:
|
||||
# Wait for google_assistant.helpers.async_initialize.sync_google to be called
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config.should_expose(State(CLOUD_NEVER_EXPOSED_ENTITIES[0], "mock")) is False
|
||||
|
||||
|
||||
async def test_missing_service_account(hass: HomeAssistant) -> None:
|
||||
"""Test the google config _async_request_sync_devices."""
|
||||
|
||||
@@ -13,7 +13,7 @@ from homeassistant.components.homeassistant.exposed_entities import (
|
||||
async_listen_entity_updates,
|
||||
async_should_expose,
|
||||
)
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES, EntityCategory
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@@ -39,10 +39,10 @@ def entities_fixture(
|
||||
|
||||
def entities_unique_id(entity_registry: er.EntityRegistry) -> dict[str, str]:
|
||||
"""Create some entities in the entity registry."""
|
||||
entry_blocked = entity_registry.async_get_or_create(
|
||||
entry_group = entity_registry.async_get_or_create(
|
||||
"group", "test", "unique", suggested_object_id="all_locks"
|
||||
)
|
||||
assert entry_blocked.entity_id == CLOUD_NEVER_EXPOSED_ENTITIES[0]
|
||||
assert entry_group.entity_id == "group.all_locks"
|
||||
entry_lock = entity_registry.async_get_or_create("lock", "test", "unique1")
|
||||
entry_binary_sensor = entity_registry.async_get_or_create(
|
||||
"binary_sensor", "test", "unique1"
|
||||
@@ -64,7 +64,7 @@ def entities_unique_id(entity_registry: er.EntityRegistry) -> dict[str, str]:
|
||||
"media_player", "test", "unique4", original_device_class="media_player"
|
||||
)
|
||||
return {
|
||||
"blocked": entry_blocked.entity_id,
|
||||
"group": entry_group.entity_id,
|
||||
"lock": entry_lock.entity_id,
|
||||
"binary_sensor": entry_binary_sensor.entity_id,
|
||||
"door_sensor": entry_binary_sensor_door.entity_id,
|
||||
@@ -76,7 +76,7 @@ def entities_unique_id(entity_registry: er.EntityRegistry) -> dict[str, str]:
|
||||
|
||||
def entities_no_unique_id(hass: HomeAssistant) -> dict[str, str]:
|
||||
"""Create some entities not in the entity registry."""
|
||||
blocked = CLOUD_NEVER_EXPOSED_ENTITIES[0]
|
||||
group = "group.all_locks"
|
||||
lock = "lock.test"
|
||||
binary_sensor = "binary_sensor.test"
|
||||
door_sensor = "binary_sensor.door"
|
||||
@@ -89,7 +89,7 @@ def entities_no_unique_id(hass: HomeAssistant) -> dict[str, str]:
|
||||
hass.states.async_set(sensor_temperature, "on", {"device_class": "temperature"})
|
||||
hass.states.async_set(media_player, "idle", {})
|
||||
return {
|
||||
"blocked": blocked,
|
||||
"group": group,
|
||||
"lock": lock,
|
||||
"binary_sensor": binary_sensor,
|
||||
"door_sensor": door_sensor,
|
||||
@@ -248,33 +248,6 @@ async def test_expose_entity_unknown(
|
||||
}
|
||||
|
||||
|
||||
async def test_expose_entity_blocked(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test behavior when exposing a blocked entity."""
|
||||
ws_client = await hass_ws_client(hass)
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Set options
|
||||
await ws_client.send_json_auto_id(
|
||||
{
|
||||
"type": "homeassistant/expose_entity",
|
||||
"assistants": ["cloud.alexa"],
|
||||
"entity_ids": ["group.all_locks"],
|
||||
"should_expose": True,
|
||||
}
|
||||
)
|
||||
|
||||
response = await ws_client.receive_json()
|
||||
assert not response["success"]
|
||||
assert response["error"] == {
|
||||
"code": "not_allowed",
|
||||
"message": "can't expose 'group.all_locks'",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expose_new", [True, False])
|
||||
async def test_expose_new_entities(
|
||||
hass: HomeAssistant,
|
||||
@@ -414,8 +387,8 @@ async def test_should_expose(
|
||||
# Unknown entity is not exposed
|
||||
assert async_should_expose(hass, "test.test", "test.test") is False
|
||||
|
||||
# Blocked entity is not exposed
|
||||
assert async_should_expose(hass, "cloud.alexa", entities["blocked"]) is False
|
||||
# Group entity is not exposed
|
||||
assert async_should_expose(hass, "cloud.alexa", entities["group"]) is False
|
||||
|
||||
# Lock is not exposed
|
||||
assert async_should_expose(hass, "cloud.alexa", entities["lock"]) is False
|
||||
|
||||
@@ -8,9 +8,10 @@ import pytest
|
||||
from homeassistant.components.labs import (
|
||||
EVENT_LABS_UPDATED,
|
||||
async_is_preview_feature_enabled,
|
||||
async_setup,
|
||||
)
|
||||
from homeassistant.components.labs.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import assert_stored_labs_data
|
||||
|
||||
@@ -48,7 +49,7 @@ async def test_websocket_list_preview_features(
|
||||
if load_integration:
|
||||
hass.config.components.add("kitchen_sink")
|
||||
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -68,7 +69,7 @@ async def test_websocket_update_preview_feature_enable(
|
||||
"""Test enabling a preview feature via WebSocket."""
|
||||
# Load kitchen_sink integration
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -132,7 +133,7 @@ async def test_websocket_update_preview_feature_disable(
|
||||
}
|
||||
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -164,7 +165,7 @@ async def test_websocket_update_nonexistent_feature(
|
||||
hass_storage: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test updating a preview feature that doesn't exist."""
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -193,7 +194,7 @@ async def test_websocket_update_unavailable_preview_feature(
|
||||
) -> None:
|
||||
"""Test updating a preview feature whose integration is not loaded still works."""
|
||||
# Don't load kitchen_sink integration
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -235,7 +236,7 @@ async def test_websocket_requires_admin(
|
||||
hass_admin_user.groups = []
|
||||
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -264,7 +265,7 @@ async def test_websocket_update_validates_enabled_parameter(
|
||||
) -> None:
|
||||
"""Test that enabled parameter must be boolean."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -291,7 +292,7 @@ async def test_storage_persists_preview_feature_across_calls(
|
||||
) -> None:
|
||||
"""Test that storage persists preview feature state across multiple calls."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -350,7 +351,7 @@ async def test_preview_feature_urls_present(
|
||||
) -> None:
|
||||
"""Test that preview features include feedback and report URLs."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -401,7 +402,7 @@ async def test_websocket_update_preview_feature_backup_scenarios(
|
||||
) -> None:
|
||||
"""Test various backup scenarios when updating preview features."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -463,7 +464,7 @@ async def test_websocket_list_multiple_enabled_features(
|
||||
}
|
||||
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -484,7 +485,7 @@ async def test_websocket_update_rapid_toggle(
|
||||
) -> None:
|
||||
"""Test rapid toggling of a preview feature."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -534,7 +535,7 @@ async def test_websocket_update_same_state_idempotent(
|
||||
) -> None:
|
||||
"""Test that enabling an already-enabled feature is idempotent."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -572,7 +573,7 @@ async def test_websocket_list_filtered_by_loaded_components(
|
||||
) -> None:
|
||||
"""Test that list only shows features from loaded integrations."""
|
||||
# Don't load kitchen_sink - its preview feature shouldn't appear
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -600,7 +601,7 @@ async def test_websocket_update_with_missing_required_field(
|
||||
) -> None:
|
||||
"""Test that missing required fields are rejected."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -625,7 +626,7 @@ async def test_websocket_event_data_structure(
|
||||
) -> None:
|
||||
"""Test that event data has correct structure."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -666,7 +667,7 @@ async def test_websocket_backup_timeout_handling(
|
||||
) -> None:
|
||||
"""Test handling of backup timeout/long-running backup."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -702,7 +703,7 @@ async def test_websocket_subscribe_feature(
|
||||
) -> None:
|
||||
"""Test subscribing to a specific preview feature."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -739,7 +740,7 @@ async def test_websocket_subscribe_feature_receives_updates(
|
||||
) -> None:
|
||||
"""Test that subscription receives updates when feature is toggled."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -793,7 +794,7 @@ async def test_websocket_subscribe_nonexistent_feature(
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test subscribing to a preview feature that doesn't exist."""
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -821,7 +822,7 @@ async def test_websocket_subscribe_does_not_require_admin(
|
||||
hass_admin_user.groups = []
|
||||
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
@@ -847,7 +848,7 @@ async def test_websocket_subscribe_only_receives_subscribed_feature_updates(
|
||||
) -> None:
|
||||
"""Test that subscription only receives updates for the subscribed feature."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
assert await async_setup(hass, {})
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
|
||||
Reference in New Issue
Block a user