Always setup demo platforms with device support from config entry (#94601)

* Always setup demo platforms with device support from config entry

* Update tests depending on the demo integration
This commit is contained in:
Erik Montnemery 2023-06-14 21:03:07 +02:00 committed by GitHub
parent c5fccffbb3
commit f68ed8b7a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 94 additions and 87 deletions

View File

@ -5,22 +5,19 @@ from typing import Any
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN from . import DOMAIN
async def async_setup_platform( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up the demo switches.""" """Set up the demo switch platform."""
async_add_entities( async_add_entities(
[ [
DemoSwitch("switch1", "Decorative Lights", True, None, True), DemoSwitch("switch1", "Decorative Lights", True, None, True),
@ -36,24 +33,16 @@ async def async_setup_platform(
) )
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Demo config entry."""
await async_setup_platform(hass, {}, async_add_entities)
class DemoSwitch(SwitchEntity): class DemoSwitch(SwitchEntity):
"""Representation of a demo switch.""" """Representation of a demo switch."""
_attr_has_entity_name = True
_attr_should_poll = False _attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
name: str, device_name: str,
state: bool, state: bool,
icon: str | None, icon: str | None,
assumed: bool, assumed: bool,
@ -64,11 +53,10 @@ class DemoSwitch(SwitchEntity):
self._attr_device_class = device_class self._attr_device_class = device_class
self._attr_icon = icon self._attr_icon = icon
self._attr_is_on = state self._attr_is_on = state
self._attr_name = name or DEVICE_DEFAULT_NAME
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)}, identifiers={(DOMAIN, unique_id)},
name=self.name, name=device_name,
) )
def turn_on(self, **kwargs: Any) -> None: def turn_on(self, **kwargs: Any) -> None:

View File

@ -3,40 +3,37 @@ from __future__ import annotations
from homeassistant.components.text import TextEntity, TextMode from homeassistant.components.text import TextEntity, TextMode
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN from . import DOMAIN
async def async_setup_platform( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up the demo Text entity.""" """Set up the Demo text platform."""
async_add_entities( async_add_entities(
[ [
DemoText( DemoText(
unique_id="text", unique_id="text",
name="Text", device_name="Text",
icon=None, icon=None,
native_value="Hello world", native_value="Hello world",
), ),
DemoText( DemoText(
unique_id="password", unique_id="password",
name="Password", device_name="Password",
icon="mdi:text", icon="mdi:text",
native_value="Hello world", native_value="Hello world",
mode=TextMode.PASSWORD, mode=TextMode.PASSWORD,
), ),
DemoText( DemoText(
unique_id="text_1_to_5_char", unique_id="text_1_to_5_char",
name="Text with 1 to 5 characters", device_name="Text with 1 to 5 characters",
icon="mdi:text", icon="mdi:text",
native_value="Hello", native_value="Hello",
native_min=1, native_min=1,
@ -44,7 +41,7 @@ async def async_setup_platform(
), ),
DemoText( DemoText(
unique_id="text_lowercase", unique_id="text_lowercase",
name="Text with only lower case characters", device_name="Text with only lower case characters",
icon="mdi:text", icon="mdi:text",
native_value="world", native_value="world",
pattern=r"[a-z]+", pattern=r"[a-z]+",
@ -53,24 +50,16 @@ async def async_setup_platform(
) )
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Demo config entry."""
await async_setup_platform(hass, {}, async_add_entities)
class DemoText(TextEntity): class DemoText(TextEntity):
"""Representation of a demo text entity.""" """Representation of a demo text entity."""
_attr_has_entity_name = True
_attr_should_poll = False _attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
name: str, device_name: str,
icon: str | None, icon: str | None,
native_value: str | None, native_value: str | None,
mode: TextMode = TextMode.TEXT, mode: TextMode = TextMode.TEXT,
@ -80,7 +69,7 @@ class DemoText(TextEntity):
) -> None: ) -> None:
"""Initialize the Demo text entity.""" """Initialize the Demo text entity."""
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._attr_name = name or DEVICE_DEFAULT_NAME self._attr_name = None
self._attr_native_value = native_value self._attr_native_value = native_value
self._attr_icon = icon self._attr_icon = icon
self._attr_mode = mode self._attr_mode = mode
@ -92,7 +81,7 @@ class DemoText(TextEntity):
self._attr_pattern = pattern self._attr_pattern = pattern
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)}, identifiers={(DOMAIN, unique_id)},
name=name, name=device_name,
) )
async def async_set_value(self, value: str) -> None: async def async_set_value(self, value: str) -> None:

View File

