From b9b36d9e12faae1e0f28f1a34283845f1390d8ee Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Sat, 6 Jun 2026 18:12:58 +0200 Subject: [PATCH 01/13] Add card group browsing to the Yoto media browser (#173152) --- homeassistant/components/yoto/coordinator.py | 6 +- homeassistant/components/yoto/media_player.py | 93 ++++++++++--- homeassistant/components/yoto/strings.json | 3 + tests/components/yoto/conftest.py | 13 ++ tests/components/yoto/test_media_player.py | 122 +++++++++++++++++- 5 files changed, 212 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/yoto/coordinator.py b/homeassistant/components/yoto/coordinator.py index 972aa446088eda..d7c64d4930dc11 100644 --- a/homeassistant/components/yoto/coordinator.py +++ b/homeassistant/components/yoto/coordinator.py @@ -114,11 +114,15 @@ async def _async_update_data(self) -> dict[str, YotoPlayer]: return self.client.players async def _async_load_library(self) -> None: - """Load the card library; failures only affect titles and artwork.""" + """Load the card library and groups; failures only affect browsing.""" try: await self.client.update_library() except YotoError as err: _LOGGER.warning("Could not load Yoto card library: %s", err) + try: + await self.client.update_groups() + except YotoError as err: + _LOGGER.warning("Could not load Yoto card groups: %s", err) async def _async_status_push_tick(self, _now: datetime) -> None: """Ask each player to push a fresh status snapshot over MQTT.""" diff --git a/homeassistant/components/yoto/media_player.py b/homeassistant/components/yoto/media_player.py index 1a1bd670108937..b3d98f9e817fa1 100644 --- a/homeassistant/components/yoto/media_player.py +++ b/homeassistant/components/yoto/media_player.py @@ -4,7 +4,7 @@ from datetime import datetime from typing import Any -from yoto_api import Card, Chapter, PlaybackStatus, Track, YotoError, YotoPlayer +from yoto_api import Card, Chapter, Group, PlaybackStatus, Track, YotoError, YotoPlayer from homeassistant.components.media_player import ( BrowseError, @@ -25,9 +25,8 @@ from .entity import YotoEntity URI_SCHEME = "yoto" -# The URI authority ("card") names the content type. Only cards exist today; -# reserving it leaves room for groups without breaking URIs. URI_CARD = "card" +URI_GROUP = "group" PARALLEL_UPDATES = 0 @@ -186,7 +185,7 @@ async def async_play_media( ) -> None: """Play a Yoto card, chapter, or track from the browse tree.""" try: - card_id, chapter_key, track_key = _parse_uri(media_id) + card_id, chapter_key, track_key = _parse_card_uri(media_id) except ValueError as err: raise ServiceValidationError( translation_domain=DOMAIN, @@ -264,8 +263,27 @@ async def async_browse_media( if not media_content_id: return self._browse_root() + client = self.coordinator.client + if media_content_id.startswith(f"{URI_SCHEME}://{URI_GROUP}/"): + try: + group_id = _parse_group_uri(media_content_id) + except ValueError as err: + raise BrowseError( + translation_domain=DOMAIN, + translation_key="invalid_media_id", + translation_placeholders={"media_id": media_content_id}, + ) from err + group = client.groups.get(group_id) + if group is None: + raise BrowseError( + translation_domain=DOMAIN, + translation_key="unknown_group", + translation_placeholders={"group_id": group_id}, + ) + return self._browse_group(group) + try: - card_id, chapter_key, _ = _parse_uri(media_content_id) + card_id, chapter_key, _ = _parse_card_uri(media_content_id) except ValueError as err: raise BrowseError( translation_domain=DOMAIN, @@ -273,7 +291,7 @@ async def async_browse_media( translation_placeholders={"media_id": media_content_id}, ) from err - card = self.coordinator.client.library.get(card_id) + card = client.library.get(card_id) if card is None: raise BrowseError( translation_domain=DOMAIN, @@ -283,7 +301,7 @@ async def async_browse_media( if not card.chapters: try: - await self.coordinator.client.update_card_detail(card_id) + await client.update_card_detail(card_id) except YotoError as err: raise BrowseError( translation_domain=DOMAIN, @@ -307,7 +325,12 @@ async def async_browse_media( return self._browse_card(card) def _browse_root(self) -> BrowseMedia: - """List every card in the user's library.""" + """List every card and group in the user's library.""" + client = self.coordinator.client + children: list[BrowseMedia] = [ + self._card_node(card) for card in client.library.values() + ] + children.extend(self._group_node(group) for group in client.groups.values()) return BrowseMedia( media_class=MediaClass.DIRECTORY, media_content_id="", @@ -315,13 +338,19 @@ def _browse_root(self) -> BrowseMedia: title="Yoto library", can_play=False, can_expand=True, - children=[ - self._card_node(card) - for card in self.coordinator.client.library.values() - ], + children=children, children_media_class=MediaClass.ALBUM, ) + def _browse_group(self, group: Group) -> BrowseMedia: + """List the cards in a group.""" + library = self.coordinator.client.library + cards = [library[card_id] for card_id in group.card_ids if card_id in library] + node = self._group_node(group) + node.children = [self._card_node(card) for card in cards] + node.children_media_class = MediaClass.ALBUM + return node + def _browse_card(self, card: Card) -> BrowseMedia: """List a card's chapters, collapsing single-chapter cards to tracks.""" chapters = card.chapters @@ -366,6 +395,18 @@ def _card_node(self, card: Card) -> BrowseMedia: thumbnail=card.cover_image_large, ) + def _group_node(self, group: Group) -> BrowseMedia: + """Build a browse node for a group.""" + return BrowseMedia( + media_class=MediaClass.PLAYLIST, + media_content_id=_build_group_uri(group.id), + media_content_type=MediaType.PLAYLIST, + title=group.name or group.id, + can_play=False, + can_expand=True, + thumbnail=group.image_url, + ) + def _chapter_node( self, card_id: str, chapter_key: str, chapter: Chapter ) -> BrowseMedia: @@ -423,19 +464,33 @@ def _build_uri( return f"{URI_SCHEME}://{'/'.join(segments)}" -def _parse_uri(media_id: str) -> tuple[str, str | None, str | None]: - """Parse a yoto://card/... URI into card/chapter/track parts. +def _build_group_uri(group_id: str) -> str: + """Build a yoto://group/... URI.""" + return f"{URI_SCHEME}://{URI_GROUP}/{group_id}" + - Parsed manually because URL parsers lower-case the authority and Yoto - IDs are case-sensitive. - """ +# URIs parsed manually because URL parsers lower-case the authority and Yoto +# IDs are case-sensitive. +def _parse_card_uri(media_id: str) -> tuple[str, str | None, str | None]: + """Parse a yoto://card/... URI into card/chapter/track parts.""" prefix = f"{URI_SCHEME}://{URI_CARD}/" if not media_id.startswith(prefix): - raise ValueError(f"Not a Yoto media identifier: {media_id}") + raise ValueError(f"Not a Yoto card identifier: {media_id}") parts = media_id[len(prefix) :].split("/") if not parts or len(parts) > 3 or any(not segment for segment in parts): - raise ValueError(f"Not a Yoto media identifier: {media_id}") + raise ValueError(f"Not a Yoto card identifier: {media_id}") card_id = parts[0] chapter_key = parts[1] if len(parts) > 1 else None track_key = parts[2] if len(parts) > 2 else None return card_id, chapter_key, track_key + + +def _parse_group_uri(media_id: str) -> str: + """Parse a yoto://group/ URI.""" + prefix = f"{URI_SCHEME}://{URI_GROUP}/" + if not media_id.startswith(prefix): + raise ValueError(f"Not a Yoto group identifier: {media_id}") + parts = media_id[len(prefix) :].split("/") + if len(parts) != 1 or not parts[0]: + raise ValueError(f"Not a Yoto group identifier: {media_id}") + return parts[0] diff --git a/homeassistant/components/yoto/strings.json b/homeassistant/components/yoto/strings.json index a8c673ee61c216..7103e75a37f200 100644 --- a/homeassistant/components/yoto/strings.json +++ b/homeassistant/components/yoto/strings.json @@ -52,6 +52,9 @@ "unknown_chapter": { "message": "Unknown chapter {chapter_key} on card {card_id}" }, + "unknown_group": { + "message": "Unknown Yoto group: {group_id}" + }, "unknown_track": { "message": "Unknown track {track_key} on card {card_id}" }, diff --git a/tests/components/yoto/conftest.py b/tests/components/yoto/conftest.py index 967eb50aaed72a..230a5e39436192 100644 --- a/tests/components/yoto/conftest.py +++ b/tests/components/yoto/conftest.py @@ -11,6 +11,7 @@ Card, Chapter, Device, + Group, PlaybackEvent, PlaybackStatus, PlayerInfo, @@ -33,6 +34,7 @@ USER_ID = "auth0|user-test" PLAYER_ID = "player-test" CARD_ID = "card-test" +GROUP_ID = "group-test" SCOPES = " ".join(YOTO_SCOPES) ACCESS_TOKEN = jwt.encode({"sub": USER_ID}, "test-secret-long-enough-for-hmac-sha256") @@ -120,6 +122,16 @@ def mock_setup_entry() -> Generator[AsyncMock]: yield mock_setup +def _build_group() -> Group: + """Build a representative Yoto card group.""" + return Group( + id=GROUP_ID, + name="Bedtime", + image_url="https://example.test/group.jpg", + card_ids=[CARD_ID], + ) + + @pytest.fixture def mock_yoto_client() -> Generator[MagicMock]: """Patch YotoClient used by the runtime to a configurable mock.""" @@ -129,6 +141,7 @@ def mock_yoto_client() -> Generator[MagicMock]: client = client_class.return_value client.players = {PLAYER_ID: _build_player()} client.library = {CARD_ID: _build_card()} + client.groups = {GROUP_ID: _build_group()} client.token = MagicMock(refresh_token="mock-refresh-token") yield client diff --git a/tests/components/yoto/test_media_player.py b/tests/components/yoto/test_media_player.py index a2ef208b2c1749..406ff4a5a64a01 100644 --- a/tests/components/yoto/test_media_player.py +++ b/tests/components/yoto/test_media_player.py @@ -240,6 +240,7 @@ async def test_play_media( pytest.param("yoto://card/", id="missing_card_id"), pytest.param("yoto://card/card-test/01/01-INT/extra", id="too_many_segments"), pytest.param("yoto://card/card-test//01-INT", id="empty_segment"), + pytest.param("yoto://group/group-test", id="group_uri_not_playable"), ], ) async def test_play_media_invalid_uri_raises( @@ -323,12 +324,12 @@ async def test_play_media_card_detail_failure_raises( @pytest.mark.usefixtures("mock_yoto_client") -async def test_browse_media_root_lists_cards( +async def test_browse_media_root_lists_cards_and_groups( hass: HomeAssistant, mock_config_entry: MockConfigEntry, hass_ws_client: WebSocketGenerator, ) -> None: - """Browsing without a content id lists every library card.""" + """Browsing the root lists every library card followed by every group.""" await setup_integration(hass, mock_config_entry) client = await hass_ws_client() @@ -339,11 +340,122 @@ async def test_browse_media_root_lists_cards( assert response["success"] children = response["result"]["children"] - assert len(children) == 1 - assert children[0]["title"] == "Outer Space" + assert [c["title"] for c in children] == ["Outer Space", "Bedtime"] assert children[0]["media_content_id"] == "yoto://card/card-test" assert children[0]["can_play"] is True - assert children[0]["can_expand"] is True + assert children[1]["media_content_id"] == "yoto://group/group-test" + assert children[1]["can_play"] is False + assert children[1]["can_expand"] is True + + +@pytest.mark.usefixtures("mock_yoto_client") +async def test_browse_group_lists_cards( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + hass_ws_client: WebSocketGenerator, +) -> None: + """Browsing a group lists its member cards.""" + await setup_integration(hass, mock_config_entry) + client = await hass_ws_client() + + await client.send_json( + { + "id": 1, + "type": "media_player/browse_media", + "entity_id": ENTITY_ID, + "media_content_type": "music", + "media_content_id": "yoto://group/group-test", + } + ) + response = await client.receive_json() + + assert response["success"] + result = response["result"] + assert result["children_media_class"] == "album" + children = result["children"] + assert [c["title"] for c in children] == ["Outer Space"] + assert children[0]["media_content_id"] == "yoto://card/card-test" + + +async def test_browse_group_skips_cards_missing_from_library( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_yoto_client: MagicMock, + hass_ws_client: WebSocketGenerator, +) -> None: + """A group may reference cards absent from the library; those are skipped.""" + mock_yoto_client.groups["group-test"].card_ids = ["card-test", "missing-card"] + await setup_integration(hass, mock_config_entry) + client = await hass_ws_client() + + await client.send_json( + { + "id": 1, + "type": "media_player/browse_media", + "entity_id": ENTITY_ID, + "media_content_type": "music", + "media_content_id": "yoto://group/group-test", + } + ) + response = await client.receive_json() + + assert response["success"] + children = response["result"]["children"] + assert [c["title"] for c in children] == ["Outer Space"] + + +@pytest.mark.usefixtures("mock_yoto_client") +async def test_browse_unknown_group_raises( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + hass_ws_client: WebSocketGenerator, +) -> None: + """Browsing a group that's not in the library returns a browse error.""" + await setup_integration(hass, mock_config_entry) + client = await hass_ws_client() + + await client.send_json( + { + "id": 1, + "type": "media_player/browse_media", + "entity_id": ENTITY_ID, + "media_content_type": "music", + "media_content_id": "yoto://group/does-not-exist", + } + ) + response = await client.receive_json() + assert response["success"] is False + + +@pytest.mark.usefixtures("mock_yoto_client") +@pytest.mark.parametrize( + "media_content_id", + [ + pytest.param("yoto://group/", id="missing_group_id"), + pytest.param("yoto://group/group-test/extra", id="too_many_segments"), + ], +) +async def test_browse_invalid_group_uri_raises( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + hass_ws_client: WebSocketGenerator, + media_content_id: str, +) -> None: + """A malformed yoto://group/ URI returns a browse error.""" + await setup_integration(hass, mock_config_entry) + client = await hass_ws_client() + + await client.send_json( + { + "id": 1, + "type": "media_player/browse_media", + "entity_id": ENTITY_ID, + "media_content_type": "music", + "media_content_id": media_content_id, + } + ) + response = await client.receive_json() + assert response["success"] is False async def test_browse_card_with_multiple_chapters_and_multiple_tracks( From c72d723e0d235806bde4c4d82a45986bfeff5f63 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 6 Jun 2026 11:13:03 -0500 Subject: [PATCH 02/13] Wait for ESPHome bluetooth proxy connection at startup (#173164) --- .../components/esphome/entry_data.py | 2 + homeassistant/components/esphome/manager.py | 23 +++- tests/components/esphome/test_manager.py | 123 ++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/esphome/entry_data.py b/homeassistant/components/esphome/entry_data.py index 8d3e2ff1547a97..7dd004c2af8332 100644 --- a/homeassistant/components/esphome/entry_data.py +++ b/homeassistant/components/esphome/entry_data.py @@ -166,6 +166,8 @@ class RuntimeEntryData: ) loaded_platforms: set[Platform] = field(default_factory=set) platform_load_lock: asyncio.Lock = field(default_factory=asyncio.Lock) + # Set once the first connection has finished scanner setup or teardown. + first_connect_done: asyncio.Event = field(default_factory=asyncio.Event) _storage_contents: StoreData | None = None _pending_storage: Callable[[], StoreData] | None = None assist_pipeline_update_callbacks: list[CALLBACK_TYPE] = field(default_factory=list) diff --git a/homeassistant/components/esphome/manager.py b/homeassistant/components/esphome/manager.py index 2a6d38471722e2..3eeaed77be5e63 100644 --- a/homeassistant/components/esphome/manager.py +++ b/homeassistant/components/esphome/manager.py @@ -1,11 +1,12 @@ """Manager for esphome devices.""" +import asyncio import base64 from functools import partial import logging import secrets import struct -from typing import TYPE_CHECKING, Any, NamedTuple +from typing import TYPE_CHECKING, Any, Final, NamedTuple from aioesphomeapi import ( APIClient, @@ -106,6 +107,9 @@ _LOGGER = logging.getLogger(__name__) +# Max time to wait at startup for a BLE proxy to register its scanner. +STARTUP_SCANNER_WAIT: Final = 3.0 + LOG_LEVEL_TO_LOGGER = { LogLevel.LOG_LEVEL_NONE: logging.DEBUG, LogLevel.LOG_LEVEL_ERROR: logging.ERROR, @@ -677,6 +681,8 @@ async def _on_connect(self) -> None: hass, device_info.bluetooth_mac_address or device_info.mac_address ) + entry_data.first_connect_done.set() + if device_info.voice_assistant_feature_flags_compat(api_version) and ( Platform.ASSIST_SATELLITE not in entry_data.loaded_platforms ): @@ -988,6 +994,21 @@ async def async_start(self) -> None: await reconnect_logic.start() + # Wait for a cached BLE proxy to register its scanner before finishing setup. + if ( + device_info := entry_data.device_info + ) is not None and device_info.bluetooth_proxy_feature_flags_compat( + entry_data.api_version + ): + try: + async with asyncio.timeout(STARTUP_SCANNER_WAIT): + await entry_data.first_connect_done.wait() + except TimeoutError: + _LOGGER.debug( + "%s: Timed out waiting for Bluetooth scanner to register", + self.host, + ) + @callback def _async_setup_device_registry( diff --git a/tests/components/esphome/test_manager.py b/tests/components/esphome/test_manager.py index 89a42e9aadf9c8..96ffcb52d3b7c0 100644 --- a/tests/components/esphome/test_manager.py +++ b/tests/components/esphome/test_manager.py @@ -9,7 +9,9 @@ from aioesphomeapi import ( APIClient, APIConnectionError, + APIVersion, AreaInfo, + BluetoothProxyFeature, DeviceInfo, EncryptionPlaintextAPIError, ExecuteServiceResponse, @@ -3274,3 +3276,124 @@ async def test_service_registration_response_types( hass.services.supports_response(DOMAIN, "test_status_service") == SupportsResponse.NONE ) + + +def _create_cached_bluetooth_proxy_entry( + hass: HomeAssistant, + hass_storage: dict[str, Any], + bluetooth_proxy_feature_flags: BluetoothProxyFeature, +) -> tuple[MockConfigEntry, DeviceInfo]: + """Create an entry with cached device info so setup knows the proxy state.""" + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="11:22:33:44:55:aa", + data={ + CONF_HOST: "test.local", + CONF_PORT: 6053, + CONF_PASSWORD: "", + CONF_BLUETOOTH_MAC_ADDRESS: "AA:BB:CC:DD:EE:FC", + }, + ) + entry.add_to_hass(hass) + device_info = DeviceInfo( + name="test", + mac_address="11:22:33:44:55:AA", + bluetooth_mac_address="AA:BB:CC:DD:EE:FC", + bluetooth_proxy_feature_flags=bluetooth_proxy_feature_flags, + ) + storage_key = f"{DOMAIN}.{entry.entry_id}" + hass_storage[storage_key] = { + "version": 1, + "minor_version": 1, + "key": storage_key, + "data": { + "device_info": device_info.to_dict(), + "api_version": APIVersion(1, 9).to_dict(), + }, + } + return entry, device_info + + +@pytest.mark.usefixtures("mock_zeroconf") +async def test_bluetooth_proxy_waits_for_scanner_at_startup( + hass: HomeAssistant, + mock_client: APIClient, + hass_storage: dict[str, Any], +) -> None: + """Test setup waits for a cached bluetooth proxy to register its scanner.""" + entry, device_info = _create_cached_bluetooth_proxy_entry( + hass, hass_storage, BluetoothProxyFeature.PASSIVE_SCAN + ) + connect_event = asyncio.Event() + reached_connect = asyncio.Event() + + async def _block_until_released() -> tuple[DeviceInfo, list[Any], list[Any]]: + reached_connect.set() + await connect_event.wait() + return (device_info, [], []) + + mock_client.device_info_and_list_entities = _block_until_released + + setup_task = hass.async_create_task(hass.config_entries.async_setup(entry.entry_id)) + async with asyncio.timeout(2): + await reached_connect.wait() + + # Setup must still be waiting for the scanner to be registered. + assert not setup_task.done() + + connect_event.set() + async with asyncio.timeout(2): + assert await setup_task is True + assert entry.runtime_data.first_connect_done.is_set() + + +@pytest.mark.usefixtures("mock_zeroconf") +async def test_bluetooth_proxy_startup_wait_times_out( + hass: HomeAssistant, + mock_client: APIClient, + hass_storage: dict[str, Any], +) -> None: + """Test setup finishes if a cached bluetooth proxy never connects.""" + entry, device_info = _create_cached_bluetooth_proxy_entry( + hass, hass_storage, BluetoothProxyFeature.PASSIVE_SCAN + ) + connect_event = asyncio.Event() + + async def _never_returns() -> tuple[DeviceInfo, list[Any], list[Any]]: + await connect_event.wait() + return (device_info, [], []) + + mock_client.device_info_and_list_entities = _never_returns + + with patch("homeassistant.components.esphome.manager.STARTUP_SCANNER_WAIT", 0.05): + async with asyncio.timeout(2): + assert await hass.config_entries.async_setup(entry.entry_id) is True + + connect_event.set() + await hass.async_block_till_done() + + +@pytest.mark.usefixtures("mock_zeroconf") +async def test_non_bluetooth_device_does_not_wait_at_startup( + hass: HomeAssistant, + mock_client: APIClient, + hass_storage: dict[str, Any], +) -> None: + """Test setup does not wait for a device that is not a bluetooth proxy.""" + entry, device_info = _create_cached_bluetooth_proxy_entry( + hass, hass_storage, BluetoothProxyFeature(0) + ) + connect_event = asyncio.Event() + + async def _never_returns() -> tuple[DeviceInfo, list[Any], list[Any]]: + await connect_event.wait() + return (device_info, [], []) + + mock_client.device_info_and_list_entities = _never_returns + + # The connection is blocked, but without proxy flags setup must not wait. + async with asyncio.timeout(2): + assert await hass.config_entries.async_setup(entry.entry_id) is True + + connect_event.set() + await hass.async_block_till_done() From 018cd1333e49f4defc40758ea83933d3f0438123 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 6 Jun 2026 11:14:59 -0500 Subject: [PATCH 03/13] Bump ollama library (#173129) --- homeassistant/components/ollama/manifest.json | 2 +- requirements_all.txt | 2 +- script/licenses.py | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ollama/manifest.json b/homeassistant/components/ollama/manifest.json index 87713ce3f6227b..4d54eb9110ee72 100644 --- a/homeassistant/components/ollama/manifest.json +++ b/homeassistant/components/ollama/manifest.json @@ -8,5 +8,5 @@ "documentation": "https://www.home-assistant.io/integrations/ollama", "integration_type": "service", "iot_class": "local_polling", - "requirements": ["ollama==0.5.1"] + "requirements": ["ollama==0.6.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 1af318dcf9c20e..9c3441e395bcc0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1727,7 +1727,7 @@ oemthermostat==1.1.1 ohme==1.9.1 # homeassistant.components.ollama -ollama==0.5.1 +ollama==0.6.2 # homeassistant.components.omnilogic omnilogic==0.4.5 diff --git a/script/licenses.py b/script/licenses.py index 97732dcdb53731..302cd36e8f351d 100644 --- a/script/licenses.py +++ b/script/licenses.py @@ -192,7 +192,6 @@ def from_dict(cls, data: PackageMetadata) -> PackageDefinition: "maxcube-api", # https://github.com/uebelack/python-maxcube-api/pull/48 "neurio", # https://github.com/jordanh/neurio-python/pull/13 "nsw-fuel-api-client", # https://github.com/nickw444/nsw-fuel-api-client/pull/14 - "ollama", # https://github.com/ollama/ollama-python/pull/526 "pigpio", # https://github.com/joan2937/pigpio/pull/608 "pymitv", # MIT "pybbox", # https://github.com/HydrelioxGitHub/pybbox/pull/5 From ba9248cc941339ba56d3ba1c13fcec927d507e40 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 6 Jun 2026 11:15:48 -0500 Subject: [PATCH 04/13] LLM: format numeric states with display precision (#173128) --- homeassistant/helpers/llm.py | 5 ++++ tests/helpers/test_llm.py | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/homeassistant/helpers/llm.py b/homeassistant/helpers/llm.py index 3035b713e02191..c450daeff48710 100644 --- a/homeassistant/helpers/llm.py +++ b/homeassistant/helpers/llm.py @@ -22,6 +22,7 @@ from homeassistant.components.homeassistant import async_should_expose from homeassistant.components.intent import async_device_supports_timers from homeassistant.components.script import DOMAIN as SCRIPT_DOMAIN +from homeassistant.components.sensor import async_rounded_state from homeassistant.components.todo import DOMAIN as TODO_DOMAIN, TodoServices from homeassistant.components.weather import INTENT_GET_WEATHER from homeassistant.const import ( @@ -720,6 +721,10 @@ def _get_exposed_entities( if include_state: info["state"] = state.state + # Format numeric states with configured display precision + if state.domain == "sensor": + info["state"] = async_rounded_state(hass, state.entity_id, state) + # Convert timestamp device_class states from UTC to local time if state.attributes.get("device_class") == "timestamp" and state.state: if (parsed_utc := dt_util.parse_datetime(state.state)) is not None: diff --git a/tests/helpers/test_llm.py b/tests/helpers/test_llm.py index fff046029d00a4..93ae74cf9aef04 100644 --- a/tests/helpers/test_llm.py +++ b/tests/helpers/test_llm.py @@ -483,6 +483,46 @@ async def test_assist_api_prompt( ) hass.states.async_set(entry2.entity_id, "on", {"friendly_name": "Living Room"}) + # Create two sensors with different display precisions + power1 = entity_registry.async_get_or_create( + "sensor", + "power1", + "mock-id-power-1", + original_name="Power 1", + suggested_object_id="power1", + device_id=device.id, + ) + entity_registry.async_update_entity_options( + power1.entity_id, + "sensor", + {"display_precision": 0}, + ) + hass.states.async_set( + power1.entity_id, + "1234.1234", + {"friendly_name": "Power 1"}, + ) + async_expose_entity(hass, "conversation", power1.entity_id, True) + power2 = entity_registry.async_get_or_create( + "sensor", + "power2", + "mock-id-power-2", + original_name="Power 2", + suggested_object_id="power2", + device_id=device.id, + ) + entity_registry.async_update_entity_options( + power2.entity_id, + "sensor", + {"suggested_display_precision": 2}, + ) + hass.states.async_set( + power2.entity_id, + "1234.1234", + {"friendly_name": "Power 2"}, + ) + async_expose_entity(hass, "conversation", power2.entity_id, True) + def create_entity( device: dr.DeviceEntry, write_state=True, @@ -600,6 +640,14 @@ def create_entity( domain: light state: 'on' areas: Test Area, Alternative name +- names: Power 1 + domain: sensor + state: '1234' + areas: Test Area, Alternative name +- names: Power 2 + domain: sensor + state: '1234.12' + areas: Test Area, Alternative name - names: Test Device, my test light domain: light state: unavailable @@ -643,6 +691,12 @@ def create_entity( - names: Living Room domain: light areas: Test Area, Alternative name +- names: Power 1 + domain: sensor + areas: Test Area, Alternative name +- names: Power 2 + domain: sensor + areas: Test Area, Alternative name - names: Test Device, my test light domain: light areas: Test Area, Alternative name From 34f3452280e52d4181f32162da308469acd34fa6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 6 Jun 2026 11:17:49 -0500 Subject: [PATCH 05/13] Wait for Shelly bluetooth proxy connection at startup (#173165) --- homeassistant/components/shelly/__init__.py | 20 ++++ .../components/shelly/coordinator.py | 43 +++---- tests/components/shelly/test_init.py | 106 ++++++++++++++++++ 3 files changed, 150 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 02ebbdc530f7cb..c46e89fc55bd99 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -1,5 +1,6 @@ """The Shelly integration.""" +import asyncio from functools import partial from typing import Final @@ -73,6 +74,7 @@ get_http_port, get_rpc_scripts_event_types, get_ws_context, + is_rpc_ble_scanner_supported, remove_empty_sub_devices, remove_stale_blu_trv_devices, ) @@ -114,6 +116,9 @@ ) CONFIG_SCHEMA: Final = vol.Schema({DOMAIN: COAP_SCHEMA}, extra=vol.ALLOW_EXTRA) +# Max time to wait at startup for a BLE proxy to register its scanner. +STARTUP_SCANNER_WAIT: Final = 3.0 + async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the Shelly component.""" @@ -365,6 +370,21 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry) runtime_data.rpc = ShellyRpcCoordinator(hass, entry, device) runtime_data.rpc.async_setup() + + if ( + is_rpc_ble_scanner_supported(entry) + and entry.options.get(CONF_BLE_SCANNER_MODE, BLEScannerMode.DISABLED) + != BLEScannerMode.DISABLED + ): + # Wait for the proxy to register its scanner before finishing setup. + try: + async with asyncio.timeout(STARTUP_SCANNER_WAIT): + await runtime_data.rpc.ble_scanner_setup_done.wait() + except TimeoutError: + LOGGER.debug( + "%s: Timed out waiting for BLE scanner to register", entry.title + ) + runtime_data.rpc_poll = ShellyRpcPollingCoordinator(hass, entry, device) await hass.config_entries.async_forward_entry_setups( entry, runtime_data.platforms diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index 8b4578f0e1fe97..3788955fea0a4e 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -521,6 +521,8 @@ def __init__( super().__init__(hass, entry, device, update_interval) self.connected = False + # Set once BLE scanner setup has been attempted after connecting. + self.ble_scanner_setup_done = asyncio.Event() self._disconnected_callbacks: list[CALLBACK_TYPE] = [] self._connection_lock = asyncio.Lock() self._event_listeners: list[Callable[[dict[str, Any]], None]] = [] @@ -759,27 +761,30 @@ async def _async_setup_outbound_websocket(self) -> None: async def _async_connect_ble_scanner(self) -> None: """Connect BLE scanner.""" - ble_scanner_mode = self.config_entry.options.get( - CONF_BLE_SCANNER_MODE, BLEScannerMode.DISABLED - ) - if ble_scanner_mode == BLEScannerMode.DISABLED and self.connected: - await async_stop_scanner(self.device) - async_remove_scanner(self.hass, self.bluetooth_source) - return - if await async_ensure_ble_enabled(self.device): - # BLE enable required a reboot, don't bother connecting - # the scanner since it will be disconnected anyway - LOGGER.debug( - "Device %s BLE enable required a reboot, skipping scanner connect", - self.name, + try: + ble_scanner_mode = self.config_entry.options.get( + CONF_BLE_SCANNER_MODE, BLEScannerMode.DISABLED ) - return - assert self.device_id is not None - self._disconnected_callbacks.append( - await async_connect_scanner( - self.hass, self, ble_scanner_mode, self.device_id + if ble_scanner_mode == BLEScannerMode.DISABLED and self.connected: + await async_stop_scanner(self.device) + async_remove_scanner(self.hass, self.bluetooth_source) + return + if await async_ensure_ble_enabled(self.device): + # BLE enable required a reboot, don't bother connecting + # the scanner since it will be disconnected anyway + LOGGER.debug( + "Device %s BLE enable required a reboot, skipping scanner connect", + self.name, + ) + return + assert self.device_id is not None + self._disconnected_callbacks.append( + await async_connect_scanner( + self.hass, self, ble_scanner_mode, self.device_id + ) ) - ) + finally: + self.ble_scanner_setup_done.set() @callback def _async_handle_rpc_device_online(self) -> None: diff --git a/tests/components/shelly/test_init.py b/tests/components/shelly/test_init.py index 0eaa3192ca10cf..a2c567299fdd11 100644 --- a/tests/components/shelly/test_init.py +++ b/tests/components/shelly/test_init.py @@ -1,5 +1,6 @@ """Test cases for the Shelly component.""" +import asyncio from ipaddress import IPv4Address from typing import Any from unittest.mock import AsyncMock, Mock, call, patch @@ -769,3 +770,108 @@ async def test_empty_device_removal( # verify that the empty sub-device is removed assert device_registry.async_get(sub_device_entry.id) is None + + +async def test_rpc_waits_for_ble_scanner_at_startup( + hass: HomeAssistant, + mock_rpc_device: Mock, +) -> None: + """Test setup waits for the bluetooth scanner to be registered.""" + connect_event = asyncio.Event() + reached_connect = asyncio.Event() + + async def _block_until_released(*args: Any, **kwargs: Any) -> Mock: + reached_connect.set() + await connect_event.wait() + return Mock() + + entry = await init_integration( + hass, + 2, + options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE}, + skip_setup=True, + ) + + with patch( + "homeassistant.components.shelly.coordinator.async_connect_scanner", + _block_until_released, + ): + setup_task = hass.async_create_task( + hass.config_entries.async_setup(entry.entry_id) + ) + async with asyncio.timeout(2): + await reached_connect.wait() + + # Setup must still be waiting for the scanner to be registered. + assert not setup_task.done() + + connect_event.set() + async with asyncio.timeout(2): + assert await setup_task is True + + await hass.async_block_till_done() + assert entry.state is ConfigEntryState.LOADED + + +async def test_rpc_ble_scanner_startup_wait_times_out( + hass: HomeAssistant, + mock_rpc_device: Mock, +) -> None: + """Test setup finishes if the bluetooth scanner never registers.""" + connect_event = asyncio.Event() + + async def _never_returns(*args: Any, **kwargs: Any) -> Mock: + await connect_event.wait() + return Mock() + + entry = await init_integration( + hass, + 2, + options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE}, + skip_setup=True, + ) + + with ( + patch( + "homeassistant.components.shelly.coordinator.async_connect_scanner", + _never_returns, + ), + patch("homeassistant.components.shelly.STARTUP_SCANNER_WAIT", 0.05), + ): + async with asyncio.timeout(5): + assert await hass.config_entries.async_setup(entry.entry_id) is True + + assert entry.state is ConfigEntryState.LOADED + connect_event.set() + await hass.async_block_till_done() + + +async def test_rpc_disabled_ble_scanner_does_not_wait_at_startup( + hass: HomeAssistant, + mock_rpc_device: Mock, +) -> None: + """Test setup does not wait when the BLE scanner is disabled.""" + block_event = asyncio.Event() + + async def _block_forever(self: Any) -> None: + await block_event.wait() + + entry = await init_integration( + hass, + 2, + options={CONF_BLE_SCANNER_MODE: BLEScannerMode.DISABLED}, + skip_setup=True, + ) + + with patch( + "homeassistant.components.shelly.coordinator.ShellyRpcCoordinator" + "._async_connect_ble_scanner", + _block_forever, + ): + # Scanner setup is blocked, but a disabled proxy must not wait for it. + async with asyncio.timeout(2): + assert await hass.config_entries.async_setup(entry.entry_id) is True + + assert entry.state is ConfigEntryState.LOADED + block_event.set() + await hass.async_block_till_done() From 42136f1464ed5de06d0c1468ebf502b2d1597d15 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 6 Jun 2026 12:47:49 -0500 Subject: [PATCH 06/13] Bubble up conversation response in script run (#173131) Co-authored-by: Paulus Schoutsen Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- homeassistant/helpers/script.py | 14 ++++++++++++-- tests/helpers/test_script.py | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index fe8a721e138350..5431d891c13635 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -400,10 +400,16 @@ class _ConditionFail(_HaltScript): class _StopScript(_HaltScript): """Throw if script needs to stop.""" - def __init__(self, message: str, response: Any) -> None: + def __init__( + self, + message: str, + response: Any, + conversation_response: str | None | UndefinedType = UNDEFINED, + ) -> None: """Initialize a halt exception.""" super().__init__(message) self.response = response + self.conversation_response = conversation_response class _ScriptRun: @@ -481,6 +487,10 @@ async def async_run(self) -> ScriptRunResult | None: response = err.response + # Bubble up child conversation response + if err.conversation_response is not UNDEFINED: + self._conversation_response = err.conversation_response + except Exception: script_execution_set("error") raise @@ -979,7 +989,7 @@ async def _async_step_stop(self) -> None: ) from ex else: response = None - raise _StopScript(stop, response) + raise _StopScript(stop, response, self._conversation_response) ## Variable actions ## diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index 657cfb3910aeb1..ee739e1367f595 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -6763,6 +6763,32 @@ async def test_conversation_response_not_set_subscript_if( assert_action_trace(expected_trace) +async def test_conversation_response_nested_with_stop( + hass: HomeAssistant, +) -> None: + """Test setting conversation response in a child block with a stop.""" + sequence = cv.SCRIPT_SCHEMA( + [ + { + "choose": { + "conditions": { + "condition": "template", + "value_template": "{{ true }}", + }, + "sequence": [ + {"set_conversation_response": "{{ 'conversation response' }}"}, + {"stop": "stop response"}, + ], + }, + }, + ] + ) + script_obj = script.Script(hass, sequence, "Test Name", "test_domain") + + result = await script_obj.async_run(context=Context()) + assert result.conversation_response == "conversation response" + + async def test_stopping_run_before_starting( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: From c5f93cdd72507a71ab5505ce0d71b1fb5e0e151a Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 6 Jun 2026 12:48:07 -0500 Subject: [PATCH 07/13] Validate sentences and answers (#173127) Co-authored-by: Paulus Schoutsen --- .../components/assist_satellite/__init__.py | 14 +++++++++++ .../components/conversation/trigger.py | 19 ++++++++++++++- .../assist_satellite/test_entity.py | 23 +++++++++++++++++++ tests/components/conversation/test_trigger.py | 15 ++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/assist_satellite/__init__.py b/homeassistant/components/assist_satellite/__init__.py index dfc40551da04b0..dcb0ea48b6b920 100644 --- a/homeassistant/components/assist_satellite/__init__.py +++ b/homeassistant/components/assist_satellite/__init__.py @@ -5,6 +5,8 @@ from pathlib import Path from typing import Any +from hassil.parse_expression import parse_sentence +from hassil.parser import ParseError from hassil.util import ( PUNCTUATION_END, PUNCTUATION_END_WORD, @@ -164,6 +166,7 @@ async def handle_ask_question(call: ServiceCall) -> dict[str, Any]: [cv.string], has_one_non_empty_item, has_no_punctuation, + is_valid_sentence, ), } ], @@ -212,6 +215,17 @@ def has_no_punctuation(value: list[str]) -> list[str]: return value +def is_valid_sentence(value: list[str]) -> list[str]: + """Validate result can be parsed by hassil.""" + for sentence in value: + try: + parse_sentence(sentence) + except ParseError as err: + raise vol.Invalid(f"invalid sentence: {err}") from err + + return value + + def has_one_non_empty_item(value: list[str]) -> list[str]: """Validate result has at least one item.""" if len(value) < 1: diff --git a/homeassistant/components/conversation/trigger.py b/homeassistant/components/conversation/trigger.py index 6394b1d43dda08..4ba877a781c738 100644 --- a/homeassistant/components/conversation/trigger.py +++ b/homeassistant/components/conversation/trigger.py @@ -3,6 +3,8 @@ from collections.abc import Awaitable, Callable from typing import Any +from hassil.parse_expression import parse_sentence +from hassil.parser import ParseError from hassil.recognize import RecognizeResult from hassil.util import ( PUNCTUATION_END, @@ -42,6 +44,17 @@ def has_no_punctuation(value: list[str]) -> list[str]: return value +def is_valid_sentence(value: list[str]) -> list[str]: + """Validate result can be parsed by hassil.""" + for sentence in value: + try: + parse_sentence(sentence) + except ParseError as err: + raise vol.Invalid(f"invalid sentence: {err}") from err + + return value + + def has_one_non_empty_item(value: list[str]) -> list[str]: """Validate result has at least one item.""" if len(value) < 1: @@ -58,7 +71,11 @@ def has_one_non_empty_item(value: list[str]) -> list[str]: { vol.Required(CONF_PLATFORM): DOMAIN, vol.Required(CONF_COMMAND): vol.All( - cv.ensure_list, [cv.string], has_one_non_empty_item, has_no_punctuation + cv.ensure_list, + [cv.string], + has_one_non_empty_item, + has_no_punctuation, + is_valid_sentence, ), } ) diff --git a/tests/components/assist_satellite/test_entity.py b/tests/components/assist_satellite/test_entity.py index 09e7ed6b781591..837d551f0650f2 100644 --- a/tests/components/assist_satellite/test_entity.py +++ b/tests/components/assist_satellite/test_entity.py @@ -6,6 +6,7 @@ from unittest.mock import Mock, patch import pytest +import voluptuous as vol from homeassistant.components import stt from homeassistant.components.assist_pipeline import ( @@ -986,6 +987,28 @@ async def test_ask_question_requires_entity_permission( ) +@pytest.mark.parametrize("sentence", ["no punctuation!", "[malformed template)"]) +async def test_ask_question_invalid_sentences( + hass: HomeAssistant, + init_components: ConfigEntry, + entity: MockAssistSatellite, + sentence: str, +) -> None: + """Test that invalid sentences raise an exception.""" + with pytest.raises(vol.Invalid): + await hass.services.async_call( + DOMAIN, + "ask_question", + { + "entity_id": "assist_satellite.test_entity", + "question": "Test", + "answers": [{"id": "answer", "sentences": [sentence]}], + }, + blocking=True, + return_response=True, + ) + + async def test_wake_word_start_keeps_responding( hass: HomeAssistant, init_components: ConfigEntry, entity: MockAssistSatellite ) -> None: diff --git a/tests/components/conversation/test_trigger.py b/tests/components/conversation/test_trigger.py index 62715ee3ffe4d2..efd230fb8e8a73 100644 --- a/tests/components/conversation/test_trigger.py +++ b/tests/components/conversation/test_trigger.py @@ -573,6 +573,21 @@ async def test_fails_on_no_sentences(hass: HomeAssistant) -> None: ) +async def test_fails_on_bad_parse(hass: HomeAssistant) -> None: + """Test that validation fails when sentence is malformed.""" + with pytest.raises(vol.Invalid): + await trigger.async_validate_trigger_config( + hass, + [ + { + "id": "trigger1", + "platform": "conversation", + "command": ["[test)"], + }, + ], + ) + + async def test_wildcards(hass: HomeAssistant, service_calls: list[ServiceCall]) -> None: """Test wildcards in trigger sentences.""" assert await async_setup_component( From 1cf8fe4d0b0af3ce0aedf66aa61dce7a0149348e Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sat, 6 Jun 2026 19:54:36 +0200 Subject: [PATCH 08/13] Drop legacy requires_api_password from discovery announcement (#173090) Co-authored-by: Claude Opus 4.8 (1M context) --- homeassistant/components/api/__init__.py | 1 - homeassistant/components/zeroconf/__init__.py | 2 -- tests/components/zeroconf/test_repairs.py | 1 - 3 files changed, 4 deletions(-) diff --git a/homeassistant/components/api/__init__.py b/homeassistant/components/api/__init__.py index 933fca543deec3..ded5f8e57be606 100644 --- a/homeassistant/components/api/__init__.py +++ b/homeassistant/components/api/__init__.py @@ -59,7 +59,6 @@ ATTR_INTERNAL_URL = "internal_url" ATTR_LOCATION_NAME = "location_name" ATTR_INSTALLATION_TYPE = "installation_type" -ATTR_REQUIRES_API_PASSWORD = "requires_api_password" ATTR_UUID = "uuid" ATTR_VERSION = "version" diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 6644315abb5de7..3ac49daad3dd7f 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -258,8 +258,6 @@ async def _async_get_local_service_info(hass: HomeAssistant) -> AsyncServiceInfo "internal_url": "", # Old base URL, for backward compatibility "base_url": "", - # Always needs authentication - "requires_api_password": True, } # Get instance URL's diff --git a/tests/components/zeroconf/test_repairs.py b/tests/components/zeroconf/test_repairs.py index e24c296b0eb1a9..ad77b69fa85fad 100644 --- a/tests/components/zeroconf/test_repairs.py +++ b/tests/components/zeroconf/test_repairs.py @@ -58,7 +58,6 @@ def _get_hass_service_info_mock( "external_url": None, "internal_url": "http://10.0.0.1:8123", "location_name": "Home", - "requires_api_password": "True", "uuid": instance_id, "version": "2025.9.0.dev0", }, From 6ee819cdc3d75935db5eb94a855856918a6e97f9 Mon Sep 17 00:00:00 2001 From: Vincent Knoop Pathuis <48653141+vpathuis@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:14:01 +0200 Subject: [PATCH 09/13] Bump to Ultraheat 0.6.1 (#173175) --- homeassistant/components/landisgyr_heat_meter/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/landisgyr_heat_meter/manifest.json b/homeassistant/components/landisgyr_heat_meter/manifest.json index 1161134c5de520..8ca5c1b5933f2f 100644 --- a/homeassistant/components/landisgyr_heat_meter/manifest.json +++ b/homeassistant/components/landisgyr_heat_meter/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/landisgyr_heat_meter", "integration_type": "device", "iot_class": "local_polling", - "requirements": ["ultraheat-api==0.6.0"] + "requirements": ["ultraheat-api==0.6.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 9c3441e395bcc0..adae8796cc5778 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -3249,7 +3249,7 @@ uhooapi==1.2.8 uiprotect==10.5.0 # homeassistant.components.landisgyr_heat_meter -ultraheat-api==0.6.0 +ultraheat-api==0.6.1 # homeassistant.components.unifi_discovery unifi-discovery==1.4.0 From 26d56b821895c8e97d8a7850ab6d45daabe5a825 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:14:46 +0200 Subject: [PATCH 10/13] Use DOMAIN constant in test (async_setup_component o-z) (#173018) --- tests/components/onboarding/test_init.py | 9 +- tests/components/onboarding/test_views.py | 50 ++++---- .../openai_conversation/conftest.py | 2 +- .../openai_conversation/test_init.py | 4 +- tests/components/otbr/test_websocket_api.py | 9 +- .../owntracks/test_device_tracker.py | 2 +- tests/components/owntracks/test_init.py | 2 +- tests/components/person/test_init.py | 4 +- .../prusalink/test_binary_sensor.py | 13 +- tests/components/prusalink/test_button.py | 9 +- tests/components/prusalink/test_camera.py | 7 +- tests/components/prusalink/test_sensor.py | 15 +-- tests/components/python_script/test_init.py | 12 +- tests/components/recovery_mode/test_init.py | 3 +- tests/components/repairs/__init__.py | 3 +- tests/components/rflink/test_init.py | 2 +- .../components/rss_feed_template/test_init.py | 3 +- tests/components/scene/test_init.py | 3 +- tests/components/script/test_init.py | 44 +++---- tests/components/script/test_recorder.py | 3 +- tests/components/search/test_init.py | 4 +- tests/components/sensor/test_init.py | 82 ++++++------- tests/components/sensor/test_recorder.py | 112 +++++++++--------- .../sensor/test_recorder_missing_stats.py | 5 +- tests/components/spaceapi/test_init.py | 6 +- .../spc/test_alarm_control_panel.py | 3 +- tests/components/spc/test_init.py | 5 +- tests/components/stream/test_hls.py | 3 +- tests/components/stream/test_init.py | 10 +- tests/components/stream/test_ll_hls.py | 14 +-- tests/components/stream/test_recorder.py | 3 +- tests/components/stream/test_worker.py | 10 +- tests/components/stt/test_init.py | 8 +- tests/components/switch/test_init.py | 3 +- tests/components/switch/test_light.py | 5 +- tests/components/system_health/test_init.py | 12 +- tests/components/template/test_blueprint.py | 12 +- tests/components/template/test_config.py | 6 +- tests/components/template/test_entity.py | 2 +- tests/components/template/test_image.py | 18 +-- tests/components/template/test_select.py | 2 +- tests/components/template/test_sensor.py | 7 +- .../template/test_trigger_entity.py | 4 +- tests/components/template/test_weather.py | 6 +- tests/components/text/test_init.py | 4 +- tests/components/timer/test_init.py | 4 +- tests/components/tts/test_init.py | 3 +- .../components/usage_prediction/test_init.py | 4 +- .../usage_prediction/test_websocket.py | 5 +- tests/components/voip/test_voip.py | 34 +++--- tests/components/weather/test_intent.py | 6 +- tests/components/web_rtc/test_init.py | 15 +-- tests/components/webhook/test_init.py | 13 +- tests/components/webhook/test_trigger.py | 3 +- tests/components/websocket_api/conftest.py | 3 +- tests/components/websocket_api/test_auth.py | 27 +++-- .../components/websocket_api/test_commands.py | 4 +- tests/components/websocket_api/test_http.py | 3 +- 58 files changed, 348 insertions(+), 321 deletions(-) diff --git a/tests/components/onboarding/test_init.py b/tests/components/onboarding/test_init.py index 6688ecccb5d5f1..8a43640bcdd5eb 100644 --- a/tests/components/onboarding/test_init.py +++ b/tests/components/onboarding/test_init.py @@ -4,6 +4,7 @@ from unittest.mock import Mock, patch from homeassistant.components import onboarding +from homeassistant.components.onboarding import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -21,7 +22,7 @@ async def test_not_setup_views_if_onboarded( mock_storage(hass_storage, {"done": onboarding.STEPS}) with patch("homeassistant.components.onboarding.views.async_setup") as mock_setup: - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert len(mock_setup.mock_calls) == 0 assert onboarding.DOMAIN not in hass.data @@ -33,7 +34,7 @@ async def test_setup_views_if_not_onboarded(hass: HomeAssistant) -> None: with patch( "homeassistant.components.onboarding.views.async_setup", ) as mock_setup: - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert len(mock_setup.mock_calls) == 1 assert onboarding.DOMAIN in hass.data @@ -84,7 +85,7 @@ async def test_having_owner_finishes_user_step( patch("homeassistant.components.onboarding.views.async_setup") as mock_setup, patch.object(onboarding, "STEPS", [onboarding.STEP_USER]), ): - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert len(mock_setup.mock_calls) == 0 assert onboarding.DOMAIN not in hass.data @@ -97,5 +98,5 @@ async def test_having_owner_finishes_user_step( async def test_migration(hass: HomeAssistant, hass_storage: dict[str, Any]) -> None: """Test migrating onboarding to new version.""" hass_storage[onboarding.STORAGE_KEY] = {"version": 1, "data": {"done": ["user"]}} - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert onboarding.async_is_onboarded(hass) diff --git a/tests/components/onboarding/test_views.py b/tests/components/onboarding/test_views.py index b895e2969d9c4c..02e695002887ab 100644 --- a/tests/components/onboarding/test_views.py +++ b/tests/components/onboarding/test_views.py @@ -11,7 +11,7 @@ import pytest from homeassistant.components import onboarding -from homeassistant.components.onboarding import const, views +from homeassistant.components.onboarding import DOMAIN, const, views from homeassistant.core import HomeAssistant from homeassistant.helpers import area_registry as ar from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component @@ -110,7 +110,7 @@ async def test_onboarding_progress( """Test fetching progress.""" mock_storage(hass_storage, {"done": ["hello"]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -134,7 +134,7 @@ async def test_onboarding_user_already_done( mock_storage(hass_storage, {"done": [views.STEP_USER]}) with patch.object(onboarding, "STEPS", ["hello", "world"]): - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -165,7 +165,7 @@ async def test_onboarding_user( area_registry.async_create("Living Room") assert await async_setup_component(hass, "person", {}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() cur_users = len(await hass.auth.async_get_users()) @@ -228,7 +228,7 @@ async def test_onboarding_user_invalid_name( """Test not providing name.""" mock_storage(hass_storage, {"done": []}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -254,7 +254,7 @@ async def test_onboarding_user_race( """Test race condition on creating new user.""" mock_storage(hass_storage, {"done": ["hello"]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -294,7 +294,7 @@ async def test_onboarding_integration( """Test finishing integration step.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -338,7 +338,7 @@ async def test_onboarding_integration_missing_credential( """Test that we fail integration step if user is missing credentials.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() refresh_token = hass.auth.async_validate_access_token(hass_access_token) @@ -362,7 +362,7 @@ async def test_onboarding_integration_invalid_redirect_uri( """Test finishing integration step.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -396,7 +396,7 @@ async def test_onboarding_integration_requires_auth( """Test finishing integration step.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -417,7 +417,7 @@ async def test_onboarding_core_sets_up_met( """Test finishing the core step.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -438,7 +438,7 @@ async def test_onboarding_core_sets_up_shopping_list( """Test finishing the core step set up the shopping list.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -459,7 +459,7 @@ async def test_onboarding_core_sets_up_google_translate( """Test finishing the core step sets up google translate.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -480,7 +480,7 @@ async def test_onboarding_core_sets_up_radio_browser( """Test finishing the core step set up the radio browser.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -502,7 +502,7 @@ async def test_onboarding_core_no_rpi_power( """Test that the core step do not set up rpi_power on non RPi.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -527,7 +527,7 @@ async def test_onboarding_core_ensures_analytics_loaded( mock_storage(hass_storage, {"done": [const.STEP_USER]}) assert "analytics" not in hass.config.components - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -548,7 +548,7 @@ async def test_onboarding_analytics( """Test finishing analytics step.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -571,7 +571,7 @@ async def test_onboarding_installation_type( """Test returning installation type during onboarding.""" mock_storage(hass_storage, {"done": []}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -605,7 +605,7 @@ async def test_onboarding_view_after_done( """Test raising after onboarding.""" mock_storage(hass_storage, {"done": [const.STEP_USER]}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -623,7 +623,7 @@ async def test_complete_onboarding( onboarding.async_add_listener(hass, listener_1) listener_1.assert_not_called() - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() listener_2 = Mock() @@ -693,7 +693,7 @@ async def test_wait_integration( """Test we can get wait for an integration to load.""" mock_storage(hass_storage, {"done": []}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -712,7 +712,7 @@ async def test_wait_integration_startup( """Test we can get wait for an integration to load during startup.""" mock_storage(hass_storage, {"done": []}) - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client() @@ -767,7 +767,7 @@ async def test_not_setup_platform_if_onboarded( assert await async_setup_component(hass, "test", {}) await hass.async_block_till_done() - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() assert len(platform_mock.async_setup_views.mock_calls) == 0 @@ -782,7 +782,7 @@ async def test_setup_platform_if_not_onboarded( assert await async_setup_component(hass, "test", {}) await hass.async_block_till_done() - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() platform_mock.async_setup_views.assert_awaited_once_with(hass, {"done": []}) @@ -805,7 +805,7 @@ async def test_bad_platform( assert await async_setup_component(hass, "test", {}) await hass.async_block_till_done() - assert await async_setup_component(hass, "onboarding", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() assert platform_mock.mock_calls == [] diff --git a/tests/components/openai_conversation/conftest.py b/tests/components/openai_conversation/conftest.py index 1c90fc2635cf65..2839fe10a0cae6 100644 --- a/tests/components/openai_conversation/conftest.py +++ b/tests/components/openai_conversation/conftest.py @@ -125,7 +125,7 @@ async def mock_init_component( with patch( "openai.resources.models.AsyncModels.list", ): - assert await async_setup_component(hass, "openai_conversation", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() diff --git a/tests/components/openai_conversation/test_init.py b/tests/components/openai_conversation/test_init.py index f1bb3b689c3829..f8d85e353e7412 100644 --- a/tests/components/openai_conversation/test_init.py +++ b/tests/components/openai_conversation/test_init.py @@ -284,7 +284,7 @@ async def test_init_error( "openai.resources.models.AsyncModels.list", side_effect=side_effect, ): - assert await async_setup_component(hass, "openai_conversation", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() assert error in caplog.text assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY @@ -305,7 +305,7 @@ async def test_init_auth_error( message="", ), ): - assert await async_setup_component(hass, "openai_conversation", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR diff --git a/tests/components/otbr/test_websocket_api.py b/tests/components/otbr/test_websocket_api.py index 7311b194df465c..0b7d2bc8e2a92d 100644 --- a/tests/components/otbr/test_websocket_api.py +++ b/tests/components/otbr/test_websocket_api.py @@ -6,6 +6,7 @@ import python_otbr_api from homeassistant.components import otbr, thread +from homeassistant.components.otbr import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -85,7 +86,7 @@ async def test_get_info_no_entry( hass_ws_client: WebSocketGenerator, ) -> None: """Test async_get_info.""" - await async_setup_component(hass, "otbr", {}) + await async_setup_component(hass, DOMAIN, {}) websocket_client = await hass_ws_client(hass) await websocket_client.send_json_auto_id({"type": "otbr/info"}) @@ -175,7 +176,7 @@ async def test_create_network_no_entry( hass_ws_client: WebSocketGenerator, ) -> None: """Test create network.""" - await async_setup_component(hass, "otbr", {}) + await async_setup_component(hass, DOMAIN, {}) websocket_client = await hass_ws_client(hass) await websocket_client.send_json_auto_id( {"type": "otbr/create_network", "extended_address": "blah"} @@ -470,7 +471,7 @@ async def test_set_network_no_entry( hass_ws_client: WebSocketGenerator, ) -> None: """Test set network.""" - await async_setup_component(hass, "otbr", {}) + await async_setup_component(hass, DOMAIN, {}) websocket_client = await hass_ws_client(hass) await websocket_client.send_json_auto_id( { @@ -761,7 +762,7 @@ async def test_set_channel_no_entry( hass_ws_client: WebSocketGenerator, ) -> None: """Test set channel.""" - await async_setup_component(hass, "otbr", {}) + await async_setup_component(hass, DOMAIN, {}) websocket_client = await hass_ws_client(hass) await websocket_client.send_json_auto_id( { diff --git a/tests/components/owntracks/test_device_tracker.py b/tests/components/owntracks/test_device_tracker.py index 5ed875aebc5a82..9c89eb12dcbb78 100644 --- a/tests/components/owntracks/test_device_tracker.py +++ b/tests/components/owntracks/test_device_tracker.py @@ -332,7 +332,7 @@ async def setup_owntracks( ).add_to_hass(hass) with patch.object(owntracks, "OwnTracksContext", ctx_cls): - assert await async_setup_component(hass, "owntracks", {"owntracks": config}) + assert await async_setup_component(hass, DOMAIN, {"owntracks": config}) await hass.async_block_till_done() diff --git a/tests/components/owntracks/test_init.py b/tests/components/owntracks/test_init.py index 62a088c8b40448..b84ed13743aa76 100644 --- a/tests/components/owntracks/test_init.py +++ b/tests/components/owntracks/test_init.py @@ -55,7 +55,7 @@ async def mock_client( MockConfigEntry( domain=DOMAIN, data={"webhook_id": "owntracks_test", "secret": "abcd"} ).add_to_hass(hass) - await async_setup_component(hass, "owntracks", {}) + await async_setup_component(hass, DOMAIN, {}) return await hass_client_no_auth() diff --git a/tests/components/person/test_init.py b/tests/components/person/test_init.py index 50209b38ab6549..9c0595dc8cbee7 100644 --- a/tests/components/person/test_init.py +++ b/tests/components/person/test_init.py @@ -1469,7 +1469,7 @@ async def test_persons_with_entity(hass: HomeAssistant) -> None: """Test finding persons with an entity.""" assert await async_setup_component( hass, - "person", + DOMAIN, { "person": [ { @@ -1500,7 +1500,7 @@ async def test_entities_in_person(hass: HomeAssistant) -> None: """Test finding entities tracked by person.""" assert await async_setup_component( hass, - "person", + DOMAIN, { "person": [ { diff --git a/tests/components/prusalink/test_binary_sensor.py b/tests/components/prusalink/test_binary_sensor.py index cf8aa1fc2eb5e6..1e987f892680f4 100644 --- a/tests/components/prusalink/test_binary_sensor.py +++ b/tests/components/prusalink/test_binary_sensor.py @@ -5,6 +5,7 @@ import pytest +from homeassistant.components.prusalink import DOMAIN from homeassistant.const import STATE_OFF, STATE_ON, Platform from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -26,7 +27,7 @@ async def test_binary_sensors_no_job( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """Test sensors while no job active.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("binary_sensor.workshop_mock_title_mmu") assert state is not None @@ -37,7 +38,7 @@ async def test_status_connect_enabled_by_default( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """Connect binary sensor is enabled by default and reflects status_connect.ok.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("binary_sensor.workshop_mock_title_connectivity") assert state is not None @@ -52,7 +53,7 @@ async def test_status_connect_not_created_when_absent( ) -> None: """Connect sensor is not created when status_connect is not in the response.""" del mock_get_status_idle["printer"]["status_connect"] - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert hass.states.get("binary_sensor.workshop_mock_title_connectivity") is None @@ -62,7 +63,7 @@ async def test_sd_ready( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """SD card sensor reflects sd_ready from info endpoint.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("binary_sensor.workshop_mock_title_sd_card") assert state is not None @@ -74,7 +75,7 @@ async def test_farm_mode( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """Farm mode sensor reflects farm_mode from info endpoint.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("binary_sensor.workshop_mock_title_farm_mode") assert state is not None @@ -90,6 +91,6 @@ async def test_farm_mode_not_created_when_absent( ) -> None: """Farm mode sensor is not created when farm_mode field is absent from info.""" del mock_info_api["farm_mode"] - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert hass.states.get("binary_sensor.workshop_mock_title_farm_mode") is None diff --git a/tests/components/prusalink/test_button.py b/tests/components/prusalink/test_button.py index 3f66a6619d629b..c29c1294530e01 100644 --- a/tests/components/prusalink/test_button.py +++ b/tests/components/prusalink/test_button.py @@ -6,6 +6,7 @@ from pyprusalink.types import Conflict import pytest +from homeassistant.components.prusalink import DOMAIN from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError @@ -76,7 +77,7 @@ async def test_button_pause_cancel( method: str, ) -> None: """Test cancel and pause buttons in PRINTING state.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) await press_button_and_verify(f"button.{object_id}", method) @@ -97,7 +98,7 @@ async def test_button_resume_cancel( method: str, ) -> None: """Test cancel and resume buttons in PAUSED state.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) await press_button_and_verify(f"button.{object_id}", method) @@ -109,7 +110,7 @@ async def test_button_continue( press_button_and_verify, ) -> None: """Test continue button is enabled in ATTENTION state and calls continue_job.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) await press_button_and_verify( "button.workshop_mock_title_continue_job", "continue_job" ) @@ -123,7 +124,7 @@ async def test_button_continue_unavailable_when_printing( mock_get_status_printing, ) -> None: """Continue button is unavailable when printer is not in ATTENTION state.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("button.workshop_mock_title_continue_job") assert state is not None assert state.state == "unavailable" diff --git a/tests/components/prusalink/test_camera.py b/tests/components/prusalink/test_camera.py index db7ea835f514dd..86a60a783c5465 100644 --- a/tests/components/prusalink/test_camera.py +++ b/tests/components/prusalink/test_camera.py @@ -4,6 +4,7 @@ import pytest +from homeassistant.components.prusalink import DOMAIN from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -25,7 +26,7 @@ async def test_camera_no_job( hass_client: ClientSessionGenerator, ) -> None: """Test camera while no job active.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("camera.workshop_mock_title_preview") assert state is not None assert state.state == "unavailable" @@ -43,7 +44,7 @@ async def test_camera_idle_job_mk3( hass_client: ClientSessionGenerator, ) -> None: """Test camera while job state is idle (MK3).""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("camera.workshop_mock_title_preview") assert state is not None assert state.state == "unavailable" @@ -61,7 +62,7 @@ async def test_camera_active_job( hass_client: ClientSessionGenerator, ) -> None: """Test camera while job active.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("camera.workshop_mock_title_preview") assert state is not None assert state.state == "idle" diff --git a/tests/components/prusalink/test_sensor.py b/tests/components/prusalink/test_sensor.py index 5c4ee7f87f8d16..454e80f6cc8717 100644 --- a/tests/components/prusalink/test_sensor.py +++ b/tests/components/prusalink/test_sensor.py @@ -6,6 +6,7 @@ import pytest +from homeassistant.components.prusalink import DOMAIN from homeassistant.components.sensor import ( ATTR_OPTIONS, ATTR_STATE_CLASS, @@ -37,7 +38,7 @@ def setup_sensor_platform_only(): @pytest.mark.usefixtures("entity_registry_enabled_by_default") async def test_sensors_no_job(hass: HomeAssistant, mock_config_entry, mock_api) -> None: """Test sensors while no job active.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("sensor.workshop_mock_title") assert state is not None @@ -146,7 +147,7 @@ async def test_sensors_idle_job_mk3( mock_job_api_idle_mk3, ) -> None: """Test sensors while job state is idle (MK3).""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("sensor.workshop_mock_title") assert state is not None @@ -260,7 +261,7 @@ async def test_sensors_active_job( "homeassistant.components.prusalink.sensor.utcnow", return_value=datetime(2022, 8, 27, 14, 0, 0, tzinfo=UTC), ): - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("sensor.workshop_mock_title") assert state is not None @@ -301,7 +302,7 @@ async def test_axis_x_y_sensors( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """Test X and Y axis position sensors.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("sensor.workshop_mock_title_x_position") assert state is not None @@ -328,7 +329,7 @@ async def test_axis_x_y_not_created_when_absent( """X and Y sensors are not created when axis fields are absent from the response.""" del mock_get_status_idle["printer"]["axis_x"] del mock_get_status_idle["printer"]["axis_y"] - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert hass.states.get("sensor.workshop_mock_title_x_position") is None assert hass.states.get("sensor.workshop_mock_title_y_position") is None @@ -339,7 +340,7 @@ async def test_min_extrusion_temp_sensor( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None ) -> None: """Test minimum extrusion temperature sensor from info endpoint.""" - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) state = hass.states.get("sensor.workshop_mock_title_minimum_extrusion_temperature") assert state is not None @@ -358,7 +359,7 @@ async def test_min_extrusion_temp_not_created_when_absent( ) -> None: """Min extrusion temp sensor is not created when the info field is absent.""" del mock_info_api["min_extrusion_temp"] - assert await async_setup_component(hass, "prusalink", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert ( hass.states.get("sensor.workshop_mock_title_minimum_extrusion_temperature") diff --git a/tests/components/python_script/test_init.py b/tests/components/python_script/test_init.py index bb380a5d840ca2..a5185a5a8c7e84 100644 --- a/tests/components/python_script/test_init.py +++ b/tests/components/python_script/test_init.py @@ -28,7 +28,7 @@ async def test_setup(hass: HomeAssistant) -> None: "homeassistant.components.python_script.glob.iglob", return_value=scripts ), ): - res = await async_setup_component(hass, "python_script", {}) + res = await async_setup_component(hass, DOMAIN, {}) assert res assert hass.services.has_service("python_script", "hello") @@ -60,7 +60,7 @@ async def test_setup_fails_on_no_dir( with patch( "homeassistant.components.python_script.os.path.isdir", return_value=False ): - res = await async_setup_component(hass, "python_script", {}) + res = await async_setup_component(hass, DOMAIN, {}) assert not res assert "Folder python_scripts not found in configuration folder" in caplog.text @@ -371,7 +371,7 @@ async def test_reload(hass: HomeAssistant) -> None: "homeassistant.components.python_script.glob.iglob", return_value=scripts ), ): - res = await async_setup_component(hass, "python_script", {}) + res = await async_setup_component(hass, DOMAIN, {}) assert res assert hass.services.has_service("python_script", "hello") @@ -537,7 +537,7 @@ async def test_execute_with_output( "homeassistant.components.python_script.glob.iglob", return_value=scripts ), ): - await async_setup_component(hass, "python_script", {}) + await async_setup_component(hass, DOMAIN, {}) source = """ output = {"result": f"hello {data.get('name', 'World')}"} @@ -581,7 +581,7 @@ async def test_execute_no_output( "homeassistant.components.python_script.glob.iglob", return_value=scripts ), ): - await async_setup_component(hass, "python_script", {}) + await async_setup_component(hass, DOMAIN, {}) source = """ no_output = {"result": f"hello {data.get('name', 'World')}"} @@ -620,7 +620,7 @@ async def test_execute_wrong_output_type(hass: HomeAssistant) -> None: "homeassistant.components.python_script.glob.iglob", return_value=scripts ), ): - await async_setup_component(hass, "python_script", {}) + await async_setup_component(hass, DOMAIN, {}) source = """ output = f"hello {data.get('name', 'World')}" diff --git a/tests/components/recovery_mode/test_init.py b/tests/components/recovery_mode/test_init.py index 506cd010725db4..fc235c058d8d51 100644 --- a/tests/components/recovery_mode/test_init.py +++ b/tests/components/recovery_mode/test_init.py @@ -1,5 +1,6 @@ """Tests for the Recovery Mode integration.""" +from homeassistant.components.recovery_mode import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -8,7 +9,7 @@ async def test_works(hass: HomeAssistant) -> None: """Test Recovery Mode works.""" - assert await async_setup_component(hass, "recovery_mode", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() notifications = async_get_persistent_notifications(hass) assert len(notifications) == 1 diff --git a/tests/components/repairs/__init__.py b/tests/components/repairs/__init__.py index 7d5e4a43cd8919..84c33bc206f0bc 100644 --- a/tests/components/repairs/__init__.py +++ b/tests/components/repairs/__init__.py @@ -5,6 +5,7 @@ from aiohttp.test_utils import TestClient +from homeassistant.components.repairs import DOMAIN from homeassistant.components.repairs.issue_handler import ( # noqa: F401 async_process_repairs_platforms, ) @@ -23,7 +24,7 @@ async def get_repairs( hass_ws_client: WebSocketGenerator, ): """Return the repairs list of issues.""" - assert await async_setup_component(hass, "repairs", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass) await hass.async_block_till_done() diff --git a/tests/components/rflink/test_init.py b/tests/components/rflink/test_init.py index 3250e97ee6c51e..09233a70904521 100644 --- a/tests/components/rflink/test_init.py +++ b/tests/components/rflink/test_init.py @@ -72,7 +72,7 @@ async def create_rflink_connection(*args, **kwargs): "homeassistant.components.rflink.create_rflink_connection", mock_create ) - await async_setup_component(hass, "rflink", config) + await async_setup_component(hass, DOMAIN, config) if old_yaml: await async_setup_component(hass, domain, config) diff --git a/tests/components/rss_feed_template/test_init.py b/tests/components/rss_feed_template/test_init.py index 3b708b577afab0..7dcb78d0ce9c09 100644 --- a/tests/components/rss_feed_template/test_init.py +++ b/tests/components/rss_feed_template/test_init.py @@ -6,6 +6,7 @@ from defusedxml import ElementTree import pytest +from homeassistant.components.rss_feed_template import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -32,7 +33,7 @@ async def mock_http_client( } } - await async_setup_component(hass, "rss_feed_template", config) + await async_setup_component(hass, DOMAIN, config) return await hass_client() diff --git a/tests/components/scene/test_init.py b/tests/components/scene/test_init.py index 3747610298d16a..6c86a96df4f03a 100644 --- a/tests/components/scene/test_init.py +++ b/tests/components/scene/test_init.py @@ -6,6 +6,7 @@ import pytest from homeassistant.components import light, scene +from homeassistant.components.scene import DOMAIN from homeassistant.const import ( ATTR_ENTITY_ID, ENTITY_MATCH_ALL, @@ -234,7 +235,7 @@ async def activate(hass: HomeAssistant, entity_id: str = ENTITY_MATCH_ALL) -> No async def test_services_registered(hass: HomeAssistant) -> None: """Test we register services with empty config.""" - assert await async_setup_component(hass, "scene", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() assert hass.services.has_service("scene", "reload") assert hass.services.has_service("scene", "turn_on") diff --git a/tests/components/script/test_init.py b/tests/components/script/test_init.py index 1d0d6b7a179078..98dc7811056991 100644 --- a/tests/components/script/test_init.py +++ b/tests/components/script/test_init.py @@ -79,7 +79,7 @@ def record_call(service): assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -148,7 +148,7 @@ def state_listener(entity_id, old_state, new_state): } assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -203,7 +203,7 @@ async def test_setup_with_invalid_configs( hass: HomeAssistant, config, nbr_script_entities ) -> None: """Test setup with invalid configs.""" - assert await async_setup_component(hass, "script", {"script": config}) + assert await async_setup_component(hass, DOMAIN, {"script": config}) assert len(hass.states.async_entity_ids(DOMAIN)) == nbr_script_entities @@ -385,7 +385,7 @@ def event_handler(event): assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -561,7 +561,7 @@ async def test_service_descriptions(hass: HomeAssistant) -> None: # Test 1: has "description" but no "fields" assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -640,7 +640,7 @@ async def test_shared_context(hass: HomeAssistant) -> None: hass.bus.async_listen(EVENT_SCRIPT_STARTED, run_mock) assert await async_setup_component( - hass, "script", {"script": {"test": {"sequence": [{"event": event}]}}} + hass, DOMAIN, {"script": {"test": {"sequence": [{"event": event}]}}} ) await hass.services.async_call( @@ -673,7 +673,7 @@ async def test_logging_script_error( """Test logging script error.""" assert await async_setup_component( hass, - "script", + DOMAIN, {"script": {"hello": {"sequence": [{"action": "non.existing"}]}}}, ) with pytest.raises(ServiceNotFound) as err: @@ -686,7 +686,7 @@ async def test_logging_script_error( async def test_turning_no_scripts_off(hass: HomeAssistant) -> None: """Test it is possible to turn two scripts off.""" - assert await async_setup_component(hass, "script", {}) + assert await async_setup_component(hass, DOMAIN, {}) # Testing it doesn't raise await hass.services.async_call( @@ -948,7 +948,7 @@ async def test_config_basic( """Test passing info in config.""" assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test_script": { @@ -973,7 +973,7 @@ async def test_config_multiple_domains(hass: HomeAssistant) -> None: """Test splitting configuration over multiple domains.""" assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "first_script": { @@ -1043,7 +1043,7 @@ async def test_concurrent_script(hass: HomeAssistant, concurrently) -> None: call_script_2 = {"action": "script.script2"} assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "script1": { @@ -1127,7 +1127,7 @@ async def test_script_variables( """Test defining scripts.""" assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "script1": { @@ -1229,7 +1229,7 @@ async def test_script_this_var_always( assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "script1": { @@ -1269,7 +1269,7 @@ async def test_script_restore_last_triggered(hass: HomeAssistant) -> None: assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "no_last_triggered": { @@ -1314,7 +1314,7 @@ async def test_recursive_script( assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "script1": { @@ -1364,7 +1364,7 @@ async def test_recursive_script_indirect( assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "script1": { @@ -1503,7 +1503,7 @@ async def test_setup_with_duplicate_scripts( """Test setup with duplicate configs.""" assert await async_setup_component( hass, - "script", + DOMAIN, { "script one": { "duplicate": { @@ -1531,7 +1531,7 @@ async def test_websocket_config( } assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "hello": config, @@ -1586,7 +1586,7 @@ def record_call(service): # Make sure the service of a script with overridden entity_id works assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -1769,7 +1769,7 @@ async def test_responses(hass: HomeAssistant, response: Any) -> None: mock_restore_cache(hass, ()) assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -1804,7 +1804,7 @@ async def test_responses_no_response(hass: HomeAssistant) -> None: mock_restore_cache(hass, ()) assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { @@ -1890,7 +1890,7 @@ async def test_reload_when_labs_flag_changes( assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { diff --git a/tests/components/script/test_recorder.py b/tests/components/script/test_recorder.py index 8c4fb765bacdbe..6e535b88ae4094 100644 --- a/tests/components/script/test_recorder.py +++ b/tests/components/script/test_recorder.py @@ -11,6 +11,7 @@ ATTR_LAST_TRIGGERED, ATTR_MAX, ATTR_MODE, + DOMAIN, ) from homeassistant.const import ATTR_FRIENDLY_NAME from homeassistant.core import Context, HomeAssistant, ServiceCall, callback @@ -45,7 +46,7 @@ def record_call(service): assert await async_setup_component( hass, - "script", + DOMAIN, { "script": { "test": { diff --git a/tests/components/search/test_init.py b/tests/components/search/test_init.py index 268f829ba0a02e..df99522f9dde5b 100644 --- a/tests/components/search/test_init.py +++ b/tests/components/search/test_init.py @@ -2,7 +2,7 @@ from pytest_unordered import unordered -from homeassistant.components.search import ItemType, Searcher +from homeassistant.components.search import DOMAIN, ItemType, Searcher from homeassistant.core import HomeAssistant from homeassistant.helpers import ( area_registry as ar, @@ -28,7 +28,7 @@ async def test_search( hass_ws_client: WebSocketGenerator, ) -> None: """Test search.""" - assert await async_setup_component(hass, "search", {}) + assert await async_setup_component(hass, DOMAIN, {}) # Labels label_energy = label_registry.async_create("Energy") diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index dc09bddfe10adc..5a243834a7a248 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -141,7 +141,7 @@ async def test_temperature_conversion( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -162,7 +162,7 @@ async def test_temperature_conversion_wrong_device_class( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Check compatible unit is applied @@ -189,7 +189,7 @@ async def test_ambiguous_unit_of_measurement_compat( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Check temperature is not converted @@ -218,7 +218,7 @@ async def test_deprecated_last_reset( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -263,7 +263,7 @@ async def test_datetime_conversion( ] setup_test_component_platform(hass, sensor.DOMAIN, entities) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entities[0].entity_id) @@ -296,7 +296,7 @@ async def test_uptime_device_class_auto_normalizes_drift( entity._attr_uptime_drift_tolerance = drift_tolerance setup_test_component_platform(hass, sensor.DOMAIN, [entity]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert (state := hass.states.get(entity.entity_id)) @@ -350,7 +350,7 @@ async def test_a_sensor_with_a_non_numeric_device_class( ] setup_test_component_platform(hass, sensor.DOMAIN, entities) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entities[0].entity_id) @@ -380,7 +380,7 @@ async def test_deprecated_datetime_str( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -402,7 +402,7 @@ async def test_reject_timezoneless_datetime_str( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -500,7 +500,7 @@ async def test_restore_sensor_save_state( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Trigger saving state @@ -528,7 +528,7 @@ async def test_restore_sensor_save_state_frozen_time_datetime( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Trigger saving state @@ -556,7 +556,7 @@ async def test_restore_sensor_save_state_frozen_time_date( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Trigger saving state @@ -622,7 +622,7 @@ async def test_restore_sensor_restore_state( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert hass.states.get(entity0.entity_id) @@ -656,7 +656,7 @@ async def test_translated_unit( setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) assert await async_setup_component( - hass, "sensor", {"sensor": {"platform": "test"}} + hass, DOMAIN, {"sensor": {"platform": "test"}} ) await hass.async_block_till_done() @@ -690,7 +690,7 @@ async def test_translated_unit_with_native_unit_raises( setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) assert await async_setup_component( - hass, "sensor", {"sensor": {"platform": "test"}} + hass, DOMAIN, {"sensor": {"platform": "test"}} ) await hass.async_block_till_done() # Setup fails so entity_id is None @@ -728,7 +728,7 @@ async def test_unit_translation_key_without_platform_raises( setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) assert await async_setup_component( - hass, "sensor", {"sensor": {"platform": "test"}} + hass, DOMAIN, {"sensor": {"platform": "test"}} ) await hass.async_block_till_done() @@ -961,7 +961,7 @@ async def test_custom_unit( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() entity_id = entity0.entity_id @@ -1256,7 +1256,7 @@ async def test_custom_unit_change( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -1392,7 +1392,7 @@ async def test_unit_conversion_priority( ], ) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Registered entity -> Follow automatic unit conversion @@ -1554,7 +1554,7 @@ async def test_unit_conversion_priority_precision( ], ) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Registered entity -> Follow automatic unit conversion @@ -1716,7 +1716,7 @@ async def test_unit_conversion_priority_suggested_unit_change( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0, entity1]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Registered entity -> Follow automatic unit conversion the first @@ -1814,7 +1814,7 @@ async def test_unit_conversion_priority_suggested_unit_change_2( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0, entity1]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Registered entity -> Follow unit in entity registry @@ -1915,7 +1915,7 @@ async def test_default_precision( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() entry = entity_registry.async_get(entity0.entity_id) @@ -1980,7 +1980,7 @@ async def test_suggested_precision_option( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Assert the suggested precision is stored in the registry @@ -2073,7 +2073,7 @@ async def test_suggested_precision_option_update( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Assert the suggested precision is stored in the registry @@ -2145,7 +2145,7 @@ async def test_unit_conversion_priority_legacy_conversion_removed( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -2184,7 +2184,7 @@ async def test_value_unknown_in_enumeration( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2206,7 +2206,7 @@ async def test_invalid_enumeration_entity_with_device_class( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2227,7 +2227,7 @@ async def test_invalid_enumeration_entity_without_device_class( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2260,7 +2260,7 @@ async def test_non_numeric_device_class_with_unit_of_measurement( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2340,7 +2340,7 @@ async def test_device_classes_with_invalid_unit_of_measurement( str(unit) if unit else "no unit of measurement" for unit in DEVICE_CLASS_UNITS.get(device_class, set()) ] - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2371,7 +2371,7 @@ async def test_state_classes_with_invalid_unit_of_measurement( str(unit) if unit else "no unit of measurement" for unit in STATE_CLASS_UNITS.get(state_class, set()) } - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -2424,7 +2424,7 @@ async def test_non_numeric_validation_error( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -2469,7 +2469,7 @@ async def test_non_numeric_validation_raise( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -2516,7 +2516,7 @@ async def test_numeric_validation( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -2541,7 +2541,7 @@ async def test_numeric_validation_ignores_custom_device_class( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -2571,7 +2571,7 @@ async def test_device_classes_with_invalid_state_class( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() classes = DEVICE_CLASS_STATE_CLASSES.get(device_class, set()) @@ -2625,7 +2625,7 @@ async def test_numeric_state_expected_helper( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) @@ -3015,7 +3015,7 @@ async def test_entity_category_config_raises_error( entity0 = MockSensor(name="Test", entity_category=EntityCategory.CONFIG) setup_test_component_platform(hass, sensor.DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert ( @@ -3057,7 +3057,7 @@ async def test_suggested_unit_guard_invalid_unit( unique_id="invalid", ) setup_test_component_platform(hass, sensor.DOMAIN, [entity]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() assert not hass.states.get("sensor.invalid") @@ -3119,7 +3119,7 @@ async def test_suggested_unit_guard_valid_unit( ) setup_test_component_platform(hass, sensor.DOMAIN, [entity]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() # Unit of measurement should set to the suggested unit of measurement diff --git a/tests/components/sensor/test_recorder.py b/tests/components/sensor/test_recorder.py index 69cba6e0fbabd8..f66efde76e790b 100644 --- a/tests/components/sensor/test_recorder.py +++ b/tests/components/sensor/test_recorder.py @@ -313,7 +313,7 @@ async def test_compile_hourly_statistics( ) -> None: """Test compiling hourly statistics.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -371,7 +371,7 @@ async def test_compile_hourly_statistics_angle( ) -> None: """Test compiling hourly statistics for measurement_angle.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) with freeze_time(zero) as freezer: @@ -456,7 +456,7 @@ async def test_compile_hourly_statistics_with_some_same_last_updated( If the last updated value is the same we will have a zero duration. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) entity_id = "sensor.test1" @@ -547,7 +547,7 @@ async def test_compile_hourly_statistics_with_some_same_last_updated_angle( If the last updated value is the same we will have a zero duration. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) entity_id = "sensor.test1" @@ -705,7 +705,7 @@ async def test_compile_hourly_statistics_with_all_same_last_updated( If the last updated value is the same we will have a zero duration. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) entity_id = "sensor.test1" @@ -846,7 +846,7 @@ async def test_compile_hourly_statistics_only_state_is_at_end_of_period( ) -> None: """Test compiling hourly statistics when the only states are at end of period.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) entity_id = "sensor.test1" @@ -938,7 +938,7 @@ async def test_compile_hourly_statistics_purged_state_changes( This tests statistics falls back to the state machine when states are purged. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1036,7 +1036,7 @@ async def test_compile_hourly_statistics_ignore_future_state( """ zero = get_start_time(dt_util.utcnow() + timedelta(minutes=5)) previous_period = zero - timedelta(minutes=5) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1098,7 +1098,7 @@ async def test_compile_hourly_statistics_wrong_unit( ) -> None: """Test stats for sensor with unit not matching device class.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) with freeze_time(zero) as freezer: @@ -1335,7 +1335,7 @@ async def test_compile_hourly_sum_statistics_amount( period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1516,7 +1516,7 @@ async def test_compile_hourly_sum_statistics_amount_reset_every_state_change( ) -> None: """Test compiling hourly statistics.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1640,7 +1640,7 @@ async def test_compile_hourly_sum_statistics_amount_invalid_last_reset( ) -> None: """Test compiling hourly statistics.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1741,7 +1741,7 @@ async def test_compile_hourly_sum_statistics_nan_inf_state( ) -> None: """Test compiling hourly statistics with nan and inf states.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -1886,7 +1886,7 @@ async def test_compile_hourly_sum_statistics_negative_state( await async_setup_component(hass, "homeassistant", {}) with freeze_time(zero) as freezer: await async_setup_component( - hass, "sensor", {"sensor": [{"platform": "demo"}, {"platform": "test"}]} + hass, DOMAIN, {"sensor": [{"platform": "demo"}, {"platform": "test"}]} ) await hass.async_block_till_done() attributes = { @@ -1995,7 +1995,7 @@ async def test_compile_hourly_sum_statistics_total_no_reset( period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -2109,7 +2109,7 @@ async def test_compile_hourly_sum_statistics_total_increasing( period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -2223,7 +2223,7 @@ async def test_compile_hourly_sum_statistics_total_increasing_small_dip( period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -2327,7 +2327,7 @@ async def test_compile_hourly_energy_statistics_unsupported( period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) sns1_attr = { @@ -2432,7 +2432,7 @@ async def test_compile_hourly_energy_statistics_multiple( period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period2 = period0 + timedelta(minutes=10) period2_end = period0 + timedelta(minutes=15) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) sns1_attr = {**ENERGY_SENSOR_ATTRIBUTES, "last_reset": None} @@ -2649,7 +2649,7 @@ async def test_compile_hourly_statistics_unchanged( ) -> None: """Test compiling hourly statistics, with no changes during the hour.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -2693,7 +2693,7 @@ async def test_compile_hourly_statistics_unchanged_angle( ) -> None: """Test compiling hourly stats, no changes for measurement_angle.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) with freeze_time(zero) as freezer: @@ -2748,7 +2748,7 @@ async def test_compile_hourly_statistics_partially_unavailable( ) -> None: """Test compiling hourly statistics, with the sensor being partially unavailable.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) four, states = await async_record_states_partially_unavailable( @@ -2820,7 +2820,7 @@ async def test_compile_hourly_statistics_unavailable( sensor.test2 should have statistics generated """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -2872,7 +2872,7 @@ async def test_compile_hourly_statistics_unavailable_angle( sensor.test2 should have statistics generated """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) four, states = await async_record_states_partially_unavailable( @@ -2919,7 +2919,7 @@ async def test_compile_hourly_statistics_fails( ) -> None: """Test compiling hourly statistics throws.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) with patch( @@ -3232,7 +3232,7 @@ async def test_list_statistic_ids( statistic_type: str | StatisticMeanType, ) -> None: """Test listing future statistic ids.""" - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -3294,7 +3294,7 @@ async def test_list_statistic_ids_unsupported( energy_attributes: dict[str, Any], ) -> None: """Test listing future statistic ids for unsupported sensor.""" - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = dict(energy_attributes) @@ -3345,7 +3345,7 @@ async def test_compile_hourly_statistics_changing_units_1( This tests the case where the recorder cannot convert between the units. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -3476,7 +3476,7 @@ async def test_compile_hourly_statistics_changing_units_2( converter. """ zero = get_start_time(dt_util.utcnow()) - timedelta(seconds=30 * 5) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -3556,7 +3556,7 @@ async def test_compile_hourly_statistics_changing_units_3( converter. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -3712,7 +3712,7 @@ async def test_compile_hourly_statistics_convert_units_1( This tests the case where the recorder can convert between the units. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -3926,7 +3926,7 @@ async def test_compile_hourly_statistics_equivalent_units_1( ) -> None: """Test compiling hourly statistics where units change from one hour to the next.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -4074,7 +4074,7 @@ async def test_compile_hourly_statistics_equivalent_units_2( ) -> None: """Test compiling hourly statistics where units change during an hour.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -4159,7 +4159,7 @@ async def test_compile_hourly_statistics_custom_equivalent_units( ) -> None: """Test stats where units change with custom equivalent units.""" zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) @@ -4369,7 +4369,7 @@ async def test_compile_hourly_statistics_changing_device_class_1( Changing device class may influence the unit class. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) @@ -4587,7 +4587,7 @@ async def test_compile_hourly_statistics_changing_device_class_2( class, then set to None. """ zero = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) @@ -4725,7 +4725,7 @@ async def test_compile_hourly_statistics_changing_state_class( period0 = get_start_time(dt_util.utcnow()) period0_end = period1 = period0 + timedelta(minutes=5) period1_end = period0 + timedelta(minutes=10) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes_1 = { @@ -4862,7 +4862,7 @@ async def test_compile_statistics_hourly_daily_monthly_summary( zero = dt_util.utcnow() instance = get_instance(hass) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) # Wait for the sensor recorder platform to be added await async_recorder_block_till_done(hass) attributes = { @@ -5341,7 +5341,7 @@ async def test_validate_unit_change_convertible( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5477,7 +5477,7 @@ async def test_validate_statistics_unit_ignore_device_class( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5588,7 +5588,7 @@ async def test_validate_statistics_unit_change_no_device_class( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5722,7 +5722,7 @@ async def test_validate_statistics_state_class_removed( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5790,7 +5790,7 @@ async def test_validate_statistics_state_class_removed_issue_cleaned_up( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5849,7 +5849,7 @@ async def test_validate_statistics_sensor_no_longer_recorded( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5903,7 +5903,7 @@ async def test_validate_statistics_sensor_not_recorded( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -5954,7 +5954,7 @@ async def test_validate_statistics_sensor_removed( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -6003,7 +6003,7 @@ async def test_validate_statistics_unit_change_no_conversion( """Test validate_statistics.""" now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -6161,7 +6161,7 @@ async def test_validate_statistics_unit_change_equivalent_units( """ now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -6265,7 +6265,7 @@ async def test_validate_statistics_unit_change_equivalent_units_2( """ now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -6344,7 +6344,7 @@ async def test_validate_statistics_unit_change_custom_equivalent_units( """ now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) # Add a recorder platform that provides custom equivalent units @@ -6409,7 +6409,7 @@ async def test_validate_statistics_other_domain( hass: HomeAssistant, hass_ws_client: WebSocketGenerator ) -> None: """Test sensor does not raise issues for statistics for other domains.""" - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() @@ -6463,7 +6463,7 @@ async def test_update_statistics_issues( now = get_start_time(dt_util.utcnow()) hass.config.units = units - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) # No statistics, no state - no issues @@ -6514,7 +6514,7 @@ async def test_update_statistics_issues_with_custom_equivalent_units( """Test update_statistics_issues when custom equivalent units are provided.""" now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) # Add a recorder platform that provides custom equivalent units @@ -6701,7 +6701,7 @@ async def test_exclude_attributes(hass: HomeAssistant) -> None: options=["option1", "option2"], ) setup_test_component_platform(hass, DOMAIN, [entity0]) - assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"sensor": {"platform": "test"}}) await hass.async_block_till_done() await async_wait_recording_done(hass) @@ -6742,7 +6742,7 @@ async def test_clean_up_repairs( hass: HomeAssistant, hass_ws_client: WebSocketGenerator ) -> None: """Test cleaning up repairs.""" - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) issue_registry = ir.async_get(hass) client = await hass_ws_client() @@ -6799,7 +6799,7 @@ async def test_validate_statistics_mean_type_changed( """ now = get_start_time(dt_util.utcnow()) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) await async_recorder_block_till_done(hass) client = await hass_ws_client() diff --git a/tests/components/sensor/test_recorder_missing_stats.py b/tests/components/sensor/test_recorder_missing_stats.py index fd28a7052a52c1..90c9c10d99d38b 100644 --- a/tests/components/sensor/test_recorder_missing_stats.py +++ b/tests/components/sensor/test_recorder_missing_stats.py @@ -14,6 +14,7 @@ statistics_during_period, ) from homeassistant.components.recorder.util import session_scope +from homeassistant.components.sensor import DOMAIN from homeassistant.core import CoreState from homeassistant.helpers import recorder as recorder_helper from homeassistant.setup import async_setup_component @@ -58,7 +59,7 @@ async def test_compile_missing_statistics( async_test_recorder(hass, wait_recorder=False), ): recorder_helper.async_initialize_recorder(hass) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident()) await hass.async_start() await async_wait_recording_done(hass) @@ -102,7 +103,7 @@ async def test_compile_missing_statistics( async_test_recorder(hass, wait_recorder=False), ): recorder_helper.async_initialize_recorder(hass) - await async_setup_component(hass, "sensor", {}) + await async_setup_component(hass, DOMAIN, {}) hass.states.async_set("sensor.test1", "0", POWER_SENSOR_ATTRIBUTES) get_instance(hass).recorder_and_worker_thread_ids.add(threading.get_ident()) await hass.async_start() diff --git a/tests/components/spaceapi/test_init.py b/tests/components/spaceapi/test_init.py index 2151397832787b..51c9e3433b9aac 100644 --- a/tests/components/spaceapi/test_init.py +++ b/tests/components/spaceapi/test_init.py @@ -97,7 +97,7 @@ async def mock_client( hass: HomeAssistant, hass_client: ClientSessionGenerator ) -> TestClient: """Start the Home Assistant HTTP component.""" - await async_setup_component(hass, "spaceapi", CONFIG) + await async_setup_component(hass, DOMAIN, CONFIG) hass.states.async_set( "test.temp1", @@ -199,7 +199,7 @@ async def test_spaceapi_no_auth_required( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test SpaceAPI is accessible without authentication.""" - assert await async_setup_component(hass, "spaceapi", CONFIG) + assert await async_setup_component(hass, DOMAIN, CONFIG) hass.states.async_set("test.test_door", "on") @@ -215,7 +215,7 @@ async def test_spaceapi_cors_headers( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test CORS headers are present on SpaceAPI responses.""" - assert await async_setup_component(hass, "spaceapi", CONFIG) + assert await async_setup_component(hass, DOMAIN, CONFIG) hass.states.async_set("test.test_door", "on") diff --git a/tests/components/spc/test_alarm_control_panel.py b/tests/components/spc/test_alarm_control_panel.py index 12fb885b92b5e2..ca928b632c07d3 100644 --- a/tests/components/spc/test_alarm_control_panel.py +++ b/tests/components/spc/test_alarm_control_panel.py @@ -5,6 +5,7 @@ from pyspcwebgw.const import AreaMode from homeassistant.components.alarm_control_panel import AlarmControlPanelState +from homeassistant.components.spc import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -13,7 +14,7 @@ async def test_update_alarm_device(hass: HomeAssistant, mock_client: AsyncMock) """Test that alarm panel state changes on incoming websocket data.""" config = {"spc": {"api_url": "http://localhost/", "ws_url": "ws://localhost/"}} - assert await async_setup_component(hass, "spc", config) is True + assert await async_setup_component(hass, DOMAIN, config) is True await hass.async_block_till_done() diff --git a/tests/components/spc/test_init.py b/tests/components/spc/test_init.py index dc407dc2c5b16a..a2be6f51756140 100644 --- a/tests/components/spc/test_init.py +++ b/tests/components/spc/test_init.py @@ -2,6 +2,7 @@ from unittest.mock import AsyncMock +from homeassistant.components.spc import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -10,7 +11,7 @@ async def test_valid_device_config(hass: HomeAssistant, mock_client: AsyncMock) """Test valid device config.""" config = {"spc": {"api_url": "http://localhost/", "ws_url": "ws://localhost/"}} - assert await async_setup_component(hass, "spc", config) is True + assert await async_setup_component(hass, DOMAIN, config) is True async def test_invalid_device_config( @@ -19,4 +20,4 @@ async def test_invalid_device_config( """Test valid device config.""" config = {"spc": {"api_url": "http://localhost/"}} - assert await async_setup_component(hass, "spc", config) is False + assert await async_setup_component(hass, DOMAIN, config) is False diff --git a/tests/components/stream/test_hls.py b/tests/components/stream/test_hls.py index 4cb11090af2837..96476fb514b61e 100644 --- a/tests/components/stream/test_hls.py +++ b/tests/components/stream/test_hls.py @@ -10,6 +10,7 @@ from homeassistant.components.stream import Stream, create_stream from homeassistant.components.stream.const import ( + DOMAIN, EXT_X_START_LL_HLS, EXT_X_START_NON_LL_HLS, HLS_PROVIDER, @@ -48,7 +49,7 @@ @pytest.fixture async def setup_component(hass: HomeAssistant) -> None: """Test fixture to setup the stream component.""" - await async_setup_component(hass, "stream", HLS_CONFIG) + await async_setup_component(hass, DOMAIN, HLS_CONFIG) class HlsClient: diff --git a/tests/components/stream/test_init.py b/tests/components/stream/test_init.py index ba5f8d2e70f255..28552c87ffad86 100644 --- a/tests/components/stream/test_init.py +++ b/tests/components/stream/test_init.py @@ -15,7 +15,7 @@ async_check_stream_client_error, create_stream, ) -from homeassistant.components.stream.const import ATTR_PREFER_TCP +from homeassistant.components.stream.const import ATTR_PREFER_TCP, DOMAIN from homeassistant.const import EVENT_LOGGING_CHANGED from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError @@ -42,7 +42,7 @@ async def test_log_levels( ) -> None: """Test that the worker logs the url without username and password.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) # These namespaces should only pass log messages when the stream logger # is at logging.DEBUG or below @@ -83,7 +83,7 @@ async def test_log_levels( async def test_check_open_stream_params(hass: HomeAssistant) -> None: """Test check open stream params.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) container_mock = MagicMock() source = "rtsp://foobar" @@ -134,7 +134,7 @@ async def test_try_open_stream_error( hass: HomeAssistant, error: av.HTTPClientError, enum_result: StreamClientError ) -> None: """Test trying to open a stream.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) with ( patch("av.open", side_effect=error), @@ -175,7 +175,7 @@ async def test_convert_stream_options( expected_pyav_options: dict[str, Any], ) -> None: """Test stream options.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) container_mock = MagicMock() source = "rtsp://foobar" diff --git a/tests/components/stream/test_ll_hls.py b/tests/components/stream/test_ll_hls.py index 636bd5f8262a01..4844f73a65e2be 100644 --- a/tests/components/stream/test_ll_hls.py +++ b/tests/components/stream/test_ll_hls.py @@ -128,7 +128,7 @@ async def test_ll_hls_stream( """ await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -261,7 +261,7 @@ async def test_ll_hls_playlist_view( """Test rendering the hls playlist with 1 and 2 output segments.""" await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -332,7 +332,7 @@ async def test_ll_hls_msn( """Test that requests using _HLS_msn get held and returned or rejected.""" await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -402,7 +402,7 @@ async def _handler_bad_request(request): await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -480,7 +480,7 @@ async def test_ll_hls_playlist_rollover_part( await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -561,7 +561,7 @@ async def test_ll_hls_playlist_msn_part( await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -629,7 +629,7 @@ async def test_get_part_segments( """Test requests for part segments and hinted parts.""" await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, diff --git a/tests/components/stream/test_recorder.py b/tests/components/stream/test_recorder.py index 7c856180f7719b..dc3373de2e5c9b 100644 --- a/tests/components/stream/test_recorder.py +++ b/tests/components/stream/test_recorder.py @@ -12,6 +12,7 @@ from homeassistant.components.stream import Stream, create_stream from homeassistant.components.stream.const import ( + DOMAIN, HLS_PROVIDER, OUTPUT_IDLE_TIMEOUT, RECORDER_PROVIDER, @@ -37,7 +38,7 @@ @pytest.fixture(autouse=True) async def stream_component(hass: HomeAssistant) -> None: """Set up the component before each test.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) @pytest.fixture diff --git a/tests/components/stream/test_worker.py b/tests/components/stream/test_worker.py index 87c24bfe30391d..a37a39579701d0 100644 --- a/tests/components/stream/test_worker.py +++ b/tests/components/stream/test_worker.py @@ -837,7 +837,7 @@ async def test_durations(hass: HomeAssistant, worker_finished_stream) -> None: target_part_duration = TEST_PART_DURATION - 0.01 await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -917,7 +917,7 @@ async def test_has_keyframe( """Test that the has_keyframe metadata matches the media.""" await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -962,7 +962,7 @@ async def test_h265_video_is_hvc1(hass: HomeAssistant, worker_finished_stream) - """Test that a h265 video gets muxed as hvc1.""" await async_setup_component( hass, - "stream", + DOMAIN, { "stream": { CONF_LL_HLS: True, @@ -1007,7 +1007,7 @@ async def test_h265_video_is_hvc1(hass: HomeAssistant, worker_finished_stream) - async def test_get_image(hass: HomeAssistant, h264_video, filename) -> None: """Test getting an image from the stream.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) # Since libjpeg-turbo is not installed on the CI runner, we use a mock with patch( @@ -1070,7 +1070,7 @@ async def test_worker_disable_ll_hls(hass: HomeAssistant) -> None: async def test_get_image_rotated(hass: HomeAssistant, h264_video, filename) -> None: """Test getting a rotated image.""" - await async_setup_component(hass, "stream", {"stream": {}}) + await async_setup_component(hass, DOMAIN, {"stream": {}}) # Since libjpeg-turbo is not installed on the CI runner, we use a mock with patch( diff --git a/tests/components/stt/test_init.py b/tests/components/stt/test_init.py index 23e0dab42c5429..68c27847cf9d05 100644 --- a/tests/components/stt/test_init.py +++ b/tests/components/stt/test_init.py @@ -113,7 +113,7 @@ async def mock_setup( TEST_DOMAIN, async_get_engine=AsyncMock(return_value=mock_provider), ) - assert await async_setup_component(hass, "stt", {"stt": {"platform": TEST_DOMAIN}}) + assert await async_setup_component(hass, DOMAIN, {"stt": {"platform": TEST_DOMAIN}}) await hass.async_block_till_done() @@ -460,7 +460,7 @@ async def test_ws_list_engines( async def test_default_engine_none(hass: HomeAssistant, tmp_path: Path) -> None: """Test async_default_engine.""" - assert await async_setup_component(hass, "stt", {"stt": {}}) + assert await async_setup_component(hass, DOMAIN, {"stt": {}}) await hass.async_block_till_done() assert async_default_engine(hass) is None @@ -478,7 +478,7 @@ async def test_default_engine( TEST_DOMAIN, async_get_engine=AsyncMock(return_value=mock_provider), ) - assert await async_setup_component(hass, "stt", {"stt": {"platform": TEST_DOMAIN}}) + assert await async_setup_component(hass, DOMAIN, {"stt": {"platform": TEST_DOMAIN}}) await hass.async_block_till_done() assert async_default_engine(hass) == TEST_DOMAIN @@ -583,7 +583,7 @@ async def test_get_engine_legacy( async_get_engine=AsyncMock(return_value=mock_provider), ) assert await async_setup_component( - hass, "stt", {"stt": [{"platform": TEST_DOMAIN}, {"platform": "cloud"}]} + hass, DOMAIN, {"stt": [{"platform": TEST_DOMAIN}, {"platform": "cloud"}]} ) await hass.async_block_till_done() diff --git a/tests/components/switch/test_init.py b/tests/components/switch/test_init.py index f52c455dabdd6a..fa501015af3783 100644 --- a/tests/components/switch/test_init.py +++ b/tests/components/switch/test_init.py @@ -4,6 +4,7 @@ from homeassistant import core from homeassistant.components import switch +from homeassistant.components.switch import DOMAIN from homeassistant.const import CONF_PLATFORM from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -63,7 +64,7 @@ async def test_switch_context( hass_admin_user: MockUser, ) -> None: """Test that switch context works.""" - assert await async_setup_component(hass, "switch", {"switch": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"switch": {"platform": "test"}}) await hass.async_block_till_done() diff --git a/tests/components/switch/test_light.py b/tests/components/switch/test_light.py index 4387151ce34bd9..14b8055e3ef987 100644 --- a/tests/components/switch/test_light.py +++ b/tests/components/switch/test_light.py @@ -7,6 +7,7 @@ ATTR_SUPPORTED_COLOR_MODES, ColorMode, ) +from homeassistant.components.switch import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -51,7 +52,7 @@ async def test_default_state(hass: HomeAssistant) -> None: async def test_light_service_calls(hass: HomeAssistant) -> None: """Test service calls to light.""" - await async_setup_component(hass, "switch", {"switch": [{"platform": "demo"}]}) + await async_setup_component(hass, DOMAIN, {"switch": [{"platform": "demo"}]}) await async_setup_component( hass, "light", @@ -86,7 +87,7 @@ async def test_light_service_calls(hass: HomeAssistant) -> None: async def test_switch_service_calls(hass: HomeAssistant) -> None: """Test service calls to switch.""" - await async_setup_component(hass, "switch", {"switch": [{"platform": "demo"}]}) + await async_setup_component(hass, DOMAIN, {"switch": [{"platform": "demo"}]}) await async_setup_component( hass, "light", diff --git a/tests/components/system_health/test_init.py b/tests/components/system_health/test_init.py index e37078db9eb937..a0b1ba382fcd17 100644 --- a/tests/components/system_health/test_init.py +++ b/tests/components/system_health/test_init.py @@ -6,7 +6,7 @@ from aiohttp.client_exceptions import ClientError from homeassistant.components import system_health -from homeassistant.components.system_health import async_register_info +from homeassistant.components.system_health import DOMAIN, async_register_info from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -61,7 +61,7 @@ async def test_info_endpoint_return_info( "homeassistant.components.homeassistant.system_health.system_health_info", return_value={"hello": True}, ): - assert await async_setup_component(hass, "system_health", {}) + assert await async_setup_component(hass, DOMAIN, {}) data = await gather_system_health_info(hass, hass_ws_client) @@ -79,7 +79,7 @@ async def mock_info(hass: HomeAssistant) -> dict[str, Any]: return {"storage": "YAML"} async_register_info(hass, "lovelace", mock_info) - assert await async_setup_component(hass, "system_health", {}) + assert await async_setup_component(hass, DOMAIN, {}) data = await gather_system_health_info(hass, hass_ws_client) assert len(data) == 1 @@ -99,7 +99,7 @@ async def mock_info(hass: HomeAssistant) -> dict[str, Any]: raise TimeoutError async_register_info(hass, "lovelace", mock_info) - assert await async_setup_component(hass, "system_health", {}) + assert await async_setup_component(hass, DOMAIN, {}) data = await gather_system_health_info(hass, hass_ws_client) assert len(data) == 1 @@ -116,7 +116,7 @@ async def mock_info(hass: HomeAssistant) -> dict[str, Any]: raise Exception("TEST ERROR") # noqa: TRY002 async_register_info(hass, "lovelace", mock_info) - assert await async_setup_component(hass, "system_health", {}) + assert await async_setup_component(hass, DOMAIN, {}) data = await gather_system_health_info(hass, hass_ws_client) assert len(data) == 1 @@ -165,7 +165,7 @@ async def test_platform_loading( ), ) - assert await async_setup_component(hass, "system_health", {}) + assert await async_setup_component(hass, DOMAIN, {}) data = await gather_system_health_info(hass, hass_ws_client) assert data["fake_integration"] == { diff --git a/tests/components/template/test_blueprint.py b/tests/components/template/test_blueprint.py index 0a653dfd257142..063dd20db0aef2 100644 --- a/tests/components/template/test_blueprint.py +++ b/tests/components/template/test_blueprint.py @@ -109,7 +109,7 @@ async def test_inverted_binary_sensor( ): assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -324,7 +324,7 @@ async def test_trigger_event_sensor( """Test event sensor blueprint.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -403,7 +403,7 @@ async def test_blueprint_template_override( """Test blueprint template where the template config overrides the blueprint.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -503,7 +503,7 @@ async def test_invalid_blueprint( with patch_invalid_blueprint(): assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -529,7 +529,7 @@ async def test_no_blueprint(hass: HomeAssistant) -> None: ): assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ {"binary_sensor": {"name": "test entity", "state": "off"}}, @@ -589,7 +589,7 @@ async def test_variables_for_entity( assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { diff --git a/tests/components/template/test_config.py b/tests/components/template/test_config.py index a38780d3bf01e7..a9633ea5128e9f 100644 --- a/tests/components/template/test_config.py +++ b/tests/components/template/test_config.py @@ -276,7 +276,7 @@ async def test_invalid_binary_sensor_schema_with_auto_off( ) -> None: """Test invalid config schemas create issue and log warning.""" - await async_setup_component(hass, "template", {"template": [config]}) + await async_setup_component(hass, DOMAIN, {"template": [config]}) assert ( expected_error is None and "ERROR" not in caplog.text @@ -536,7 +536,7 @@ async def test_invalid_schema_raises_issue( ) -> None: """Test invalid config schemas create issue and log warning.""" - await async_setup_component(hass, "template", {"template": [config]}) + await async_setup_component(hass, DOMAIN, {"template": [config]}) assert expected_warning in caplog.text @@ -553,7 +553,7 @@ async def test_multiple_configuration_keys( """Test multiple configurations keys create entities.""" await async_setup_component( hass, - "template", + DOMAIN, { "template": [{"binary_sensor": [{"name": "Foo", "state": "{{ True }}"}]}], "template mytemplates": [ diff --git a/tests/components/template/test_entity.py b/tests/components/template/test_entity.py index f2fd2d12c6baf8..6c0d0d6db3fd95 100644 --- a/tests/components/template/test_entity.py +++ b/tests/components/template/test_entity.py @@ -55,7 +55,7 @@ async def test_reload_stops_entity_action_scripts( hass: HomeAssistant, config: dict ) -> None: """Test that reloading stops template entity action scripts.""" - assert await async_setup_component(hass, "template", config) + assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() diff --git a/tests/components/template/test_image.py b/tests/components/template/test_image.py index 101b475956a203..7f18e53d3bbd8e 100644 --- a/tests/components/template/test_image.py +++ b/tests/components/template/test_image.py @@ -151,7 +151,7 @@ async def test_missing_optional_config( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": { @@ -193,7 +193,7 @@ async def test_multiple_configs( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": [ @@ -229,7 +229,7 @@ async def test_missing_required_keys(hass: HomeAssistant) -> None: with assert_setup_component(0, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": { @@ -253,7 +253,7 @@ async def test_unique_id( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "unique_id": "b", @@ -287,7 +287,7 @@ async def test_custom_entity_picture( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": { @@ -322,7 +322,7 @@ async def test_template_error( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": { @@ -379,7 +379,7 @@ async def test_templates_with_entities( with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "image": { @@ -435,7 +435,7 @@ async def test_trigger_image( assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -497,7 +497,7 @@ async def test_trigger_image_custom_entity_picture( assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": [ { diff --git a/tests/components/template/test_select.py b/tests/components/template/test_select.py index e6a55ac47f7a6e..028d77818c2f41 100644 --- a/tests/components/template/test_select.py +++ b/tests/components/template/test_select.py @@ -123,7 +123,7 @@ async def test_multiple_configs(hass: HomeAssistant) -> None: with assert_setup_component(1, "template"): assert await setup.async_setup_component( hass, - "template", + DOMAIN, { "template": { "select": [ diff --git a/tests/components/template/test_sensor.py b/tests/components/template/test_sensor.py index a0d5708154c568..128e0e46e793db 100644 --- a/tests/components/template/test_sensor.py +++ b/tests/components/template/test_sensor.py @@ -9,6 +9,7 @@ from homeassistant.bootstrap import async_from_config_dict from homeassistant.components import sensor, template +from homeassistant.components.template import DOMAIN from homeassistant.const import ( ATTR_ENTITY_PICTURE, ATTR_FRIENDLY_NAME, @@ -1226,7 +1227,7 @@ async def test_numeric_trigger_entity_set_unknown( """Test trigger entity state parsing with numeric sensors.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -1264,7 +1265,7 @@ async def test_trigger_attribute_order( """Test trigger entity attributes order.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { @@ -1347,7 +1348,7 @@ async def test_entity_last_reset_total_increasing( with patch("homeassistant.util.dt.now", return_value=now): assert await async_setup_component( hass, - "template", + DOMAIN, { "template": [ { diff --git a/tests/components/template/test_trigger_entity.py b/tests/components/template/test_trigger_entity.py index d3a42b3ccd1909..30a9dc9a8d158e 100644 --- a/tests/components/template/test_trigger_entity.py +++ b/tests/components/template/test_trigger_entity.py @@ -267,7 +267,7 @@ async def test_shutdown_stops_script_and_keeps_triggers_subscribed( """Test HA shutdown stops coordinator scripts without unsubscribing.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": { "trigger": {"platform": "event", "event_type": "test_event"}, @@ -320,7 +320,7 @@ async def test_reload_stops_script_and_unsubscribes_triggers( """Test that reloading stops coordinator scripts and unsubscribes old triggers.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": { "trigger": {"platform": "event", "event_type": "test_event"}, diff --git a/tests/components/template/test_weather.py b/tests/components/template/test_weather.py index 2f972c1c312615..236f573cf99ec7 100644 --- a/tests/components/template/test_weather.py +++ b/tests/components/template/test_weather.py @@ -6,7 +6,7 @@ from syrupy.assertion import SnapshotAssertion from homeassistant.components import template -from homeassistant.components.template.const import CONF_PICTURE +from homeassistant.components.template.const import CONF_PICTURE, DOMAIN from homeassistant.components.weather import ( ATTR_WEATHER_APPARENT_TEMPERATURE, ATTR_WEATHER_CLOUD_COVERAGE, @@ -803,7 +803,7 @@ async def test_restore_weather_save_state( """Test Restore saved state for Weather trigger template.""" assert await async_setup_component( hass, - "template", + DOMAIN, { "template": { "trigger": {"platform": "event", "event_type": "test_event"}, @@ -898,7 +898,7 @@ async def test_trigger_entity_restore_state_fail( mock_restore_cache_with_extra_data(hass, ((saved_state, saved_extra_data),)) assert await async_setup_component( hass, - "template", + DOMAIN, { "template": { "trigger": {"platform": "event", "event_type": "test_event"}, diff --git a/tests/components/text/test_init.py b/tests/components/text/test_init.py index 3764d4819289e1..1dda5c3fb77155 100644 --- a/tests/components/text/test_init.py +++ b/tests/components/text/test_init.py @@ -119,7 +119,7 @@ async def test_restore_number_save_state( ) setup_test_component_platform(hass, DOMAIN, [entity0]) - assert await async_setup_component(hass, "text", {"text": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"text": {"platform": "test"}}) await hass.async_block_till_done() # Trigger saving state @@ -163,7 +163,7 @@ async def test_restore_number_restore_state( ) setup_test_component_platform(hass, DOMAIN, [entity0]) - assert await async_setup_component(hass, "text", {"text": {"platform": "test"}}) + assert await async_setup_component(hass, DOMAIN, {"text": {"platform": "test"}}) await hass.async_block_till_done() assert hass.states.get(entity0.entity_id) diff --git a/tests/components/timer/test_init.py b/tests/components/timer/test_init.py index f45fc698132b18..c04b16def89670 100644 --- a/tests/components/timer/test_init.py +++ b/tests/components/timer/test_init.py @@ -118,7 +118,7 @@ async def test_config_options(hass: HomeAssistant) -> None: } } - assert await async_setup_component(hass, "timer", config) + assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() assert count_start + 3 == len(hass.states.async_entity_ids()) @@ -682,7 +682,7 @@ async def test_config_reload( } } - assert await async_setup_component(hass, "timer", config) + assert await async_setup_component(hass, DOMAIN, config) await hass.async_block_till_done() assert count_start + 2 == len(hass.states.async_entity_ids()) diff --git a/tests/components/tts/test_init.py b/tests/components/tts/test_init.py index 4d1f6803bb6b8e..17e341b886b1d0 100644 --- a/tests/components/tts/test_init.py +++ b/tests/components/tts/test_init.py @@ -21,6 +21,7 @@ SERVICE_PLAY_MEDIA, MediaType, ) +from homeassistant.components.tts import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN from homeassistant.core import HomeAssistant @@ -1701,7 +1702,7 @@ async def test_ws_list_engines_deprecated( mock_integration(hass, MockModule(domain="test_2")) mock_platform(hass, "test_2.tts", MockTTS(mock_provider_2)) await async_setup_component( - hass, "tts", {"tts": [{"platform": "test"}, {"platform": "test_2"}]} + hass, DOMAIN, {"tts": [{"platform": "test"}, {"platform": "test_2"}]} ) await mock_config_entry_setup(hass, mock_tts_entity) diff --git a/tests/components/usage_prediction/test_init.py b/tests/components/usage_prediction/test_init.py index 44c1ba32b55f56..3aa341540c6417 100644 --- a/tests/components/usage_prediction/test_init.py +++ b/tests/components/usage_prediction/test_init.py @@ -5,7 +5,7 @@ import pytest -from homeassistant.components.usage_prediction import get_cached_common_control +from homeassistant.components.usage_prediction import DOMAIN, get_cached_common_control from homeassistant.components.usage_prediction.models import EntityUsagePredictions from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -15,7 +15,7 @@ async def test_usage_prediction_caching(hass: HomeAssistant) -> None: """Test that usage prediction results are cached for 24 hours.""" - assert await async_setup_component(hass, "usage_prediction", {}) + assert await async_setup_component(hass, DOMAIN, {}) finish_event = asyncio.Event() diff --git a/tests/components/usage_prediction/test_websocket.py b/tests/components/usage_prediction/test_websocket.py index d20999ed67b09b..198c50553a9f89 100644 --- a/tests/components/usage_prediction/test_websocket.py +++ b/tests/components/usage_prediction/test_websocket.py @@ -8,6 +8,7 @@ from freezegun import freeze_time import pytest +from homeassistant.components.usage_prediction import DOMAIN from homeassistant.components.usage_prediction.models import EntityUsagePredictions from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component @@ -42,7 +43,7 @@ async def test_common_control( mock_predict_common_control: Mock, ) -> None: """Test usage_prediction common control WebSocket command.""" - assert await async_setup_component(hass, "usage_prediction", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass) @@ -69,7 +70,7 @@ async def test_caching_behavior( mock_predict_common_control: Mock, ) -> None: """Test that results are cached for 24 hours.""" - assert await async_setup_component(hass, "usage_prediction", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass) diff --git a/tests/components/voip/test_voip.py b/tests/components/voip/test_voip.py index 07b8b5769011d3..ec6facbe16f689 100644 --- a/tests/components/voip/test_voip.py +++ b/tests/components/voip/test_voip.py @@ -16,7 +16,7 @@ # pylint: disable-next=home-assistant-component-root-import from homeassistant.components.assist_satellite.entity import AssistSatelliteState -from homeassistant.components.voip import HassVoipDatagramProtocol +from homeassistant.components.voip import DOMAIN, HassVoipDatagramProtocol from homeassistant.components.voip.assist_satellite import Tones, VoipAssistSatellite from homeassistant.components.voip.devices import VoIPDevice, VoIPDevices from homeassistant.components.voip.voip import PreRecordMessageProtocol, make_protocol @@ -76,7 +76,7 @@ async def test_is_valid_call( call_info: CallInfo, ) -> None: """Test that a call is now allowed from an unknown device.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) protocol = HassVoipDatagramProtocol(hass, voip_devices) assert not protocol.is_valid_call(call_info) @@ -102,7 +102,7 @@ async def test_calls_not_allowed( snapshot: SnapshotAssertion, ) -> None: """Test that a pre-recorded message is played when calls aren't allowed.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) protocol: PreRecordMessageProtocol = make_protocol(hass, voip_devices, call_info) assert isinstance(protocol, PreRecordMessageProtocol) assert protocol.file_name == "problem.pcm" @@ -139,7 +139,7 @@ async def test_pipeline_not_found( snapshot: SnapshotAssertion, ) -> None: """Test that a pre-recorded message is played when a pipeline isn't found.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) with patch( "homeassistant.components.voip.voip.async_get_pipeline", return_value=None @@ -160,7 +160,7 @@ async def test_satellite_prepared( snapshot: SnapshotAssertion, ) -> None: """Test that satellite is prepared for a call.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) pipeline = assist_pipeline.Pipeline( conversation_engine="test", @@ -196,7 +196,7 @@ async def test_pipeline( call_info: CallInfo, ) -> None: """Test that pipeline function is called from RTP protocol.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -371,7 +371,7 @@ async def test_stt_stream_timeout( hass: HomeAssistant, voip_devices: VoIPDevices, voip_device: VoIPDevice ) -> None: """Test timeout in STT stream during pipeline run.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -410,7 +410,7 @@ async def test_tts_timeout( voip_device: VoIPDevice, ) -> None: """Test that TTS will time out based on its length.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -509,7 +509,7 @@ async def test_tts_wrong_extension( voip_device: VoIPDevice, ) -> None: """Test that TTS will only stream WAV audio.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) satellite.addr = ("192.168.1.1", 12345) @@ -602,7 +602,7 @@ async def test_tts_wrong_wav_format( voip_device: VoIPDevice, ) -> None: """Test that TTS will only stream WAV audio with a specific format.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) satellite.addr = ("192.168.1.1", 12345) @@ -695,7 +695,7 @@ async def test_empty_tts_output( voip_device: VoIPDevice, ) -> None: """Test that TTS will not stream when output is empty.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) satellite.addr = ("192.168.1.1", 12345) @@ -781,7 +781,7 @@ async def test_pipeline_error( snapshot: SnapshotAssertion, ) -> None: """Test that a pipeline error causes the error tone to be played.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -834,7 +834,7 @@ async def test_announce( voip_device: VoIPDevice, ) -> None: """Test announcement.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -903,7 +903,7 @@ async def test_voip_id_is_ip_address( voip_device: VoIPDevice, ) -> None: """Test announcement when VoIP is an IP address instead of a SIP header.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -964,7 +964,7 @@ async def test_announce_timeout( voip_device: VoIPDevice, ) -> None: """Test announcement when user does not pick up the phone in time.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -1007,7 +1007,7 @@ async def test_start_conversation( voip_device: VoIPDevice, ) -> None: """Test start conversation.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) assert isinstance(satellite, VoipAssistSatellite) @@ -1116,7 +1116,7 @@ async def test_start_conversation_user_doesnt_pick_up( voip_device: VoIPDevice, ) -> None: """Test start conversation when the user doesn't pick up.""" - assert await async_setup_component(hass, "voip", {}) + assert await async_setup_component(hass, DOMAIN, {}) satellite = async_get_satellite_entity(hass, voip.DOMAIN, voip_device.voip_id) satellite.addr = ("192.168.1.1", 12345) diff --git a/tests/components/weather/test_intent.py b/tests/components/weather/test_intent.py index 161ee95cebda74..7367bd92881e46 100644 --- a/tests/components/weather/test_intent.py +++ b/tests/components/weather/test_intent.py @@ -17,7 +17,7 @@ async def test_get_weather(hass: HomeAssistant) -> None: """Test get weather for first entity and by name.""" assert await async_setup_component(hass, "homeassistant", {}) - assert await async_setup_component(hass, "weather", {"weather": {}}) + assert await async_setup_component(hass, DOMAIN, {"weather": {}}) entity1 = WeatherEntity() entity1._attr_name = "Weather 1" @@ -73,7 +73,7 @@ async def test_get_weather(hass: HomeAssistant) -> None: async def test_get_weather_wrong_name(hass: HomeAssistant) -> None: """Test get weather with the wrong name.""" assert await async_setup_component(hass, "homeassistant", {}) - assert await async_setup_component(hass, "weather", {"weather": {}}) + assert await async_setup_component(hass, DOMAIN, {"weather": {}}) entity1 = WeatherEntity() entity1._attr_name = "Weather 1" @@ -109,7 +109,7 @@ async def test_get_weather_wrong_name(hass: HomeAssistant) -> None: async def test_get_weather_no_entities(hass: HomeAssistant) -> None: """Test get weather with no weather entities.""" assert await async_setup_component(hass, "homeassistant", {}) - assert await async_setup_component(hass, "weather", {"weather": {}}) + assert await async_setup_component(hass, DOMAIN, {"weather": {}}) await weather_intent.async_setup_intents(hass) # No weather entities diff --git a/tests/components/web_rtc/test_init.py b/tests/components/web_rtc/test_init.py index 01f459778546ae..1a10fe9f96621d 100644 --- a/tests/components/web_rtc/test_init.py +++ b/tests/components/web_rtc/test_init.py @@ -3,6 +3,7 @@ from webrtc_models import RTCIceServer from homeassistant.components.web_rtc import ( + DOMAIN, async_get_ice_servers, async_register_ice_servers, ) @@ -15,7 +16,7 @@ async def test_async_setup(hass: HomeAssistant) -> None: """Test setting up the web_rtc integration.""" - assert await async_setup_component(hass, "web_rtc", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() # Verify default ICE servers are registered @@ -34,7 +35,7 @@ async def test_async_setup_custom_ice_servers_core(hass: HomeAssistant) -> None: {"webrtc": {"ice_servers": [{"url": "stun:custom_stun_server:3478"}]}}, ) - assert await async_setup_component(hass, "web_rtc", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() ice_servers = async_get_ice_servers(hass) @@ -46,7 +47,7 @@ async def test_async_setup_custom_ice_servers_integration(hass: HomeAssistant) - """Test setting up web_rtc with custom ICE servers in config.""" assert await async_setup_component( hass, - "web_rtc", + DOMAIN, { "web_rtc": { "ice_servers": [ @@ -102,7 +103,7 @@ async def test_async_setup_custom_ice_servers_core_and_integration( assert await async_setup_component( hass, - "web_rtc", + DOMAIN, { "web_rtc": { "ice_servers": [{"url": "stun:custom_stun_server_integration:3478"}] @@ -124,7 +125,7 @@ async def test_async_setup_custom_ice_servers_core_and_integration( async def test_async_register_ice_servers(hass: HomeAssistant) -> None: """Test registering ICE servers.""" - assert await async_setup_component(hass, "web_rtc", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() default_servers = async_get_ice_servers(hass) @@ -159,7 +160,7 @@ def get_ice_servers() -> list[RTCIceServer]: async def test_multiple_ice_server_registrations(hass: HomeAssistant) -> None: """Test registering multiple ICE server providers.""" - assert await async_setup_component(hass, "web_rtc", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() default_servers = async_get_ice_servers(hass) @@ -213,7 +214,7 @@ async def test_ws_ice_servers_with_registered_servers( hass: HomeAssistant, hass_ws_client: WebSocketGenerator ) -> None: """Test WebSocket ICE servers endpoint with registered servers.""" - assert await async_setup_component(hass, "web_rtc", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() @callback diff --git a/tests/components/webhook/test_init.py b/tests/components/webhook/test_init.py index 09dd0d6e03e76d..041ca12c9e3c81 100644 --- a/tests/components/webhook/test_init.py +++ b/tests/components/webhook/test_init.py @@ -9,6 +9,7 @@ import pytest from homeassistant.components import webhook +from homeassistant.components.webhook import DOMAIN from homeassistant.components.websocket_api import auth, http from homeassistant.core import HomeAssistant from homeassistant.core_config import async_process_ha_core_config @@ -24,7 +25,7 @@ async def mock_client( hass: HomeAssistant, hass_client: ClientSessionGenerator ) -> TestClient: """Create http client for webhooks.""" - await async_setup_component(hass, "webhook", {}) + await async_setup_component(hass, DOMAIN, {}) return await hass_client() @@ -283,7 +284,7 @@ async def test_webhook_local_only_mock_request( hass: HomeAssistant, remote: str | None, expected_calls: int ) -> None: """Test local_only webhooks for MockRequests with various remote values.""" - await async_setup_component(hass, "webhook", {}) + await async_setup_component(hass, DOMAIN, {}) hooks = [] webhook_id = webhook.async_generate_id() @@ -316,7 +317,7 @@ async def test_listing_webhook( hass_access_token: str, ) -> None: """Test unregistering a webhook.""" - assert await async_setup_component(hass, "webhook", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass, hass_access_token) webhook.async_register(hass, "test", "Test hook", "my-id", None) @@ -360,7 +361,7 @@ async def test_listing_webhook_requires_admin( hass_read_only_access_token: str, ) -> None: """Test listing webhooks requires an admin user.""" - assert await async_setup_component(hass, "webhook", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass, hass_read_only_access_token) await client.send_json({"id": 5, "type": "webhook/list"}) @@ -377,7 +378,7 @@ async def test_ws_webhook( hass_ws_client: WebSocketGenerator, ) -> None: """Test sending webhook msg via WS API.""" - assert await async_setup_component(hass, "webhook", {}) + assert await async_setup_component(hass, DOMAIN, {}) received = [] @@ -462,7 +463,7 @@ async def test_ws_webhook_local_only( expected_calls: int, ) -> None: """Test a local_only webhook over the websocket connection.""" - assert await async_setup_component(hass, "webhook", {}) + assert await async_setup_component(hass, DOMAIN, {}) assert await async_setup_component(hass, "websocket_api", {}) await hass.async_block_till_done() diff --git a/tests/components/webhook/test_trigger.py b/tests/components/webhook/test_trigger.py index ce372fbebbba1a..eedf342de34948 100644 --- a/tests/components/webhook/test_trigger.py +++ b/tests/components/webhook/test_trigger.py @@ -5,6 +5,7 @@ import pytest +from homeassistant.components.webhook import DOMAIN from homeassistant.core import HomeAssistant, callback from homeassistant.setup import async_setup_component @@ -16,7 +17,7 @@ async def setup_http(hass: HomeAssistant) -> None: """Set up http.""" assert await async_setup_component(hass, "http", {}) - assert await async_setup_component(hass, "webhook", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() diff --git a/tests/components/websocket_api/conftest.py b/tests/components/websocket_api/conftest.py index 3ec3e85a92d8b5..84469a071605d1 100644 --- a/tests/components/websocket_api/conftest.py +++ b/tests/components/websocket_api/conftest.py @@ -3,6 +3,7 @@ from aiohttp.test_utils import TestClient import pytest +from homeassistant.components.websocket_api import DOMAIN from homeassistant.components.websocket_api.auth import TYPE_AUTH_REQUIRED from homeassistant.components.websocket_api.http import URL from homeassistant.core import HomeAssistant @@ -28,7 +29,7 @@ async def no_auth_websocket_client( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> TestClient: """Websocket connection that requires authentication.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() diff --git a/tests/components/websocket_api/test_auth.py b/tests/components/websocket_api/test_auth.py index b86bf63fc102e8..1e9cd3b0fb8005 100644 --- a/tests/components/websocket_api/test_auth.py +++ b/tests/components/websocket_api/test_auth.py @@ -7,6 +7,7 @@ import pytest from homeassistant.auth.providers.homeassistant import HassAuthProvider +from homeassistant.components.websocket_api import DOMAIN from homeassistant.components.websocket_api.auth import ( TYPE_AUTH, TYPE_AUTH_INVALID, @@ -137,7 +138,7 @@ async def test_auth_active_user_inactive( """Test authenticating with a token.""" refresh_token = hass.auth.async_validate_access_token(hass_access_token) refresh_token.user.is_active = False - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -161,7 +162,7 @@ async def test_auth_local_only_user_rejected_remote( refresh_token = hass.auth.async_validate_access_token(hass_access_token) refresh_token.user.local_only = True - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() set_mock_ip = mock_real_ip(hass.http.app) @@ -194,7 +195,7 @@ async def test_auth_local_only_user_allowed_local( refresh_token = hass.auth.async_validate_access_token(hass_access_token) refresh_token.user.local_only = True - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() set_mock_ip = mock_real_ip(hass.http.app) @@ -216,7 +217,7 @@ async def test_auth_active_with_password_not_allow( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test authenticating with a token.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -237,7 +238,7 @@ async def test_auth_legacy_support_with_password( local_auth: HassAuthProvider, ) -> None: """Test authenticating with a token.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -256,7 +257,7 @@ async def test_auth_with_invalid_token( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test authenticating with a token.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -289,7 +290,7 @@ async def test_auth_sending_invalid_json_disconnects( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test sending invalid json during auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -308,7 +309,7 @@ async def test_auth_sending_binary_disconnects( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test sending bytes during auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -327,7 +328,7 @@ async def test_auth_close_disconnects( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test closing during auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -348,7 +349,7 @@ async def test_auth_error_disconnects( caplog: pytest.LogCaptureFixture, ) -> None: """Test error during auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -379,7 +380,7 @@ async def test_auth_sending_unknown_type_disconnects( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test sending unknown type during auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -400,7 +401,7 @@ async def test_error_right_after_auth_disconnects( caplog: pytest.LogCaptureFixture, ) -> None: """Test error right after auth.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() @@ -440,7 +441,7 @@ async def test_unix_socket_auth_bypass( HASSIO_USER_NAME, group_ids=["system-admin"] ) - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() client = await hass_client_no_auth() diff --git a/tests/components/websocket_api/test_commands.py b/tests/components/websocket_api/test_commands.py index b987ce14dd72df..87ffdb31bca1fa 100644 --- a/tests/components/websocket_api/test_commands.py +++ b/tests/components/websocket_api/test_commands.py @@ -18,7 +18,7 @@ from homeassistant.components.group import DOMAIN as GROUP_DOMAIN from homeassistant.components.light import LightEntityFeature from homeassistant.components.logger import DOMAIN as LOGGER_DOMAIN -from homeassistant.components.websocket_api import const +from homeassistant.components.websocket_api import DOMAIN, const from homeassistant.components.websocket_api.auth import ( TYPE_AUTH, TYPE_AUTH_OK, @@ -1238,7 +1238,7 @@ async def test_call_service_context_with_user( hass_access_token: str, ) -> None: """Test that the user is set in the service call context.""" - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) calls = async_mock_service(hass, "domain_test", "test_service") client = await hass_client_no_auth() diff --git a/tests/components/websocket_api/test_http.py b/tests/components/websocket_api/test_http.py index 2e60e837976bac..a857151b9f1b28 100644 --- a/tests/components/websocket_api/test_http.py +++ b/tests/components/websocket_api/test_http.py @@ -10,6 +10,7 @@ import pytest from homeassistant.components.websocket_api import ( + DOMAIN, async_register_command, const, http, @@ -412,7 +413,7 @@ async def test_auth_timeout_logs_at_debug( ) -> None: """Test auth timeout is logged at debug level not warning.""" # Setup websocket API - assert await async_setup_component(hass, "websocket_api", {}) + assert await async_setup_component(hass, DOMAIN, {}) client = await hass_client() From 3a46d1088b683802e1a2dd3b1f1a1745d7b4fa16 Mon Sep 17 00:00:00 2001 From: Vincent Knoop Pathuis <48653141+vpathuis@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:16:41 +0200 Subject: [PATCH 11/13] Refactor Landis+Gyr heat meter to use the HA standard SerialPortSelector (#173170) --- .../landisgyr_heat_meter/config_flow.py | 52 +--------- .../components/landisgyr_heat_meter/const.py | 2 +- .../landisgyr_heat_meter/strings.json | 5 - .../landisgyr_heat_meter/test_config_flow.py | 98 +++---------------- 4 files changed, 19 insertions(+), 138 deletions(-) diff --git a/homeassistant/components/landisgyr_heat_meter/config_flow.py b/homeassistant/components/landisgyr_heat_meter/config_flow.py index 4c044c1492a421..74cef628f916ec 100644 --- a/homeassistant/components/landisgyr_heat_meter/config_flow.py +++ b/homeassistant/components/landisgyr_heat_meter/config_flow.py @@ -8,21 +8,19 @@ import ultraheat_api import voluptuous as vol -from homeassistant.components import usb from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_DEVICE -from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.selector import SerialPortSelector from .const import DOMAIN, ULTRAHEAT_TIMEOUT _LOGGER = logging.getLogger(__name__) -CONF_MANUAL_PATH = "Enter Manually" STEP_USER_DATA_SCHEMA = vol.Schema( { - vol.Required(CONF_DEVICE): str, + vol.Required(CONF_DEVICE): SerialPortSelector(), } ) @@ -39,9 +37,6 @@ async def async_step_user( errors = {} if user_input is not None: - if user_input[CONF_DEVICE] == CONF_MANUAL_PATH: - return await self.async_step_setup_serial_manual_path() - dev_path = user_input[CONF_DEVICE] _LOGGER.debug("Using this path : %s", dev_path) @@ -50,30 +45,8 @@ async def async_step_user( except CannotConnect: errors["base"] = "cannot_connect" - ports = await get_usb_ports(self.hass) - ports[CONF_MANUAL_PATH] = CONF_MANUAL_PATH - - schema = vol.Schema({vol.Required(CONF_DEVICE): vol.In(ports)}) - return self.async_show_form(step_id="user", data_schema=schema, errors=errors) - - async def async_step_setup_serial_manual_path( - self, user_input: dict[str, Any] | None = None - ) -> ConfigFlowResult: - """Set path manually.""" - errors = {} - - if user_input is not None: - dev_path = user_input[CONF_DEVICE] - try: - return await self.validate_and_create_entry(dev_path) - except CannotConnect: - errors["base"] = "cannot_connect" - - schema = vol.Schema({vol.Required(CONF_DEVICE): str}) return self.async_show_form( - step_id="setup_serial_manual_path", - data_schema=schema, - errors=errors, + step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors ) async def validate_and_create_entry(self, dev_path): @@ -111,24 +84,5 @@ async def validate_ultraheat(self, port: str) -> tuple[str, str]: return data.model, data.device_number -async def get_usb_ports(hass: HomeAssistant) -> dict[str, str]: - """Return a dict of USB ports and their friendly names.""" - ports = await usb.async_scan_serial_ports(hass) - port_descriptions = {} - for port in ports: - if isinstance(port, usb.USBDevice): - human_name = usb.human_readable_device_name( - port.device, - port.serial_number, - port.manufacturer, - port.description, - port.vid, - port.pid, - ) - port_descriptions[port.device] = human_name - - return port_descriptions - - class CannotConnect(HomeAssistantError): """Error to indicate we cannot connect.""" diff --git a/homeassistant/components/landisgyr_heat_meter/const.py b/homeassistant/components/landisgyr_heat_meter/const.py index 079bcad2534848..2007d257058935 100644 --- a/homeassistant/components/landisgyr_heat_meter/const.py +++ b/homeassistant/components/landisgyr_heat_meter/const.py @@ -4,5 +4,5 @@ DOMAIN = "landisgyr_heat_meter" -ULTRAHEAT_TIMEOUT = 30 # reading the IR port can take some time +ULTRAHEAT_TIMEOUT = 60 # reading the IR port can take some time POLLING_INTERVAL = timedelta(days=1) # Polling is only daily to prevent battery drain. diff --git a/homeassistant/components/landisgyr_heat_meter/strings.json b/homeassistant/components/landisgyr_heat_meter/strings.json index 3d9c03c66b21a4..6262c98f3e31ca 100644 --- a/homeassistant/components/landisgyr_heat_meter/strings.json +++ b/homeassistant/components/landisgyr_heat_meter/strings.json @@ -7,11 +7,6 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" }, "step": { - "setup_serial_manual_path": { - "data": { - "device": "[%key:common::config_flow::data::usb_path%]" - } - }, "user": { "data": { "device": "Select device" diff --git a/tests/components/landisgyr_heat_meter/test_config_flow.py b/tests/components/landisgyr_heat_meter/test_config_flow.py index f0c3a992228af0..a2c876e6d92a5c 100644 --- a/tests/components/landisgyr_heat_meter/test_config_flow.py +++ b/tests/components/landisgyr_heat_meter/test_config_flow.py @@ -8,7 +8,6 @@ from homeassistant import config_entries from homeassistant.components.landisgyr_heat_meter import DOMAIN -from homeassistant.components.usb import USBDevice from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType @@ -22,18 +21,6 @@ pytestmark = pytest.mark.usefixtures("mock_setup_entry") -def mock_serial_port() -> USBDevice: - """Mock of a serial port.""" - return USBDevice( - device="/dev/ttyUSB1234", - vid="162E", - pid="269C", - serial_number="1234", - manufacturer="Virtual serial port", - description="Some serial port", - ) - - @dataclass class MockUltraheatRead: """Mock of the response from the read method of the Ultraheat API.""" @@ -43,8 +30,8 @@ class MockUltraheatRead: @patch(API_HEAT_METER_SERVICE) -async def test_manual_entry(mock_heat_meter, hass: HomeAssistant) -> None: - """Test manual entry.""" +async def test_user_flow_success(mock_heat_meter, hass: HomeAssistant) -> None: + """Test successful user flow.""" mock_heat_meter().read.return_value = MockUltraheatRead("LUGCUH50", "123456789") @@ -55,14 +42,6 @@ async def test_manual_entry(mock_heat_meter, hass: HomeAssistant) -> None: assert result["step_id"] == "user" assert result["errors"] == {} - result = await hass.config_entries.flow.async_configure( - result["flow_id"], {"device": "Enter Manually"} - ) - - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "setup_serial_manual_path" - assert result["errors"] == {} - result = await hass.config_entries.flow.async_configure( result["flow_id"], {"device": "/dev/ttyUSB0"} ) @@ -77,38 +56,10 @@ async def test_manual_entry(mock_heat_meter, hass: HomeAssistant) -> None: @patch(API_HEAT_METER_SERVICE) -@patch( - "homeassistant.components.landisgyr_heat_meter.config_flow.usb.async_scan_serial_ports", - return_value=[mock_serial_port()], -) -async def test_list_entry(mock_port, mock_heat_meter, hass: HomeAssistant) -> None: - """Test select from list entry.""" - - mock_heat_meter().read.return_value = MockUltraheatRead("LUGCUH50", "123456789") - port = mock_serial_port() - - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "user" - assert result["errors"] == {} - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], {"device": port.device} - ) - assert result["type"] is FlowResultType.CREATE_ENTRY - assert result["title"] == "LUGCUH50" - assert result["data"] == { - "device": port.device, - "model": "LUGCUH50", - "device_number": "123456789", - } - - -@patch(API_HEAT_METER_SERVICE) -async def test_manual_entry_fail(mock_heat_meter, hass: HomeAssistant) -> None: - """Test manual entry fails.""" +async def test_user_flow_cannot_connect_oserror( + mock_heat_meter, hass: HomeAssistant +) -> None: + """Test connection failure due to OSError.""" mock_heat_meter().read.side_effect = OSError("device unavailable") @@ -119,33 +70,22 @@ async def test_manual_entry_fail(mock_heat_meter, hass: HomeAssistant) -> None: assert result["step_id"] == "user" assert result["errors"] == {} - result = await hass.config_entries.flow.async_configure( - result["flow_id"], {"device": "Enter Manually"} - ) - - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "setup_serial_manual_path" - assert result["errors"] == {} - result = await hass.config_entries.flow.async_configure( result["flow_id"], {"device": "/dev/ttyUSB0"} ) assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "setup_serial_manual_path" + assert result["step_id"] == "user" assert result["errors"] == {"base": "cannot_connect"} @patch(API_HEAT_METER_SERVICE) -@patch( - "homeassistant.components.landisgyr_heat_meter.config_flow.usb.async_scan_serial_ports", - return_value=[mock_serial_port()], -) -async def test_list_entry_fail(mock_port, mock_heat_meter, hass: HomeAssistant) -> None: - """Test select from list entry fails.""" +async def test_user_flow_cannot_connect_serial_exception( + mock_heat_meter, hass: HomeAssistant +) -> None: + """Test connection failure due to serialx.SerialException.""" mock_heat_meter().read.side_effect = serialx.SerialException("connection failed") - port = mock_serial_port() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} @@ -155,24 +95,18 @@ async def test_list_entry_fail(mock_port, mock_heat_meter, hass: HomeAssistant) assert result["errors"] == {} result = await hass.config_entries.flow.async_configure( - result["flow_id"], {"device": port.device} + result["flow_id"], {"device": "/dev/ttyUSB0"} ) + assert result["type"] is FlowResultType.FORM assert result["step_id"] == "user" assert result["errors"] == {"base": "cannot_connect"} @patch(API_HEAT_METER_SERVICE) -@patch( - "homeassistant.components.landisgyr_heat_meter.config_flow.usb.async_scan_serial_ports", - return_value=[mock_serial_port()], -) -async def test_already_configured( - mock_port, mock_heat_meter, hass: HomeAssistant -) -> None: +async def test_already_configured(mock_heat_meter, hass: HomeAssistant) -> None: """Test we abort if the Heat Meter is already configured.""" - # create and add existing entry entry_data = { "device": "/dev/USB0", "model": "LUGCUH50", @@ -184,16 +118,14 @@ async def test_already_configured( await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() - # run flow and see if it aborts mock_heat_meter().read.return_value = MockUltraheatRead("LUGCUH50", "123456789") - port = mock_serial_port() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) result = await hass.config_entries.flow.async_configure( - result["flow_id"], {"device": port.device} + result["flow_id"], {"device": "/dev/ttyUSB0"} ) assert result["type"] is FlowResultType.ABORT From 390766ba3a4e6d8e74795a73f3cf44940fae1a47 Mon Sep 17 00:00:00 2001 From: Tomer <57483589+tomer-w@users.noreply.github.com> Date: Sun, 7 Jun 2026 00:15:39 +0300 Subject: [PATCH 12/13] Bump victron-mqtt to 2026.6.1.1 (#173142) --- homeassistant/components/victron_gx/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/victron_gx/manifest.json b/homeassistant/components/victron_gx/manifest.json index 72f1aa74495da2..10a9662f1cd156 100644 --- a/homeassistant/components/victron_gx/manifest.json +++ b/homeassistant/components/victron_gx/manifest.json @@ -7,7 +7,7 @@ "integration_type": "hub", "iot_class": "local_push", "quality_scale": "platinum", - "requirements": ["victron-mqtt==2026.6.1"], + "requirements": ["victron-mqtt==2026.6.1.1"], "ssdp": [ { "X_MqttOnLan": "1", diff --git a/requirements_all.txt b/requirements_all.txt index adae8796cc5778..95cf7d38cc72fc 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -3302,7 +3302,7 @@ viaggiatreno_ha==0.2.4 victron-ble-ha-parser==0.7.0 # homeassistant.components.victron_gx -victron-mqtt==2026.6.1 +victron-mqtt==2026.6.1.1 # homeassistant.components.victron_remote_monitoring victron-vrm==0.1.8 From d0b34dfe925a0417435a547cd3965054c54904f2 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sat, 6 Jun 2026 23:19:29 +0200 Subject: [PATCH 13/13] Have Plugwise handle unavailable temperature measurements (#173173) --- homeassistant/components/plugwise/climate.py | 4 +-- tests/components/plugwise/test_climate.py | 28 +++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/plugwise/climate.py b/homeassistant/components/plugwise/climate.py index 6fd2e14d026544..52a7553505f630 100644 --- a/homeassistant/components/plugwise/climate.py +++ b/homeassistant/components/plugwise/climate.py @@ -155,9 +155,9 @@ def extra_restore_state_data(self) -> PlugwiseClimateExtraStoredData: ) @property - def current_temperature(self) -> float: + def current_temperature(self) -> float | None: """Return the current temperature.""" - return self.device["sensors"]["temperature"] + return self.device["sensors"].get("temperature") @property def target_temperature(self) -> float: diff --git a/tests/components/plugwise/test_climate.py b/tests/components/plugwise/test_climate.py index 8d7e15fc404b99..357ea12ab49207 100644 --- a/tests/components/plugwise/test_climate.py +++ b/tests/components/plugwise/test_climate.py @@ -9,6 +9,7 @@ from syrupy.assertion import SnapshotAssertion from homeassistant.components.climate import ( + ATTR_CURRENT_TEMPERATURE, ATTR_HVAC_ACTION, ATTR_HVAC_MODE, ATTR_HVAC_MODES, @@ -24,7 +25,13 @@ HVACMode, ) from homeassistant.components.plugwise.climate import PlugwiseClimateExtraStoredData -from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_OFF, STATE_ON +from homeassistant.const import ( + ATTR_ENTITY_ID, + ATTR_TEMPERATURE, + STATE_OFF, + STATE_ON, + STATE_UNAVAILABLE, +) from homeassistant.core import HomeAssistant, State from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.helpers import entity_registry as er @@ -680,3 +687,22 @@ async def test_anna_p1_climate_snapshot( ) -> None: """Test Anna P1 climate snapshot.""" await snapshot_platform(hass, entity_registry, snapshot, setup_platform.entry_id) + + +@pytest.mark.parametrize("chosen_env", ["m_adam_cooling"], indirect=True) +@pytest.mark.parametrize("cooling_present", [False], indirect=True) +async def test_tom_without_temperature_measurement( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_smile_adam_heat_cool: MagicMock, +) -> None: + """Test Tom without temperature measurement.""" + data = mock_smile_adam_heat_cool.async_update.return_value + del data["f871b8c4d63549319221e294e4f88074"]["sensors"]["temperature"] + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert (state := hass.states.get("climate.bathroom")) is not None + assert state.state != STATE_UNAVAILABLE + assert state.attributes[ATTR_CURRENT_TEMPERATURE] is None