Files
core/tests/components/shelly/__init__.py
Maciej Bieniek 7f4cc99a3e Use sub-devices for Shelly multi-channel devices (#144100)
* Shelly RPC sub-devices

* Better varaible name

* Add get_rpc_device_info helper

* Revert channel name changes

* Use get_rpc_device_info

* Add get_rpc_device_info helper

* Use get_block_device_info

* Use helpers in the button platform

* Fix channel name and roller mode for block devices

* Fix EM3 gen1

* Fix channel name for RPC devices

* Revert test changes

* Fix/improve test_block_get_block_channel_name

* Fix test_get_rpc_channel_name_multiple_components

* Fix tests

* Fix tests

* Fix tests

* Use key instead of index to generate sub-device identifier

* Improve logic for Pro RGBWW PM

* Split channels for em1

* Better channel name

* Cleaning

* has_entity_name is True

* Add get_block_sub_device_name() function

* Improve block functions

* Add get_rpc_sub_device_name() function

* Remove _attr_name

* Remove name for button with device class

* Fix names of virtual components

* Better Input name

* Fix get_rpc_channel_name()

* Fix names for Inputs

* get_rpc_channel_name() improvement

* Better variable name

* Clean RPC functions

* Fix input_name type

* Fix test

* Fix entity_ids for Blu Trv

* Fix get_block_channel_name()

* Fix for Blu Trv, once again

* Revert name for reboot button

* Fix button tests

* Fix tests

* Fix coordinator tests

* Fix tests for cover platform

* Fix tests for event platform

* Fix entity_ids in init tests

* Fix get_block_channel_name() for lights

* Fix tests for light platform

* Fix test for logbook

* Update snapshots for number platform

* Fix tests for sensor platform

* Fix tests for switch platform

* Fix tests for utils

* Uncomment

* Fix tests for flood

* Fix Valve entity name

* Fix climate tests

* Fix test for diagnostics

* Fix tests for init

* Remove old snapshots

* Add tests for 2PM Gen3

* Add comment

* More tests

* Cleaning

* Clean fixtures

* Update tests

* Anonymize coordinates in fixtures

* Split Pro 3EM entities into sub-devices

* Make sub-device names more unique

* 3EM (gen1) does not support sub-devices

* Coverage

* Rename "device temperature" sensor to the "relay temperature"

* Update tests after rebase

* Support sub-devices for 3EM (gen1)

* Mark has-entity-name rule as done 🎉

* Rename `relay temperature` to `temperature`
2025-05-26 10:47:22 +02:00

154 lines
4.1 KiB
Python

"""Tests for the Shelly integration."""
from collections.abc import Mapping
from copy import deepcopy
from datetime import timedelta
from typing import Any
from unittest.mock import Mock
from aioshelly.const import MODEL_25
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.shelly.const import (
CONF_GEN,
CONF_SLEEP_PERIOD,
DOMAIN,
REST_SENSORS_UPDATE_INTERVAL,
RPC_SENSORS_POLLING_INTERVAL,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MODEL
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
DeviceEntry,
DeviceRegistry,
format_mac,
)
from tests.common import MockConfigEntry, async_fire_time_changed
MOCK_MAC = "123456789ABC"
async def init_integration(
hass: HomeAssistant,
gen: int | None,
model=MODEL_25,
sleep_period=0,
options: dict[str, Any] | None = None,
skip_setup: bool = False,
data: dict[str, Any] | None = None,
) -> MockConfigEntry:
"""Set up the Shelly integration in Home Assistant."""
if data is None:
data = {
CONF_HOST: "192.168.1.37",
CONF_SLEEP_PERIOD: sleep_period,
CONF_MODEL: model,
}
if gen is not None:
data[CONF_GEN] = gen
entry = MockConfigEntry(
domain=DOMAIN, data=data, unique_id=MOCK_MAC, options=options, title="Test name"
)
entry.add_to_hass(hass)
if not skip_setup:
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
return entry
def mutate_rpc_device_status(
monkeypatch: pytest.MonkeyPatch,
mock_rpc_device: Mock,
top_level_key: str,
key: str,
value: Any,
) -> None:
"""Mutate status for rpc device."""
new_status = deepcopy(mock_rpc_device.status)
new_status[top_level_key][key] = value
monkeypatch.setattr(mock_rpc_device, "status", new_status)
def inject_rpc_device_event(
monkeypatch: pytest.MonkeyPatch,
mock_rpc_device: Mock,
event: Mapping[str, list[dict[str, Any]] | float],
) -> None:
"""Inject event for rpc device."""
monkeypatch.setattr(mock_rpc_device, "event", event)
mock_rpc_device.mock_event()
async def mock_rest_update(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
seconds=REST_SENSORS_UPDATE_INTERVAL,
) -> None:
"""Move time to create REST sensors update event."""
freezer.tick(timedelta(seconds=seconds))
async_fire_time_changed(hass)
await hass.async_block_till_done()
async def mock_polling_rpc_update(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Move time to create polling RPC sensors update event."""
freezer.tick(timedelta(seconds=RPC_SENSORS_POLLING_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
def register_entity(
hass: HomeAssistant,
domain: str,
object_id: str,
unique_id: str,
config_entry: ConfigEntry | None = None,
capabilities: Mapping[str, Any] | None = None,
device_id: str | None = None,
) -> str:
"""Register enabled entity, return entity_id."""
entity_registry = er.async_get(hass)
entity_registry.async_get_or_create(
domain,
DOMAIN,
f"{MOCK_MAC}-{unique_id}",
suggested_object_id=object_id,
disabled_by=None,
config_entry=config_entry,
capabilities=capabilities,
device_id=device_id,
)
return f"{domain}.{object_id}"
def get_entity(
hass: HomeAssistant,
domain: str,
unique_id: str,
) -> str | None:
"""Get Shelly entity."""
entity_registry = er.async_get(hass)
return entity_registry.async_get_entity_id(
domain, DOMAIN, f"{MOCK_MAC}-{unique_id}"
)
def register_device(
device_registry: DeviceRegistry, config_entry: ConfigEntry
) -> DeviceEntry:
"""Register Shelly device."""
return device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, format_mac(MOCK_MAC))},
)