@ -5,43 +5,32 @@ from datetime import time
from homeassistant.components.time import TimeEntity from homeassistant.components.time import TimeEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN from . import DOMAIN
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the Demo time entity."""
async_add_entities([DemoTime("time", "Time", time(12, 0, 0), "mdi:clock", False)])
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Demo config entry.""" """Set up the demo time platform."""
await async_setup_platform(hass, {}, async_add_entities) async_add_entities([DemoTime("time", "Time", time(12, 0, 0), "mdi:clock", False)])
class DemoTime(TimeEntity): class DemoTime(TimeEntity):
"""Representation of a Demo time entity.""" """Representation of a Demo time entity."""
_attr_has_entity_name = True
_attr_should_poll = False _attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
name: str, device_name: str,
state: time, state: time,
icon: str, icon: str,
assumed_state: bool, assumed_state: bool,
@ -49,12 +38,11 @@ class DemoTime(TimeEntity):
"""Initialize the Demo time entity.""" """Initialize the Demo time entity."""
self._attr_assumed_state = assumed_state self._attr_assumed_state = assumed_state
self._attr_icon = icon self._attr_icon = icon
self._attr_name = name or DEVICE_DEFAULT_NAME
self._attr_native_value = state self._attr_native_value = state
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)}, name=self.name identifiers={(DOMAIN, unique_id)}, name=device_name
) )
async def async_set_value(self, value: time) -> None: async def async_set_value(self, value: time) -> None:

View File

