mirror of
https://github.com/home-assistant/core.git
synced 2026-01-17 21:16:53 +01:00
Compare commits
1 Commits
matter_mut
...
multi_doma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb5daaf3fe |
@@ -176,6 +176,9 @@
|
||||
}
|
||||
},
|
||||
"triggers": {
|
||||
"door.opened": {
|
||||
"trigger": "mdi:door-open"
|
||||
},
|
||||
"occupancy_cleared": {
|
||||
"trigger": "mdi:home-outline"
|
||||
},
|
||||
|
||||
@@ -332,6 +332,16 @@
|
||||
},
|
||||
"title": "Binary sensor",
|
||||
"triggers": {
|
||||
"door.opened": {
|
||||
"description": "Triggers after one or more occupancy doors open.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"description": "[%key:component::binary_sensor::common::trigger_behavior_description_occupancy%]",
|
||||
"name": "[%key:component::binary_sensor::common::trigger_behavior_name%]"
|
||||
}
|
||||
},
|
||||
"name": "Door opened"
|
||||
},
|
||||
"occupancy_cleared": {
|
||||
"description": "Triggers after one or more occupancy sensors stop detecting occupancy.",
|
||||
"fields": {
|
||||
|
||||
@@ -53,6 +53,7 @@ def make_binary_sensor_trigger(
|
||||
|
||||
|
||||
TRIGGERS: dict[str, type[Trigger]] = {
|
||||
"_door.opened": make_binary_sensor_trigger(BinarySensorDeviceClass.DOOR, STATE_ON),
|
||||
"occupancy_detected": make_binary_sensor_trigger(
|
||||
BinarySensorDeviceClass.OCCUPANCY, STATE_ON
|
||||
),
|
||||
|
||||
@@ -23,3 +23,10 @@ occupancy_detected:
|
||||
entity:
|
||||
domain: binary_sensor
|
||||
device_class: occupancy
|
||||
|
||||
_door.opened:
|
||||
fields: *trigger_common_fields
|
||||
target:
|
||||
entity:
|
||||
domain: binary_sensor
|
||||
device_class: door
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
"winter_mode": {}
|
||||
},
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["home-assistant-frontend==20260107.2"]
|
||||
"requirements": ["home-assistant-frontend==20260107.1"]
|
||||
}
|
||||
|
||||
@@ -18,11 +18,7 @@ from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.loader import async_get_custom_components
|
||||
|
||||
from .const import DOMAIN, LABS_DATA, STORAGE_KEY, STORAGE_VERSION
|
||||
from .helpers import (
|
||||
async_is_preview_feature_enabled,
|
||||
async_listen,
|
||||
async_update_preview_feature,
|
||||
)
|
||||
from .helpers import async_is_preview_feature_enabled, async_listen
|
||||
from .models import (
|
||||
EventLabsUpdatedData,
|
||||
LabPreviewFeature,
|
||||
@@ -41,7 +37,6 @@ __all__ = [
|
||||
"EventLabsUpdatedData",
|
||||
"async_is_preview_feature_enabled",
|
||||
"async_listen",
|
||||
"async_update_preview_feature",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -61,32 +61,3 @@ def async_listen(
|
||||
listener()
|
||||
|
||||
return hass.bus.async_listen(EVENT_LABS_UPDATED, _async_feature_updated)
|
||||
|
||||
|
||||
async def async_update_preview_feature(
|
||||
hass: HomeAssistant,
|
||||
domain: str,
|
||||
preview_feature: str,
|
||||
enabled: bool,
|
||||
) -> None:
|
||||
"""Update a lab preview feature state."""
|
||||
labs_data = hass.data[LABS_DATA]
|
||||
|
||||
preview_feature_id = f"{domain}.{preview_feature}"
|
||||
|
||||
if preview_feature_id not in labs_data.preview_features:
|
||||
raise ValueError(f"Preview feature {preview_feature_id} not found")
|
||||
|
||||
if enabled:
|
||||
labs_data.data.preview_feature_status.add((domain, preview_feature))
|
||||
else:
|
||||
labs_data.data.preview_feature_status.discard((domain, preview_feature))
|
||||
|
||||
await labs_data.store.async_save(labs_data.data.to_store_format())
|
||||
|
||||
event_data: EventLabsUpdatedData = {
|
||||
"domain": domain,
|
||||
"preview_feature": preview_feature,
|
||||
"enabled": enabled,
|
||||
}
|
||||
hass.bus.async_fire(EVENT_LABS_UPDATED, event_data)
|
||||
|
||||
@@ -8,14 +8,12 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.backup import async_get_manager
|
||||
from homeassistant.const import EVENT_LABS_UPDATED
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from .const import LABS_DATA
|
||||
from .helpers import (
|
||||
async_is_preview_feature_enabled,
|
||||
async_listen,
|
||||
async_update_preview_feature,
|
||||
)
|
||||
from .helpers import async_is_preview_feature_enabled, async_listen
|
||||
from .models import EventLabsUpdatedData
|
||||
|
||||
|
||||
@callback
|
||||
@@ -97,7 +95,19 @@ async def websocket_update_preview_feature(
|
||||
)
|
||||
return
|
||||
|
||||
await async_update_preview_feature(hass, domain, preview_feature, enabled)
|
||||
if enabled:
|
||||
labs_data.data.preview_feature_status.add((domain, preview_feature))
|
||||
else:
|
||||
labs_data.data.preview_feature_status.discard((domain, preview_feature))
|
||||
|
||||
await labs_data.store.async_save(labs_data.data.to_store_format())
|
||||
|
||||
event_data: EventLabsUpdatedData = {
|
||||
"domain": domain,
|
||||
"preview_feature": preview_feature,
|
||||
"enabled": enabled,
|
||||
}
|
||||
hass.bus.async_fire(EVENT_LABS_UPDATED, event_data)
|
||||
|
||||
connection.send_result(msg["id"])
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ from .coordinator import MastodonConfigEntry, MastodonCoordinator, MastodonData
|
||||
from .services import async_setup_services
|
||||
from .utils import construct_mastodon_username, create_mastodon_client
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
"""Binary sensor platform for the Mastodon integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from mastodon.Mastodon import Account
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .coordinator import MastodonConfigEntry
|
||||
from .entity import MastodonEntity
|
||||
|
||||
# Coordinator is used to centralize the data updates
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
class MastodonBinarySensor(StrEnum):
|
||||
"""Mastodon binary sensors."""
|
||||
|
||||
BOT = "bot"
|
||||
SUSPENDED = "suspended"
|
||||
DISCOVERABLE = "discoverable"
|
||||
LOCKED = "locked"
|
||||
INDEXABLE = "indexable"
|
||||
LIMITED = "limited"
|
||||
MEMORIAL = "memorial"
|
||||
MOVED = "moved"
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class MastodonBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||
"""Mastodon binary sensor description."""
|
||||
|
||||
is_on_fn: Callable[[Account], bool | None]
|
||||
|
||||
|
||||
ENTITY_DESCRIPTIONS: tuple[MastodonBinarySensorEntityDescription, ...] = (
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.BOT,
|
||||
translation_key=MastodonBinarySensor.BOT,
|
||||
is_on_fn=lambda account: account.bot,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.DISCOVERABLE,
|
||||
translation_key=MastodonBinarySensor.DISCOVERABLE,
|
||||
is_on_fn=lambda account: account.discoverable,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.LOCKED,
|
||||
translation_key=MastodonBinarySensor.LOCKED,
|
||||
is_on_fn=lambda account: account.locked,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.MOVED,
|
||||
translation_key=MastodonBinarySensor.MOVED,
|
||||
is_on_fn=lambda account: account.moved is not None,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.INDEXABLE,
|
||||
translation_key=MastodonBinarySensor.INDEXABLE,
|
||||
is_on_fn=lambda account: account.indexable,
|
||||
entity_registry_enabled_default=False,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.LIMITED,
|
||||
translation_key=MastodonBinarySensor.LIMITED,
|
||||
is_on_fn=lambda account: account.limited is True,
|
||||
entity_registry_enabled_default=False,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.MEMORIAL,
|
||||
translation_key=MastodonBinarySensor.MEMORIAL,
|
||||
is_on_fn=lambda account: account.memorial is True,
|
||||
entity_registry_enabled_default=False,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
MastodonBinarySensorEntityDescription(
|
||||
key=MastodonBinarySensor.SUSPENDED,
|
||||
translation_key=MastodonBinarySensor.SUSPENDED,
|
||||
is_on_fn=lambda account: account.suspended is True,
|
||||
entity_registry_enabled_default=False,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: MastodonConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the binary sensor platform."""
|
||||
coordinator = entry.runtime_data.coordinator
|
||||
|
||||
async_add_entities(
|
||||
MastodonBinarySensorEntity(
|
||||
coordinator=coordinator,
|
||||
entity_description=entity_description,
|
||||
data=entry,
|
||||
)
|
||||
for entity_description in ENTITY_DESCRIPTIONS
|
||||
)
|
||||
|
||||
|
||||
class MastodonBinarySensorEntity(MastodonEntity, BinarySensorEntity):
|
||||
"""Mastodon binary sensor entity."""
|
||||
|
||||
entity_description: MastodonBinarySensorEntityDescription
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.entity_description.is_on_fn(self.coordinator.data)
|
||||
@@ -1,18 +1,5 @@
|
||||
{
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bot": { "default": "mdi:robot" },
|
||||
"discoverable": { "default": "mdi:magnify-scan" },
|
||||
"indexable": { "default": "mdi:search-web" },
|
||||
"limited": { "default": "mdi:account-cancel" },
|
||||
"locked": {
|
||||
"default": "mdi:account-lock",
|
||||
"state": { "off": "mdi:account-lock-open" }
|
||||
},
|
||||
"memorial": { "default": "mdi:candle" },
|
||||
"moved": { "default": "mdi:truck-delivery" },
|
||||
"suspended": { "default": "mdi:account-off" }
|
||||
},
|
||||
"sensor": {
|
||||
"followers": {
|
||||
"default": "mdi:account-multiple"
|
||||
|
||||
@@ -26,16 +26,6 @@
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bot": { "name": "Bot" },
|
||||
"discoverable": { "name": "Discoverable" },
|
||||
"indexable": { "name": "Indexable" },
|
||||
"limited": { "name": "Limited" },
|
||||
"locked": { "name": "Locked" },
|
||||
"memorial": { "name": "Memorial" },
|
||||
"moved": { "name": "Moved" },
|
||||
"suspended": { "name": "Suspended" }
|
||||
},
|
||||
"sensor": {
|
||||
"followers": {
|
||||
"name": "Followers",
|
||||
|
||||
@@ -489,7 +489,6 @@ DISCOVERY_SCHEMAS = [
|
||||
platform=Platform.BINARY_SENSOR,
|
||||
entity_description=MatterBinarySensorEntityDescription(
|
||||
key="WindowCoveringConfigStatusOperational",
|
||||
translation_key="config_status_operational",
|
||||
device_class=BinarySensorDeviceClass.PROBLEM,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
# unset Operational bit from ConfigStatus bitmap means problem
|
||||
|
||||
@@ -56,9 +56,6 @@
|
||||
"boost_state": {
|
||||
"name": "Boost state"
|
||||
},
|
||||
"config_status_operational": {
|
||||
"name": "Configuration status"
|
||||
},
|
||||
"dishwasher_alarm_inflow": {
|
||||
"name": "Inflow alarm"
|
||||
},
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["aiomealie==1.2.0"]
|
||||
"requirements": ["aiomealie==1.1.1"]
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: OpenAIConfigEntry) -> bo
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: OpenAIConfigEntry) -> bool:
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload OpenAI."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
@@ -280,7 +280,7 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
||||
if not any(entry.version == 1 for entry in entries):
|
||||
return
|
||||
|
||||
api_keys_entries: dict[str, tuple[OpenAIConfigEntry, bool]] = {}
|
||||
api_keys_entries: dict[str, tuple[ConfigEntry, bool]] = {}
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from typing import TYPE_CHECKING
|
||||
from openai.types.responses.response_output_item import ImageGenerationCall
|
||||
|
||||
from homeassistant.components import ai_task, conversation
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -34,7 +35,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: OpenAIConfigEntry,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up AI Task entities."""
|
||||
|
||||
@@ -24,10 +24,10 @@ from homeassistant.helpers.discovery import load_platform
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import DATA_QUIKSWITCH, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "qwikswitch"
|
||||
|
||||
CONF_DIMMER_ADJUST = "dimmer_adjust"
|
||||
CONF_BUTTON_EVENTS = "button_events"
|
||||
CV_DIM_VALUE = vol.All(vol.Coerce(float), vol.Range(min=1, max=3))
|
||||
@@ -96,7 +96,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
if not await qsusb.update_from_devices():
|
||||
return False
|
||||
|
||||
hass.data[DATA_QUIKSWITCH] = qsusb
|
||||
hass.data[DOMAIN] = qsusb
|
||||
|
||||
comps: dict[Platform, list] = {
|
||||
Platform.SWITCH: [],
|
||||
@@ -168,7 +168,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
@callback
|
||||
def async_stop(_):
|
||||
"""Stop the listener."""
|
||||
hass.data[DATA_QUIKSWITCH].stop()
|
||||
hass.data[DOMAIN].stop()
|
||||
|
||||
hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, async_stop)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DATA_QUIKSWITCH, DOMAIN
|
||||
from . import DOMAIN
|
||||
from .entity import QSEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -30,7 +30,7 @@ async def async_setup_platform(
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
qsusb = hass.data[DATA_QUIKSWITCH]
|
||||
qsusb = hass.data[DOMAIN]
|
||||
_LOGGER.debug("Setup qwikswitch.binary_sensor %s, %s", qsusb, discovery_info)
|
||||
devs = [QSBinarySensor(sensor) for sensor in discovery_info[DOMAIN]]
|
||||
add_entities(devs)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
"""Support for Qwikswitch devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pyqwikswitch.async_ import QSUsb
|
||||
|
||||
DOMAIN = "qwikswitch"
|
||||
DATA_QUIKSWITCH: HassKey[QSUsb] = HassKey(DOMAIN)
|
||||
@@ -7,7 +7,7 @@ from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DATA_QUIKSWITCH
|
||||
from . import DOMAIN
|
||||
|
||||
|
||||
class QSEntity(Entity):
|
||||
@@ -67,8 +67,8 @@ class QSToggleEntity(QSEntity):
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
new = kwargs.get(ATTR_BRIGHTNESS, 255)
|
||||
self.hass.data[DATA_QUIKSWITCH].devices.set_value(self.qsid, new)
|
||||
self.hass.data[DOMAIN].devices.set_value(self.qsid, new)
|
||||
|
||||
async def async_turn_off(self, **_):
|
||||
"""Turn the device off."""
|
||||
self.hass.data[DATA_QUIKSWITCH].devices.set_value(self.qsid, 0)
|
||||
self.hass.data[DOMAIN].devices.set_value(self.qsid, 0)
|
||||
|
||||
@@ -12,7 +12,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DATA_QUIKSWITCH, DOMAIN
|
||||
from . import DOMAIN
|
||||
from .entity import QSEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -28,7 +28,7 @@ async def async_setup_platform(
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
qsusb = hass.data[DATA_QUIKSWITCH]
|
||||
qsusb = hass.data[DOMAIN]
|
||||
_LOGGER.debug("Setup qwikswitch.sensor %s, %s", qsusb, discovery_info)
|
||||
devs = [QSSensor(sensor) for sensor in discovery_info[DOMAIN]]
|
||||
add_entities(devs)
|
||||
|
||||
@@ -7,7 +7,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DATA_QUIKSWITCH, DOMAIN
|
||||
from . import DOMAIN
|
||||
from .entity import QSToggleEntity
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ async def async_setup_platform(
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
qsusb = hass.data[DATA_QUIKSWITCH]
|
||||
qsusb = hass.data[DOMAIN]
|
||||
devs = [QSSwitch(qsid, qsusb) for qsid in discovery_info[DOMAIN]]
|
||||
add_entities(devs)
|
||||
|
||||
|
||||
@@ -144,51 +144,6 @@ class SmaConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_reconfigure(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle reconfiguration of the integration."""
|
||||
errors: dict[str, str] = {}
|
||||
reconf_entry = self._get_reconfigure_entry()
|
||||
if user_input is not None:
|
||||
errors, device_info = await self._handle_user_input(
|
||||
user_input={
|
||||
**reconf_entry.data,
|
||||
**user_input,
|
||||
}
|
||||
)
|
||||
|
||||
if not errors:
|
||||
await self.async_set_unique_id(
|
||||
str(device_info["serial"]), raise_on_progress=False
|
||||
)
|
||||
self._abort_if_unique_id_mismatch()
|
||||
return self.async_update_reload_and_abort(
|
||||
reconf_entry,
|
||||
data_updates={
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_SSL: user_input[CONF_SSL],
|
||||
CONF_VERIFY_SSL: user_input[CONF_VERIFY_SSL],
|
||||
CONF_GROUP: user_input[CONF_GROUP],
|
||||
},
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="reconfigure",
|
||||
data_schema=self.add_suggested_values_to_schema(
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_SSL): cv.boolean,
|
||||
vol.Optional(CONF_VERIFY_SSL): cv.boolean,
|
||||
vol.Optional(CONF_GROUP): vol.In(GROUPS),
|
||||
}
|
||||
),
|
||||
suggested_values=user_input or dict(reconf_entry.data),
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_reauth(
|
||||
self, entry_data: Mapping[str, Any]
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
|
||||
"unique_id_mismatch": "You selected a different SMA device than the one this config entry was configured with, this is not allowed."
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
@@ -31,16 +29,6 @@
|
||||
"description": "The SMA integration needs to re-authenticate your connection details",
|
||||
"title": "[%key:common::config_flow::title::reauth%]"
|
||||
},
|
||||
"reconfigure": {
|
||||
"data": {
|
||||
"group": "[%key:component::sma::config::step::user::data::group%]",
|
||||
"host": "[%key:common::config_flow::data::host%]",
|
||||
"ssl": "[%key:common::config_flow::data::ssl%]",
|
||||
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
|
||||
},
|
||||
"description": "Use the following form to reconfigure your SMA device.",
|
||||
"title": "Reconfigure SMA Solar Integration"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"group": "Group",
|
||||
@@ -56,13 +44,5 @@
|
||||
"title": "Set up SMA Solar"
|
||||
}
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
"group": {
|
||||
"options": {
|
||||
"installer": "Installer",
|
||||
"user": "User"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -840,26 +840,19 @@ class NodeEvents:
|
||||
# After ensuring the node is set up in HA, we should check if the node's
|
||||
# device config has changed, and if so, issue a repair registry entry for a
|
||||
# possible reinterview
|
||||
if not node.is_controller_node:
|
||||
issue_id = f"device_config_file_changed.{device.id}"
|
||||
if await node.async_has_device_config_changed():
|
||||
device_name = device.name_by_user or device.name or "Unnamed device"
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
issue_id,
|
||||
data={"device_id": device.id, "device_name": device_name},
|
||||
is_fixable=True,
|
||||
is_persistent=False,
|
||||
translation_key="device_config_file_changed",
|
||||
translation_placeholders={"device_name": device_name},
|
||||
severity=IssueSeverity.WARNING,
|
||||
)
|
||||
else:
|
||||
# Clear any existing repair issue if the device config is not considered
|
||||
# changed. This can happen when the original issue was created by
|
||||
# an upstream bug, or the change has been reverted.
|
||||
async_delete_issue(self.hass, DOMAIN, issue_id)
|
||||
if not node.is_controller_node and await node.async_has_device_config_changed():
|
||||
device_name = device.name_by_user or device.name or "Unnamed device"
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
f"device_config_file_changed.{device.id}",
|
||||
data={"device_id": device.id, "device_name": device_name},
|
||||
is_fixable=True,
|
||||
is_persistent=False,
|
||||
translation_key="device_config_file_changed",
|
||||
translation_placeholders={"device_name": device_name},
|
||||
severity=IssueSeverity.WARNING,
|
||||
)
|
||||
|
||||
async def async_handle_discovery_info(
|
||||
self,
|
||||
|
||||
@@ -121,7 +121,7 @@ def starts_with_dot(key: str) -> str:
|
||||
_TRIGGERS_DESCRIPTION_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Remove(vol.All(str, starts_with_dot)): object,
|
||||
cv.underscore_slug: vol.Any(None, _TRIGGER_DESCRIPTION_SCHEMA),
|
||||
str: vol.Any(None, _TRIGGER_DESCRIPTION_SCHEMA),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1433,6 +1433,10 @@ async def async_get_all_descriptions(
|
||||
if (target := yaml_description.get("target")) is not None:
|
||||
description["target"] = target
|
||||
|
||||
prefix, sep, _ = missing_trigger.partition(".")
|
||||
if sep and domain != prefix:
|
||||
description["translation_domain"] = domain
|
||||
|
||||
new_descriptions_cache[missing_trigger] = description
|
||||
hass.data[TRIGGER_DESCRIPTION_CACHE] = new_descriptions_cache
|
||||
return new_descriptions_cache
|
||||
|
||||
@@ -39,7 +39,7 @@ habluetooth==5.8.0
|
||||
hass-nabucasa==1.9.0
|
||||
hassil==3.5.0
|
||||
home-assistant-bluetooth==1.13.1
|
||||
home-assistant-frontend==20260107.2
|
||||
home-assistant-frontend==20260107.1
|
||||
home-assistant-intents==2026.1.6
|
||||
httpx==0.28.1
|
||||
ifaddr==0.2.0
|
||||
|
||||
4
requirements_all.txt
generated
4
requirements_all.txt
generated
@@ -319,7 +319,7 @@ aiolookin==1.0.0
|
||||
aiolyric==2.0.2
|
||||
|
||||
# homeassistant.components.mealie
|
||||
aiomealie==1.2.0
|
||||
aiomealie==1.1.1
|
||||
|
||||
# homeassistant.components.modern_forms
|
||||
aiomodernforms==0.1.8
|
||||
@@ -1215,7 +1215,7 @@ hole==0.9.0
|
||||
holidays==0.84
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20260107.2
|
||||
home-assistant-frontend==20260107.1
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2026.1.6
|
||||
|
||||
4
requirements_test_all.txt
generated
4
requirements_test_all.txt
generated
@@ -304,7 +304,7 @@ aiolookin==1.0.0
|
||||
aiolyric==2.0.2
|
||||
|
||||
# homeassistant.components.mealie
|
||||
aiomealie==1.2.0
|
||||
aiomealie==1.1.1
|
||||
|
||||
# homeassistant.components.modern_forms
|
||||
aiomodernforms==0.1.8
|
||||
@@ -1073,7 +1073,7 @@ hole==0.9.0
|
||||
holidays==0.84
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20260107.2
|
||||
home-assistant-frontend==20260107.1
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2026.1.6
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Tests for analytics platform."""
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.analytics import async_devices_payload
|
||||
from homeassistant.components.esphome import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -9,6 +11,7 @@ from homeassistant.setup import async_setup_component
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_analytics(
|
||||
hass: HomeAssistant, device_registry: dr.DeviceRegistry
|
||||
) -> None:
|
||||
|
||||
@@ -52,6 +52,7 @@ async def test_async_setup_entry_errors(
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_setup_entry_success(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MagicMock,
|
||||
@@ -66,6 +67,7 @@ async def test_async_setup_entry_success(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_unload_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MagicMock,
|
||||
@@ -85,6 +87,7 @@ async def test_async_unload_entry(
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_platforms_forwarded(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MagicMock,
|
||||
|
||||
@@ -38,6 +38,7 @@ async def test_sensors(
|
||||
ValueError,
|
||||
],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_sensor_unavailable_on_update_error(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
|
||||
@@ -11,7 +11,6 @@ from homeassistant.components.labs import (
|
||||
EVENT_LABS_UPDATED,
|
||||
async_is_preview_feature_enabled,
|
||||
async_listen,
|
||||
async_update_preview_feature,
|
||||
)
|
||||
from homeassistant.components.labs.const import DOMAIN, LABS_DATA
|
||||
from homeassistant.components.labs.models import LabPreviewFeature
|
||||
@@ -21,8 +20,6 @@ from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import assert_stored_labs_data
|
||||
|
||||
from tests.common import async_capture_events
|
||||
|
||||
|
||||
async def test_async_setup(hass: HomeAssistant) -> None:
|
||||
"""Test the Labs integration setup."""
|
||||
@@ -439,57 +436,3 @@ async def test_async_listen_helper(hass: HomeAssistant) -> None:
|
||||
|
||||
# Verify listener was not called after unsubscribe
|
||||
assert len(listener_calls) == 1
|
||||
|
||||
|
||||
async def test_async_update_preview_feature(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test enabling and disabling a preview feature using the helper function."""
|
||||
hass.config.components.add("kitchen_sink")
|
||||
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
events = async_capture_events(hass, EVENT_LABS_UPDATED)
|
||||
|
||||
await async_update_preview_feature(
|
||||
hass, "kitchen_sink", "special_repair", enabled=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert async_is_preview_feature_enabled(hass, "kitchen_sink", "special_repair")
|
||||
|
||||
assert len(events) == 1
|
||||
assert events[0].data["domain"] == "kitchen_sink"
|
||||
assert events[0].data["preview_feature"] == "special_repair"
|
||||
assert events[0].data["enabled"] is True
|
||||
|
||||
assert_stored_labs_data(
|
||||
hass_storage,
|
||||
[{"domain": "kitchen_sink", "preview_feature": "special_repair"}],
|
||||
)
|
||||
|
||||
await async_update_preview_feature(
|
||||
hass, "kitchen_sink", "special_repair", enabled=False
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not async_is_preview_feature_enabled(hass, "kitchen_sink", "special_repair")
|
||||
|
||||
assert len(events) == 2
|
||||
assert events[1].data["domain"] == "kitchen_sink"
|
||||
assert events[1].data["preview_feature"] == "special_repair"
|
||||
assert events[1].data["enabled"] is False
|
||||
|
||||
assert_stored_labs_data(hass_storage, [])
|
||||
|
||||
|
||||
async def test_async_update_preview_feature_not_found(hass: HomeAssistant) -> None:
|
||||
"""Test updating a preview feature that doesn't exist raises."""
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
with pytest.raises(
|
||||
ValueError, match="Preview feature nonexistent.feature not found"
|
||||
):
|
||||
await async_update_preview_feature(hass, "nonexistent", "feature", enabled=True)
|
||||
|
||||
@@ -1,393 +0,0 @@
|
||||
# serializer version: 1
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_bot-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_bot',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Bot',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Bot',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.BOT: 'bot'>,
|
||||
'unique_id': 'trwnh_mastodon_social_bot',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_bot-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Bot',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_bot',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_discoverable-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_discoverable',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Discoverable',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Discoverable',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.DISCOVERABLE: 'discoverable'>,
|
||||
'unique_id': 'trwnh_mastodon_social_discoverable',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_discoverable-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Discoverable',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_discoverable',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_indexable-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_indexable',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Indexable',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Indexable',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.INDEXABLE: 'indexable'>,
|
||||
'unique_id': 'trwnh_mastodon_social_indexable',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_indexable-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Indexable',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_indexable',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_limited-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_limited',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Limited',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Limited',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.LIMITED: 'limited'>,
|
||||
'unique_id': 'trwnh_mastodon_social_limited',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_limited-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Limited',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_limited',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_locked-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_locked',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Locked',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Locked',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.LOCKED: 'locked'>,
|
||||
'unique_id': 'trwnh_mastodon_social_locked',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_locked-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Locked',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_locked',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_memorial-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_memorial',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Memorial',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Memorial',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.MEMORIAL: 'memorial'>,
|
||||
'unique_id': 'trwnh_mastodon_social_memorial',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_memorial-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Memorial',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_memorial',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_moved-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_moved',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Moved',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Moved',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.MOVED: 'moved'>,
|
||||
'unique_id': 'trwnh_mastodon_social_moved',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_moved-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Moved',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_moved',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_suspended-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_suspended',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Suspended',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Suspended',
|
||||
'platform': 'mastodon',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <MastodonBinarySensor.SUSPENDED: 'suspended'>,
|
||||
'unique_id': 'trwnh_mastodon_social_suspended',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[binary_sensor.mastodon_trwnh_mastodon_social_suspended-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Mastodon @trwnh@mastodon.social Suspended',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mastodon_trwnh_mastodon_social_suspended',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -1,28 +0,0 @@
|
||||
"""Tests for the Mastodon binary sensors."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_mastodon_client", "entity_registry_enabled_by_default")
|
||||
async def test_binary_sensors(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the binary sensor entities."""
|
||||
with patch("homeassistant.components.mastodon.PLATFORMS", [Platform.BINARY_SENSOR]):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
@@ -349,7 +349,7 @@
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[eve_shutter][binary_sensor.eve_shutter_switch_20eci1701_configuration_status-entry]
|
||||
# name: test_binary_sensors[eve_shutter][binary_sensor.eve_shutter_switch_20eci1701_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -362,7 +362,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.eve_shutter_switch_20eci1701_configuration_status',
|
||||
'entity_id': 'binary_sensor.eve_shutter_switch_20eci1701_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -370,29 +370,29 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000094-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[eve_shutter][binary_sensor.eve_shutter_switch_20eci1701_configuration_status-state]
|
||||
# name: test_binary_sensors[eve_shutter][binary_sensor.eve_shutter_switch_20eci1701_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Eve Shutter Switch 20ECI1701 Configuration status',
|
||||
'friendly_name': 'Eve Shutter Switch 20ECI1701 Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.eve_shutter_switch_20eci1701_configuration_status',
|
||||
'entity_id': 'binary_sensor.eve_shutter_switch_20eci1701_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
@@ -1942,7 +1942,7 @@
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_full][binary_sensor.mock_full_window_covering_configuration_status-entry]
|
||||
# name: test_binary_sensors[window_covering_full][binary_sensor.mock_full_window_covering_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -1955,7 +1955,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mock_full_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_full_window_covering_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -1963,36 +1963,36 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_full][binary_sensor.mock_full_window_covering_configuration_status-state]
|
||||
# name: test_binary_sensors[window_covering_full][binary_sensor.mock_full_window_covering_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Mock Full Window Covering Configuration status',
|
||||
'friendly_name': 'Mock Full Window Covering Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mock_full_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_full_window_covering_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_lift][binary_sensor.mock_lift_window_covering_configuration_status-entry]
|
||||
# name: test_binary_sensors[window_covering_lift][binary_sensor.mock_lift_window_covering_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -2005,7 +2005,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mock_lift_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_lift_window_covering_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -2013,36 +2013,36 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_lift][binary_sensor.mock_lift_window_covering_configuration_status-state]
|
||||
# name: test_binary_sensors[window_covering_lift][binary_sensor.mock_lift_window_covering_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Mock Lift Window Covering Configuration status',
|
||||
'friendly_name': 'Mock Lift Window Covering Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mock_lift_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_lift_window_covering_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_pa_lift][binary_sensor.longan_link_wncv_da01_configuration_status-entry]
|
||||
# name: test_binary_sensors[window_covering_pa_lift][binary_sensor.longan_link_wncv_da01_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -2055,7 +2055,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.longan_link_wncv_da01_configuration_status',
|
||||
'entity_id': 'binary_sensor.longan_link_wncv_da01_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -2063,36 +2063,36 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_pa_lift][binary_sensor.longan_link_wncv_da01_configuration_status-state]
|
||||
# name: test_binary_sensors[window_covering_pa_lift][binary_sensor.longan_link_wncv_da01_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Longan link WNCV DA01 Configuration status',
|
||||
'friendly_name': 'Longan link WNCV DA01 Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.longan_link_wncv_da01_configuration_status',
|
||||
'entity_id': 'binary_sensor.longan_link_wncv_da01_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_pa_tilt][binary_sensor.mock_pa_tilt_window_covering_configuration_status-entry]
|
||||
# name: test_binary_sensors[window_covering_pa_tilt][binary_sensor.mock_pa_tilt_window_covering_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -2105,7 +2105,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mock_pa_tilt_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_pa_tilt_window_covering_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -2113,36 +2113,36 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_pa_tilt][binary_sensor.mock_pa_tilt_window_covering_configuration_status-state]
|
||||
# name: test_binary_sensors[window_covering_pa_tilt][binary_sensor.mock_pa_tilt_window_covering_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Mock PA Tilt Window Covering Configuration status',
|
||||
'friendly_name': 'Mock PA Tilt Window Covering Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mock_pa_tilt_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_pa_tilt_window_covering_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_tilt][binary_sensor.mock_tilt_window_covering_configuration_status-entry]
|
||||
# name: test_binary_sensors[window_covering_tilt][binary_sensor.mock_tilt_window_covering_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -2155,7 +2155,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.mock_tilt_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_tilt_window_covering_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -2163,36 +2163,36 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[window_covering_tilt][binary_sensor.mock_tilt_window_covering_configuration_status-state]
|
||||
# name: test_binary_sensors[window_covering_tilt][binary_sensor.mock_tilt_window_covering_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Mock Tilt Window Covering Configuration status',
|
||||
'friendly_name': 'Mock Tilt Window Covering Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.mock_tilt_window_covering_configuration_status',
|
||||
'entity_id': 'binary_sensor.mock_tilt_window_covering_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[zemismart_mt25b][binary_sensor.zemismart_mt25b_roller_motor_configuration_status-entry]
|
||||
# name: test_binary_sensors[zemismart_mt25b][binary_sensor.zemismart_mt25b_roller_motor_problem-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
@@ -2205,7 +2205,7 @@
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.zemismart_mt25b_roller_motor_configuration_status',
|
||||
'entity_id': 'binary_sensor.zemismart_mt25b_roller_motor_problem',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
@@ -2213,29 +2213,29 @@
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Configuration status',
|
||||
'object_id_base': 'Problem',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Configuration status',
|
||||
'original_name': 'Problem',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'config_status_operational',
|
||||
'translation_key': None,
|
||||
'unique_id': '00000000000004D2-000000000000007A-MatterNodeDevice-1-WindowCoveringConfigStatusOperational-258-7',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[zemismart_mt25b][binary_sensor.zemismart_mt25b_roller_motor_configuration_status-state]
|
||||
# name: test_binary_sensors[zemismart_mt25b][binary_sensor.zemismart_mt25b_roller_motor_problem-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'problem',
|
||||
'friendly_name': 'Zemismart MT25B Roller Motor Configuration status',
|
||||
'friendly_name': 'Zemismart MT25B Roller Motor Problem',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.zemismart_mt25b_roller_motor_configuration_status',
|
||||
'entity_id': 'binary_sensor.zemismart_mt25b_roller_motor_problem',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
|
||||
@@ -424,9 +424,7 @@ async def test_shutter_problem(
|
||||
) -> None:
|
||||
"""Test shutter problem."""
|
||||
# Eve Shutter default state (ConfigStatus = 9)
|
||||
state = hass.states.get(
|
||||
"binary_sensor.eve_shutter_switch_20eci1701_configuration_status"
|
||||
)
|
||||
state = hass.states.get("binary_sensor.eve_shutter_switch_20eci1701_problem")
|
||||
assert state
|
||||
assert state.state == "off"
|
||||
|
||||
@@ -434,9 +432,7 @@ async def test_shutter_problem(
|
||||
set_node_attribute(matter_node, 1, 258, 7, 8)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
state = hass.states.get(
|
||||
"binary_sensor.eve_shutter_switch_20eci1701_configuration_status"
|
||||
)
|
||||
state = hass.states.get("binary_sensor.eve_shutter_switch_20eci1701_problem")
|
||||
assert state
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
@@ -1647,135 +1647,80 @@
|
||||
'image': 'SuPW',
|
||||
'ingredients': list([
|
||||
dict({
|
||||
'display': '1 130g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'food': None,
|
||||
'is_food': None,
|
||||
'note': '130g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a3adfe78-d157-44d8-98be-9c133e45bb4e',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 1 Vanilla Pod',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '1 Vanilla Pod',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': '41d234d7-c040-48f9-91e6-f4636aebb77b',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 150g softened butter',
|
||||
'food': None,
|
||||
'is_food': None,
|
||||
'note': '150g softened butter',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'f6ce06bf-8b02-43e6-8316-0dc3fb0da0fc',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 100g Icing sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '100g Icing sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'f7fcd86e-b04b-4e07-b69c-513925811491',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 6 Eggs',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '6 Eggs',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a831fbc3-e2f5-452e-a745-450be8b4a130',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 100g Castor sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '100g Castor sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'b5ee4bdc-0047-4de7-968b-f3360bbcb31e',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 140g Plain wheat flour',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '140g Plain wheat flour',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a67db09d-429c-4e77-919d-cfed3da675ad',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 200g apricot jam',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '200g apricot jam',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': '55479752-c062-4b25-aae3-2b210999d7b9',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 200g castor sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '200g castor sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'ff9cd404-24ec-4d38-b0aa-0120ce1df679',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 150g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '150g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'c7fca92e-971e-4728-a227-8b04783583ed',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 Unsweetend whipped cream to garnish',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': 'Unsweetend whipped cream to garnish',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'ef023f23-7816-4871-87f6-4d29f9a283f7',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
]),
|
||||
@@ -2278,135 +2223,80 @@
|
||||
'image': 'SuPW',
|
||||
'ingredients': list([
|
||||
dict({
|
||||
'display': '1 130g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'food': None,
|
||||
'is_food': None,
|
||||
'note': '130g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a3adfe78-d157-44d8-98be-9c133e45bb4e',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 1 Vanilla Pod',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '1 Vanilla Pod',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': '41d234d7-c040-48f9-91e6-f4636aebb77b',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 150g softened butter',
|
||||
'food': None,
|
||||
'is_food': None,
|
||||
'note': '150g softened butter',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'f6ce06bf-8b02-43e6-8316-0dc3fb0da0fc',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 100g Icing sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '100g Icing sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'f7fcd86e-b04b-4e07-b69c-513925811491',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 6 Eggs',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '6 Eggs',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a831fbc3-e2f5-452e-a745-450be8b4a130',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 100g Castor sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '100g Castor sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'b5ee4bdc-0047-4de7-968b-f3360bbcb31e',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 140g Plain wheat flour',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '140g Plain wheat flour',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'a67db09d-429c-4e77-919d-cfed3da675ad',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 200g apricot jam',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '200g apricot jam',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': '55479752-c062-4b25-aae3-2b210999d7b9',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 200g castor sugar',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '200g castor sugar',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'ff9cd404-24ec-4d38-b0aa-0120ce1df679',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 150g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': '150g dark couverture chocolate (min. 55% cocoa content)',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'c7fca92e-971e-4728-a227-8b04783583ed',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
dict({
|
||||
'display': '1 Unsweetend whipped cream to garnish',
|
||||
'food': None,
|
||||
'is_food': True,
|
||||
'note': 'Unsweetend whipped cream to garnish',
|
||||
'original_text': None,
|
||||
'quantity': 1.0,
|
||||
'reference_id': 'ef023f23-7816-4871-87f6-4d29f9a283f7',
|
||||
'referenced_recipe': None,
|
||||
'title': None,
|
||||
'unit': None,
|
||||
}),
|
||||
]),
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
@@ -10,6 +12,7 @@ from . import MAC, setup_mock_device
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_migrate_camera_entities_unique_ids(hass: HomeAssistant) -> None:
|
||||
"""Test that camera entities unique ids get migrated properly."""
|
||||
config_entry = MockConfigEntry(domain="onvif", unique_id=MAC)
|
||||
|
||||
@@ -21,6 +21,7 @@ START_DATE = date(2025, 10, 4)
|
||||
END_DATE = date(2025, 10, 5)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"pickup_name",
|
||||
|
||||
@@ -35,14 +35,6 @@ MOCK_USER_REAUTH = {
|
||||
CONF_PASSWORD: "new_password",
|
||||
}
|
||||
|
||||
MOCK_USER_RECONFIGURE = {
|
||||
CONF_HOST: "1.1.1.2",
|
||||
CONF_SSL: True,
|
||||
CONF_VERIFY_SSL: False,
|
||||
CONF_GROUP: "user",
|
||||
}
|
||||
|
||||
|
||||
MOCK_DHCP_DISCOVERY_INPUT = {
|
||||
CONF_SSL: True,
|
||||
CONF_VERIFY_SSL: False,
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pysma import SmaAuthenticationException, SmaConnectionException, SmaReadException
|
||||
from pysma.helpers import DeviceInfo
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.sma.const import CONF_GROUP, DOMAIN
|
||||
from homeassistant.components.sma.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER
|
||||
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_SSL, CONF_VERIFY_SSL
|
||||
from homeassistant.const import CONF_MAC
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
@@ -20,7 +19,6 @@ from . import (
|
||||
MOCK_DHCP_DISCOVERY_INPUT,
|
||||
MOCK_USER_INPUT,
|
||||
MOCK_USER_REAUTH,
|
||||
MOCK_USER_RECONFIGURE,
|
||||
)
|
||||
|
||||
from tests.conftest import MockConfigEntry
|
||||
@@ -313,109 +311,3 @@ async def test_reauth_flow_exceptions(
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "reauth_successful"
|
||||
|
||||
|
||||
async def test_full_flow_reconfigure(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: MockConfigEntry,
|
||||
mock_sma_client: AsyncMock,
|
||||
) -> None:
|
||||
"""Test the full flow of the config flow."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_INPUT, unique_id="123456789")
|
||||
entry.add_to_hass(hass)
|
||||
result = await entry.start_reconfigure_flow(hass)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=MOCK_USER_RECONFIGURE,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "reconfigure_successful"
|
||||
assert entry.data[CONF_HOST] == "1.1.1.2"
|
||||
assert entry.data[CONF_SSL] is True
|
||||
assert entry.data[CONF_VERIFY_SSL] is False
|
||||
assert entry.data[CONF_GROUP] == "user"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "error"),
|
||||
[
|
||||
(SmaConnectionException, "cannot_connect"),
|
||||
(SmaAuthenticationException, "invalid_auth"),
|
||||
(SmaReadException, "cannot_retrieve_device_info"),
|
||||
(Exception, "unknown"),
|
||||
],
|
||||
)
|
||||
async def test_full_flow_reconfigure_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: MockConfigEntry,
|
||||
mock_sma_client: AsyncMock,
|
||||
exception: Exception,
|
||||
error: str,
|
||||
) -> None:
|
||||
"""Test we handle cannot connect error and recover from it."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_INPUT, unique_id="123456789")
|
||||
entry.add_to_hass(hass)
|
||||
result = await entry.start_reconfigure_flow(hass)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure"
|
||||
|
||||
mock_sma_client.new_session.side_effect = exception
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
MOCK_USER_RECONFIGURE,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": error}
|
||||
|
||||
mock_sma_client.new_session.side_effect = None
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=MOCK_USER_RECONFIGURE,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "reconfigure_successful"
|
||||
assert entry.data[CONF_HOST] == "1.1.1.2"
|
||||
assert entry.data[CONF_SSL] is True
|
||||
assert entry.data[CONF_VERIFY_SSL] is False
|
||||
assert entry.data[CONF_GROUP] == "user"
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_reconfigure_mismatch_id(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: MockConfigEntry,
|
||||
mock_sma_client: AsyncMock,
|
||||
) -> None:
|
||||
"""Test when a mismatch happens during reconfigure."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_INPUT, unique_id="123456789")
|
||||
entry.add_to_hass(hass)
|
||||
result = await entry.start_reconfigure_flow(hass)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure"
|
||||
|
||||
# New device, on purpose to demonstrate we can't switch
|
||||
different_device = DeviceInfo(
|
||||
manufacturer="SMA",
|
||||
name="Different SMA Device",
|
||||
type="Sunny Boy 5.0",
|
||||
serial=987654321,
|
||||
sw_version="2.0.0",
|
||||
)
|
||||
mock_sma_client.device_info = AsyncMock(return_value=different_device)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=MOCK_USER_RECONFIGURE,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "unique_id_mismatch"
|
||||
|
||||
@@ -260,6 +260,7 @@ async def test_remove_privacy_zone(
|
||||
assert not doorbell.privacy_zones
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def get_user_keyring_info(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Tests for analytics platform."""
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.analytics import async_devices_payload
|
||||
from homeassistant.components.wled import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -9,6 +11,7 @@ from homeassistant.setup import async_setup_component
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_analytics(
|
||||
hass: HomeAssistant, device_registry: dr.DeviceRegistry
|
||||
) -> None:
|
||||
|
||||
@@ -4,9 +4,8 @@ from copy import deepcopy
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from zwave_js_server.client import Client
|
||||
from zwave_js_server.event import Event
|
||||
from zwave_js_server.model.node import Node, NodeDataType
|
||||
from zwave_js_server.model.node import Node
|
||||
|
||||
from homeassistant.components.zwave_js import DOMAIN
|
||||
from homeassistant.components.zwave_js.const import CONF_KEEP_OLD_DEVICES
|
||||
@@ -24,12 +23,9 @@ from tests.typing import ClientSessionGenerator, WebSocketGenerator
|
||||
|
||||
|
||||
async def _trigger_repair_issue(
|
||||
hass: HomeAssistant,
|
||||
client: Client,
|
||||
multisensor_6_state: NodeDataType,
|
||||
device_config_changed: bool = True,
|
||||
hass: HomeAssistant, client, multisensor_6_state
|
||||
) -> Node:
|
||||
"""Trigger repair issue with configurable device config changed status."""
|
||||
"""Trigger repair issue."""
|
||||
# Create a node
|
||||
node_state = deepcopy(multisensor_6_state)
|
||||
node = Node(client, node_state)
|
||||
@@ -44,7 +40,7 @@ async def _trigger_repair_issue(
|
||||
)
|
||||
with patch(
|
||||
"zwave_js_server.model.node.Node.async_has_device_config_changed",
|
||||
return_value=device_config_changed,
|
||||
return_value=True,
|
||||
):
|
||||
client.driver.controller.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
@@ -59,9 +55,9 @@ async def test_device_config_file_changed_confirm_step(
|
||||
hass_client: ClientSessionGenerator,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
client: Client,
|
||||
multisensor_6_state: NodeDataType,
|
||||
integration: MockConfigEntry,
|
||||
client,
|
||||
multisensor_6_state,
|
||||
integration,
|
||||
) -> None:
|
||||
"""Test the device_config_file_changed issue confirm step."""
|
||||
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
|
||||
@@ -120,54 +116,14 @@ async def test_device_config_file_changed_confirm_step(
|
||||
assert len(msg["result"]["issues"]) == 0
|
||||
|
||||
|
||||
async def test_device_config_file_changed_cleared(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
client: Client,
|
||||
multisensor_6_state: NodeDataType,
|
||||
integration: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the device_config_file_changed issue is cleared when no longer true."""
|
||||
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
|
||||
|
||||
device = device_registry.async_get_device(
|
||||
identifiers={get_device_id(client.driver, node)}
|
||||
)
|
||||
assert device
|
||||
issue_id = f"device_config_file_changed.{device.id}"
|
||||
|
||||
await async_process_repairs_platforms(hass)
|
||||
ws_client = await hass_ws_client(hass)
|
||||
|
||||
# Assert the issue is present
|
||||
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||
msg = await ws_client.receive_json()
|
||||
assert msg["success"]
|
||||
assert len(msg["result"]["issues"]) == 1
|
||||
issue = msg["result"]["issues"][0]
|
||||
assert issue["issue_id"] == issue_id
|
||||
|
||||
# Simulate the node becoming ready again with device config no longer changed
|
||||
await _trigger_repair_issue(
|
||||
hass, client, multisensor_6_state, device_config_changed=False
|
||||
)
|
||||
|
||||
# Assert the issue is now cleared
|
||||
await ws_client.send_json({"id": 2, "type": "repairs/list_issues"})
|
||||
msg = await ws_client.receive_json()
|
||||
assert msg["success"]
|
||||
assert len(msg["result"]["issues"]) == 0
|
||||
|
||||
|
||||
async def test_device_config_file_changed_ignore_step(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
client: Client,
|
||||
multisensor_6_state: NodeDataType,
|
||||
integration: MockConfigEntry,
|
||||
client,
|
||||
multisensor_6_state,
|
||||
integration,
|
||||
) -> None:
|
||||
"""Test the device_config_file_changed issue ignore step."""
|
||||
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
|
||||
@@ -281,9 +237,9 @@ async def test_abort_confirm(
|
||||
hass_client: ClientSessionGenerator,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
client: Client,
|
||||
multisensor_6_state: NodeDataType,
|
||||
integration: MockConfigEntry,
|
||||
client,
|
||||
multisensor_6_state,
|
||||
integration,
|
||||
) -> None:
|
||||
"""Test aborting device_config_file_changed issue in confirm step."""
|
||||
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
|
||||
|
||||
Reference in New Issue
Block a user