mirror of
https://github.com/home-assistant/core.git
synced 2026-05-23 17:25:10 +02:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2a3f09dea | |||
| 900f5469bc | |||
| 1f541ed9d0 | |||
| 852c98b5d4 | |||
| 833e15d6f2 | |||
| ee56fd1eb0 | |||
| e6528bae8a | |||
| a17eb65498 | |||
| 912a839d66 | |||
| 65b2348e99 | |||
| 1f97b39bad | |||
| 0b5a8a0426 | |||
| d892c76f49 |
@@ -130,17 +130,26 @@ def async_register_callback(
|
||||
callback: BluetoothCallback,
|
||||
match_dict: BluetoothCallbackMatcher | None,
|
||||
mode: BluetoothScanningMode,
|
||||
*,
|
||||
scan_interval: float | None = None,
|
||||
scan_duration: float | None = None,
|
||||
) -> Callable[[], None]:
|
||||
"""Register to receive a callback on bluetooth change.
|
||||
|
||||
mode is currently not used as we only support active scanning.
|
||||
Passive scanning will be available in the future. The flag
|
||||
is required to be present to avoid a future breaking change
|
||||
when we support passive scanning.
|
||||
When ``mode`` is not PASSIVE and ``match_dict["address"]`` is set,
|
||||
the address is registered with habluetooth's active-scan scheduler
|
||||
so AUTO-mode scanners flip ACTIVE on demand for that device.
|
||||
``scan_interval`` / ``scan_duration`` default to habluetooth's
|
||||
DEFAULT_ACTIVE_SCAN_* (5 minutes / 10 seconds) when not provided;
|
||||
integrations that need a different cadence can pass explicit
|
||||
values. Without an address in the matcher the active-scan request
|
||||
is skipped; the callback itself still fires normally.
|
||||
|
||||
Returns a callback that can be used to cancel the registration.
|
||||
"""
|
||||
return _get_manager(hass).async_register_callback(callback, match_dict)
|
||||
return _get_manager(hass).async_register_callback(
|
||||
callback, match_dict, mode, scan_interval, scan_duration
|
||||
)
|
||||
|
||||
|
||||
async def async_process_advertisements(
|
||||
@@ -161,7 +170,7 @@ async def async_process_advertisements(
|
||||
done.set_result(service_info)
|
||||
|
||||
unload = _get_manager(hass).async_register_callback(
|
||||
_async_discovered_device, match_dict
|
||||
_async_discovered_device, match_dict, mode, scan_duration=timeout
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -202,6 +202,9 @@ class HomeAssistantBluetoothManager(BluetoothManager):
|
||||
self,
|
||||
callback: BluetoothCallback,
|
||||
matcher: BluetoothCallbackMatcher | None,
|
||||
mode: BluetoothScanningMode = BluetoothScanningMode.ACTIVE,
|
||||
scan_interval: float | None = None,
|
||||
scan_duration: float | None = None,
|
||||
) -> Callable[[], None]:
|
||||
"""Register a callback."""
|
||||
callback_matcher = BluetoothCallbackMatcherWithCallback(callback=callback)
|
||||
@@ -216,15 +219,31 @@ class HomeAssistantBluetoothManager(BluetoothManager):
|
||||
connectable = callback_matcher[CONNECTABLE]
|
||||
self._callback_index.add_callback_matcher(callback_matcher)
|
||||
|
||||
# If the matcher targets a specific address and the caller
|
||||
# didn't explicitly ask for PASSIVE, wire it into habluetooth's
|
||||
# active-scan scheduler so AUTO-mode scanners flip ACTIVE on
|
||||
# demand for this device. ``scan_interval``/``scan_duration``
|
||||
# default to habluetooth's DEFAULT_ACTIVE_SCAN_* when None.
|
||||
cancel_active_scan: Callable[[], None] | None = None
|
||||
if (
|
||||
mode is not BluetoothScanningMode.PASSIVE
|
||||
and (address := callback_matcher.get(ADDRESS)) is not None
|
||||
):
|
||||
cancel_active_scan = self.async_register_active_scan(
|
||||
address, scan_interval, scan_duration
|
||||
)
|
||||
|
||||
def _async_remove_callback() -> None:
|
||||
self._callback_index.remove_callback_matcher(callback_matcher)
|
||||
if cancel_active_scan is not None:
|
||||
cancel_active_scan()
|
||||
|
||||
# If we have history for the subscriber, we can trigger the callback
|
||||
# immediately with the last packet so the subscriber can see the
|
||||
# device.
|
||||
history = self._connectable_history if connectable else self._all_history
|
||||
service_infos: Iterable[BluetoothServiceInfoBleak] = []
|
||||
if address := callback_matcher.get(ADDRESS):
|
||||
if (address := callback_matcher.get(ADDRESS)) is not None:
|
||||
if service_info := history.get(address):
|
||||
service_infos = [service_info]
|
||||
else:
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}"
|
||||
},
|
||||
|
||||
@@ -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
+1
-1
@@ -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
|
||||
|
||||
@@ -1642,6 +1642,117 @@ async def test_register_callback_by_address(
|
||||
assert service_info.manufacturer_id == 89
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("matcher", "mode", "kwargs", "expected_args"),
|
||||
[
|
||||
pytest.param(
|
||||
{"address": "44:44:33:11:23:45"},
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
{"scan_interval": 300.0, "scan_duration": 5.0},
|
||||
("44:44:33:11:23:45", 300.0, 5.0),
|
||||
id="active_with_interval_and_duration",
|
||||
),
|
||||
pytest.param(
|
||||
{"address": "44:44:33:11:23:45"},
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
{"scan_interval": 300.0},
|
||||
("44:44:33:11:23:45", 300.0, None),
|
||||
id="active_with_interval_default_duration",
|
||||
),
|
||||
pytest.param(
|
||||
{"address": "44:44:33:11:23:45"},
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
{},
|
||||
("44:44:33:11:23:45", None, None),
|
||||
id="active_with_address_default_cadence",
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("enable_bluetooth", "mock_bleak_scanner_start")
|
||||
async def test_register_callback_registers_active_scan(
|
||||
hass: HomeAssistant,
|
||||
matcher: dict[str, str],
|
||||
mode: BluetoothScanningMode,
|
||||
kwargs: dict[str, float],
|
||||
expected_args: tuple[str, float | None, float | None],
|
||||
) -> None:
|
||||
"""An address matcher in non-PASSIVE mode registers an active-scan request."""
|
||||
mock_bt: list[Any] = []
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
|
||||
):
|
||||
await async_setup_with_default_adapter(hass)
|
||||
|
||||
with patch.object(hass.config_entries.flow, "async_init"):
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
def _cb(_si: BluetoothServiceInfo, _ch: BluetoothChange) -> None:
|
||||
return None
|
||||
|
||||
mock_cancel = Mock()
|
||||
with patch.object(
|
||||
HomeAssistantBluetoothManager,
|
||||
"async_register_active_scan",
|
||||
return_value=mock_cancel,
|
||||
) as mock_register:
|
||||
cancel = bluetooth.async_register_callback(
|
||||
hass, _cb, matcher, mode, **kwargs
|
||||
)
|
||||
mock_register.assert_called_once_with(*expected_args)
|
||||
mock_cancel.assert_not_called()
|
||||
cancel()
|
||||
mock_cancel.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("matcher", "mode", "kwargs"),
|
||||
[
|
||||
pytest.param(
|
||||
{"address": "44:44:33:11:23:45"},
|
||||
BluetoothScanningMode.PASSIVE,
|
||||
{"scan_interval": 300.0},
|
||||
id="passive_mode",
|
||||
),
|
||||
pytest.param(
|
||||
{SERVICE_UUID: "cba20d00-224d-11e6-9fb8-0002a5d5c51b"},
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
{"scan_interval": 300.0},
|
||||
id="no_address_in_matcher",
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("enable_bluetooth", "mock_bleak_scanner_start")
|
||||
async def test_register_callback_skips_active_scan(
|
||||
hass: HomeAssistant,
|
||||
matcher: dict[str, str],
|
||||
mode: BluetoothScanningMode,
|
||||
kwargs: dict[str, float],
|
||||
) -> None:
|
||||
"""PASSIVE mode or a matcher without an address never registers an active scan."""
|
||||
mock_bt: list[Any] = []
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
|
||||
):
|
||||
await async_setup_with_default_adapter(hass)
|
||||
|
||||
with patch.object(hass.config_entries.flow, "async_init"):
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
def _cb(_si: BluetoothServiceInfo, _ch: BluetoothChange) -> None:
|
||||
return None
|
||||
|
||||
with patch.object(
|
||||
HomeAssistantBluetoothManager, "async_register_active_scan"
|
||||
) as mock_register:
|
||||
cancel = bluetooth.async_register_callback(
|
||||
hass, _cb, matcher, mode, **kwargs
|
||||
)
|
||||
mock_register.assert_not_called()
|
||||
cancel()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_bluetooth")
|
||||
async def test_register_callback_by_address_connectable_only(
|
||||
hass: HomeAssistant, mock_bleak_scanner_start: MagicMock
|
||||
@@ -2536,6 +2647,35 @@ async def test_process_advertisements_timeout(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_bluetooth", "mock_bleak_scanner_start")
|
||||
async def test_process_advertisements_wires_timeout_as_scan_duration(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""async_process_advertisements forwards its timeout as scan_duration."""
|
||||
|
||||
def _callback(service_info: BluetoothServiceInfo) -> bool:
|
||||
return False
|
||||
|
||||
mock_cancel = Mock()
|
||||
with (
|
||||
patch.object(
|
||||
HomeAssistantBluetoothManager,
|
||||
"async_register_active_scan",
|
||||
return_value=mock_cancel,
|
||||
) as mock_register,
|
||||
pytest.raises(TimeoutError),
|
||||
):
|
||||
await async_process_advertisements(
|
||||
hass,
|
||||
_callback,
|
||||
{"address": "aa:44:33:11:23:45"},
|
||||
BluetoothScanningMode.ACTIVE,
|
||||
0,
|
||||
)
|
||||
mock_register.assert_called_once_with("aa:44:33:11:23:45", None, 0)
|
||||
mock_cancel.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("enable_bluetooth")
|
||||
async def test_wrapped_instance_with_filter(
|
||||
hass: HomeAssistant, mock_bleak_scanner_start: MagicMock
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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