@ -10,29 +10,26 @@ from homeassistant.components.update import (
UpdateEntityFeature, UpdateEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN from . import DOMAIN
FAKE_INSTALL_SLEEP_TIME = 0.5 FAKE_INSTALL_SLEEP_TIME = 0.5
async def async_setup_platform( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up demo update entities.""" """Set up demo update platform."""
async_add_entities( async_add_entities(
[ [
DemoUpdate( DemoUpdate(
unique_id="update_no_install", unique_id="update_no_install",
name="Demo Update No Install", device_name="Demo Update No Install",
title="Awesomesoft Inc.", title="Awesomesoft Inc.",
installed_version="1.0.0", installed_version="1.0.0",
latest_version="1.0.1", latest_version="1.0.1",
@ -42,14 +39,14 @@ async def async_setup_platform(
), ),
DemoUpdate( DemoUpdate(
unique_id="update_2_date", unique_id="update_2_date",
name="Demo No Update", device_name="Demo No Update",
title="AdGuard Home", title="AdGuard Home",
installed_version="1.0.0", installed_version="1.0.0",
latest_version="1.0.0", latest_version="1.0.0",
), ),
DemoUpdate( DemoUpdate(
unique_id="update_addon", unique_id="update_addon",
name="Demo add-on", device_name="Demo add-on",
title="AdGuard Home", title="AdGuard Home",
installed_version="1.0.0", installed_version="1.0.0",
latest_version="1.0.1", latest_version="1.0.1",
@ -58,7 +55,7 @@ async def async_setup_platform(
), ),
DemoUpdate( DemoUpdate(
unique_id="update_light_bulb", unique_id="update_light_bulb",
name="Demo Living Room Bulb Update", device_name="Demo Living Room Bulb Update",
title="Philips Lamps Firmware", title="Philips Lamps Firmware",
installed_version="1.93.3", installed_version="1.93.3",
latest_version="1.94.2", latest_version="1.94.2",
@ -68,7 +65,7 @@ async def async_setup_platform(
), ),
DemoUpdate( DemoUpdate(
unique_id="update_support_progress", unique_id="update_support_progress",
name="Demo Update with Progress", device_name="Demo Update with Progress",
title="Philips Lamps Firmware", title="Philips Lamps Firmware",
installed_version="1.93.3", installed_version="1.93.3",
latest_version="1.94.2", latest_version="1.94.2",
@ -82,15 +79,6 @@ async def async_setup_platform(
) )
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Demo config entry."""
await async_setup_platform(hass, {}, async_add_entities)
async def _fake_install() -> None: async def _fake_install() -> None:
"""Fake install an update.""" """Fake install an update."""
await asyncio.sleep(FAKE_INSTALL_SLEEP_TIME) await asyncio.sleep(FAKE_INSTALL_SLEEP_TIME)
@ -99,13 +87,14 @@ async def _fake_install() -> None:
class DemoUpdate(UpdateEntity): class DemoUpdate(UpdateEntity):
"""Representation of a demo update entity.""" """Representation of a demo update entity."""
_attr_has_entity_name = True
_attr_should_poll = False _attr_should_poll = False
def __init__( def __init__(
self, self,
*, *,
unique_id: str, unique_id: str,
name: str, device_name: str,
title: str | None, title: str | None,
installed_version: str | None, installed_version: str | None,
latest_version: str | None, latest_version: str | None,
@ -120,14 +109,13 @@ class DemoUpdate(UpdateEntity):
self._attr_installed_version = installed_version self._attr_installed_version = installed_version
self._attr_device_class = device_class self._attr_device_class = device_class
self._attr_latest_version = latest_version self._attr_latest_version = latest_version
self._attr_name = name or DEVICE_DEFAULT_NAME
self._attr_release_summary = release_summary self._attr_release_summary = release_summary
self._attr_release_url = release_url self._attr_release_url = release_url
self._attr_title = title self._attr_title = title
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)}, identifiers={(DOMAIN, unique_id)},
name=name, name=device_name,
) )
if support_install: if support_install:
self._attr_supported_features |= ( self._attr_supported_features |= (

View File

@ -1,4 +1,6 @@
"""The tests for the demo switch component.""" """The tests for the demo switch component."""
from unittest.mock import patch
import pytest import pytest
from homeassistant.components.demo import DOMAIN from homeassistant.components.demo import DOMAIN
@ -7,15 +9,25 @@ from homeassistant.components.switch import (
SERVICE_TURN_OFF, SERVICE_TURN_OFF,
SERVICE_TURN_ON, SERVICE_TURN_ON,
) )
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
SWITCH_ENTITY_IDS = ["switch.decorative_lights", "switch.ac"] SWITCH_ENTITY_IDS = ["switch.decorative_lights", "switch.ac"]
@pytest.fixture
async def switch_only() -> None:
"""Enable only the switch platform."""
with patch(
"homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM",
[Platform.SWITCH],
):
yield
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
async def setup_comp(hass, disable_platforms): async def setup_comp(hass, switch_only):
"""Set up demo component.""" """Set up demo component."""
assert await async_setup_component( assert await async_setup_component(
hass, SWITCH_DOMAIN, {SWITCH_DOMAIN: {"platform": DOMAIN}} hass, SWITCH_DOMAIN, {SWITCH_DOMAIN: {"platform": DOMAIN}}

View File

@ -1,4 +1,6 @@
"""The tests for the demo text component.""" """The tests for the demo text component."""
from unittest.mock import patch
import pytest import pytest
from homeassistant.components.text import ( from homeassistant.components.text import (
@ -9,15 +11,30 @@ from homeassistant.components.text import (
DOMAIN, DOMAIN,
SERVICE_SET_VALUE, SERVICE_SET_VALUE,
) )
from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODE, MAX_LENGTH_STATE_STATE from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_MODE,
MAX_LENGTH_STATE_STATE,
Platform,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
ENTITY_TEXT = "text.text" ENTITY_TEXT = "text.text"
@pytest.fixture
async def text_only() -> None:
"""Enable only the text platform."""
with patch(
"homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM",
[Platform.TEXT],
):
yield
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
async def setup_demo_text(hass, disable_platforms): async def setup_demo_text(hass, text_only):
"""Initialize setup demo text.""" """Initialize setup demo text."""
assert await async_setup_component(hass, DOMAIN, {"text": {"platform": "demo"}}) assert await async_setup_component(hass, DOMAIN, {"text": {"platform": "demo"}})
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -1,16 +1,28 @@
"""The tests for the demo time component.""" """The tests for the demo time component."""
from unittest.mock import patch
import pytest import pytest
from homeassistant.components.time import ATTR_TIME, DOMAIN, SERVICE_SET_VALUE from homeassistant.components.time import ATTR_TIME, DOMAIN, SERVICE_SET_VALUE
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
ENTITY_TIME = "time.time" ENTITY_TIME = "time.time"
@pytest.fixture
async def time_only() -> None:
"""Enable only the time platform."""
with patch(
"homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM",
[Platform.TIME],
):
yield
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
async def setup_demo_datetime(hass: HomeAssistant, disable_platforms) -> None: async def setup_demo_datetime(hass: HomeAssistant, time_only) -> None:
"""Initialize setup demo time.""" """Initialize setup demo time."""
assert await async_setup_component(hass, DOMAIN, {"time": {"platform": "demo"}}) assert await async_setup_component(hass, DOMAIN, {"time": {"platform": "demo"}})
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -20,14 +20,25 @@ from homeassistant.const import (
ATTR_ENTITY_PICTURE, ATTR_ENTITY_PICTURE,
STATE_OFF, STATE_OFF,
STATE_ON, STATE_ON,
Platform,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@pytest.fixture
async def update_only() -> None:
"""Enable only the update platform."""
with patch(
"homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM",
[Platform.UPDATE],
):
yield
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
async def setup_demo_update(hass: HomeAssistant, disable_platforms) -> None: async def setup_demo_update(hass: HomeAssistant, update_only) -> None:
"""Initialize setup demo update entity.""" """Initialize setup demo update entity."""
assert await async_setup_component(hass, DOMAIN, {"update": {"platform": "demo"}}) assert await async_setup_component(hass, DOMAIN, {"update": {"platform": "demo"}})
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -1054,6 +1054,8 @@ async def test_device_class_switch(
) )
sensor.hass = hass sensor.hass = hass
sensor.entity_id = "switch.demo_sensor" sensor.entity_id = "switch.demo_sensor"
sensor._attr_device_info = None
sensor._attr_name = "Demo Sensor"
sensor.async_write_ha_state() sensor.async_write_ha_state()
result = await sh.async_handle_message( result = await sh.async_handle_message(