mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 22:37:11 +00:00
Fix rainbird entity unique ids (#101168)
* Fix unique ids for rainbird entities * Update entity unique id use based on config entry entity id * Update tests/components/rainbird/test_binary_sensor.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Rename all entity_registry variables * Shorten long comment under line length limits --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
531479bf5b
commit
d7fa98454b
@ -48,8 +48,11 @@ class RainBirdSensor(CoordinatorEntity[RainbirdUpdateCoordinator], BinarySensorE
|
|||||||
"""Initialize the Rain Bird sensor."""
|
"""Initialize the Rain Bird sensor."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
if coordinator.unique_id:
|
||||||
self._attr_device_info = coordinator.device_info
|
self._attr_unique_id = f"{coordinator.unique_id}-{description.key}"
|
||||||
|
self._attr_device_info = coordinator.device_info
|
||||||
|
else:
|
||||||
|
self._attr_name = f"{coordinator.device_name} Rainsensor"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool | None:
|
def is_on(self) -> bool | None:
|
||||||
|
@ -34,8 +34,9 @@ async def async_setup_entry(
|
|||||||
[
|
[
|
||||||
RainBirdCalendarEntity(
|
RainBirdCalendarEntity(
|
||||||
data.schedule_coordinator,
|
data.schedule_coordinator,
|
||||||
data.coordinator.serial_number,
|
data.coordinator.unique_id,
|
||||||
data.coordinator.device_info,
|
data.coordinator.device_info,
|
||||||
|
data.coordinator.device_name,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -47,20 +48,24 @@ class RainBirdCalendarEntity(
|
|||||||
"""A calendar event entity."""
|
"""A calendar event entity."""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
_attr_name = None
|
_attr_name: str | None = None
|
||||||
_attr_icon = "mdi:sprinkler"
|
_attr_icon = "mdi:sprinkler"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: RainbirdScheduleUpdateCoordinator,
|
coordinator: RainbirdScheduleUpdateCoordinator,
|
||||||
serial_number: str,
|
unique_id: str | None,
|
||||||
device_info: DeviceInfo,
|
device_info: DeviceInfo | None,
|
||||||
|
device_name: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create the Calendar event device."""
|
"""Create the Calendar event device."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._event: CalendarEvent | None = None
|
self._event: CalendarEvent | None = None
|
||||||
self._attr_unique_id = serial_number
|
if unique_id:
|
||||||
self._attr_device_info = device_info
|
self._attr_unique_id = unique_id
|
||||||
|
self._attr_device_info = device_info
|
||||||
|
else:
|
||||||
|
self._attr_name = device_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def event(self) -> CalendarEvent | None:
|
def event(self) -> CalendarEvent | None:
|
||||||
|
@ -21,7 +21,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import CONF_SERIAL_NUMBER, DOMAIN, MANUFACTURER, TIMEOUT_SECONDS
|
from .const import DOMAIN, MANUFACTURER, TIMEOUT_SECONDS
|
||||||
|
|
||||||
UPDATE_INTERVAL = datetime.timedelta(minutes=1)
|
UPDATE_INTERVAL = datetime.timedelta(minutes=1)
|
||||||
# The calendar data requires RPCs for each program/zone, and the data rarely
|
# The calendar data requires RPCs for each program/zone, and the data rarely
|
||||||
@ -51,7 +51,7 @@ class RainbirdUpdateCoordinator(DataUpdateCoordinator[RainbirdDeviceState]):
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
name: str,
|
name: str,
|
||||||
controller: AsyncRainbirdController,
|
controller: AsyncRainbirdController,
|
||||||
serial_number: str,
|
unique_id: str | None,
|
||||||
model_info: ModelAndVersion,
|
model_info: ModelAndVersion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize RainbirdUpdateCoordinator."""
|
"""Initialize RainbirdUpdateCoordinator."""
|
||||||
@ -62,7 +62,7 @@ class RainbirdUpdateCoordinator(DataUpdateCoordinator[RainbirdDeviceState]):
|
|||||||
update_interval=UPDATE_INTERVAL,
|
update_interval=UPDATE_INTERVAL,
|
||||||
)
|
)
|
||||||
self._controller = controller
|
self._controller = controller
|
||||||
self._serial_number = serial_number
|
self._unique_id = unique_id
|
||||||
self._zones: set[int] | None = None
|
self._zones: set[int] | None = None
|
||||||
self._model_info = model_info
|
self._model_info = model_info
|
||||||
|
|
||||||
@ -72,16 +72,23 @@ class RainbirdUpdateCoordinator(DataUpdateCoordinator[RainbirdDeviceState]):
|
|||||||
return self._controller
|
return self._controller
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serial_number(self) -> str:
|
def unique_id(self) -> str | None:
|
||||||
"""Return the device serial number."""
|
"""Return the config entry unique id."""
|
||||||
return self._serial_number
|
return self._unique_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_name(self) -> str:
|
||||||
|
"""Device name for the rainbird controller."""
|
||||||
|
return f"{MANUFACTURER} Controller"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self) -> DeviceInfo | None:
|
||||||
"""Return information about the device."""
|
"""Return information about the device."""
|
||||||
|
if not self._unique_id:
|
||||||
|
return None
|
||||||
return DeviceInfo(
|
return DeviceInfo(
|
||||||
name=f"{MANUFACTURER} Controller",
|
name=self.device_name,
|
||||||
identifiers={(DOMAIN, self._serial_number)},
|
identifiers={(DOMAIN, self._unique_id)},
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
model=self._model_info.model_name,
|
model=self._model_info.model_name,
|
||||||
sw_version=f"{self._model_info.major}.{self._model_info.minor}",
|
sw_version=f"{self._model_info.major}.{self._model_info.minor}",
|
||||||
@ -164,7 +171,7 @@ class RainbirdData:
|
|||||||
self.hass,
|
self.hass,
|
||||||
name=self.entry.title,
|
name=self.entry.title,
|
||||||
controller=self.controller,
|
controller=self.controller,
|
||||||
serial_number=self.entry.data[CONF_SERIAL_NUMBER],
|
unique_id=self.entry.unique_id,
|
||||||
model_info=self.model_info,
|
model_info=self.model_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,8 +51,11 @@ class RainDelayNumber(CoordinatorEntity[RainbirdUpdateCoordinator], NumberEntity
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the Rain Bird sensor."""
|
"""Initialize the Rain Bird sensor."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._attr_unique_id = f"{coordinator.serial_number}-rain-delay"
|
if coordinator.unique_id:
|
||||||
self._attr_device_info = coordinator.device_info
|
self._attr_unique_id = f"{coordinator.unique_id}-rain-delay"
|
||||||
|
self._attr_device_info = coordinator.device_info
|
||||||
|
else:
|
||||||
|
self._attr_name = f"{coordinator.device_name} Rain delay"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> float | None:
|
def native_value(self) -> float | None:
|
||||||
|
@ -52,8 +52,13 @@ class RainBirdSensor(CoordinatorEntity[RainbirdUpdateCoordinator], SensorEntity)
|
|||||||
"""Initialize the Rain Bird sensor."""
|
"""Initialize the Rain Bird sensor."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
if coordinator.unique_id:
|
||||||
self._attr_device_info = coordinator.device_info
|
self._attr_unique_id = f"{coordinator.unique_id}-{description.key}"
|
||||||
|
self._attr_device_info = coordinator.device_info
|
||||||
|
else:
|
||||||
|
self._attr_name = (
|
||||||
|
f"{coordinator.device_name} {description.key.capitalize()}"
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> StateType:
|
def native_value(self) -> StateType:
|
||||||
|
@ -65,20 +65,23 @@ class RainBirdSwitch(CoordinatorEntity[RainbirdUpdateCoordinator], SwitchEntity)
|
|||||||
"""Initialize a Rain Bird Switch Device."""
|
"""Initialize a Rain Bird Switch Device."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._zone = zone
|
self._zone = zone
|
||||||
|
if coordinator.unique_id:
|
||||||
|
self._attr_unique_id = f"{coordinator.unique_id}-{zone}"
|
||||||
|
device_name = f"{MANUFACTURER} Sprinkler {zone}"
|
||||||
if imported_name:
|
if imported_name:
|
||||||
self._attr_name = imported_name
|
self._attr_name = imported_name
|
||||||
self._attr_has_entity_name = False
|
self._attr_has_entity_name = False
|
||||||
else:
|
else:
|
||||||
self._attr_name = None
|
self._attr_name = None if coordinator.unique_id else device_name
|
||||||
self._attr_has_entity_name = True
|
self._attr_has_entity_name = True
|
||||||
self._duration_minutes = duration_minutes
|
self._duration_minutes = duration_minutes
|
||||||
self._attr_unique_id = f"{coordinator.serial_number}-{zone}"
|
if coordinator.unique_id and self._attr_unique_id:
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
name=f"{MANUFACTURER} Sprinkler {zone}",
|
name=device_name,
|
||||||
identifiers={(DOMAIN, self._attr_unique_id)},
|
identifiers={(DOMAIN, self._attr_unique_id)},
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
via_device=(DOMAIN, coordinator.serial_number),
|
via_device=(DOMAIN, coordinator.unique_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self):
|
def extra_state_attributes(self):
|
||||||
|
@ -86,7 +86,7 @@ def yaml_config() -> dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
async def unique_id() -> str:
|
async def config_entry_unique_id() -> str:
|
||||||
"""Fixture for serial number used in the config entry."""
|
"""Fixture for serial number used in the config entry."""
|
||||||
return SERIAL_NUMBER
|
return SERIAL_NUMBER
|
||||||
|
|
||||||
@ -100,13 +100,13 @@ async def config_entry_data() -> dict[str, Any]:
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
async def config_entry(
|
async def config_entry(
|
||||||
config_entry_data: dict[str, Any] | None,
|
config_entry_data: dict[str, Any] | None,
|
||||||
unique_id: str,
|
config_entry_unique_id: str | None,
|
||||||
) -> MockConfigEntry | None:
|
) -> MockConfigEntry | None:
|
||||||
"""Fixture for MockConfigEntry."""
|
"""Fixture for MockConfigEntry."""
|
||||||
if config_entry_data is None:
|
if config_entry_data is None:
|
||||||
return None
|
return None
|
||||||
return MockConfigEntry(
|
return MockConfigEntry(
|
||||||
unique_id=unique_id,
|
unique_id=config_entry_unique_id,
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
data=config_entry_data,
|
data=config_entry_data,
|
||||||
options={ATTR_DURATION: DEFAULT_TRIGGER_TIME_MINUTES},
|
options={ATTR_DURATION: DEFAULT_TRIGGER_TIME_MINUTES},
|
||||||
|
@ -5,6 +5,7 @@ import pytest
|
|||||||
|
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from .conftest import RAIN_SENSOR_OFF, RAIN_SENSOR_ON, ComponentSetup
|
from .conftest import RAIN_SENSOR_OFF, RAIN_SENSOR_ON, ComponentSetup
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ async def test_rainsensor(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_integration: ComponentSetup,
|
setup_integration: ComponentSetup,
|
||||||
responses: list[AiohttpClientMockResponse],
|
responses: list[AiohttpClientMockResponse],
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
expected_state: bool,
|
expected_state: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test rainsensor binary sensor."""
|
"""Test rainsensor binary sensor."""
|
||||||
@ -38,3 +40,37 @@ async def test_rainsensor(
|
|||||||
"friendly_name": "Rain Bird Controller Rainsensor",
|
"friendly_name": "Rain Bird Controller Rainsensor",
|
||||||
"icon": "mdi:water",
|
"icon": "mdi:water",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get(
|
||||||
|
"binary_sensor.rain_bird_controller_rainsensor"
|
||||||
|
)
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.unique_id == "1263613994342-rainsensor"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config_entry_unique_id"),
|
||||||
|
[
|
||||||
|
(None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_no_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
responses: list[AiohttpClientMockResponse],
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test rainsensor binary sensor with no unique id."""
|
||||||
|
|
||||||
|
assert await setup_integration()
|
||||||
|
|
||||||
|
rainsensor = hass.states.get("binary_sensor.rain_bird_controller_rainsensor")
|
||||||
|
assert rainsensor is not None
|
||||||
|
assert (
|
||||||
|
rainsensor.attributes.get("friendly_name") == "Rain Bird Controller Rainsensor"
|
||||||
|
)
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get(
|
||||||
|
"binary_sensor.rain_bird_controller_rainsensor"
|
||||||
|
)
|
||||||
|
assert not entity_entry
|
||||||
|
@ -14,6 +14,7 @@ import pytest
|
|||||||
|
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from .conftest import ComponentSetup, mock_response, mock_response_error
|
from .conftest import ComponentSetup, mock_response, mock_response_error
|
||||||
|
|
||||||
@ -176,6 +177,7 @@ async def test_event_state(
|
|||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
freeze_time: datetime.datetime,
|
freeze_time: datetime.datetime,
|
||||||
expected_state: str,
|
expected_state: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test calendar upcoming event state."""
|
"""Test calendar upcoming event state."""
|
||||||
freezer.move_to(freeze_time)
|
freezer.move_to(freeze_time)
|
||||||
@ -196,6 +198,10 @@ async def test_event_state(
|
|||||||
}
|
}
|
||||||
assert state.state == expected_state
|
assert state.state == expected_state
|
||||||
|
|
||||||
|
entity = entity_registry.async_get(TEST_ENTITY)
|
||||||
|
assert entity
|
||||||
|
assert entity.unique_id == 1263613994342
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("model_and_version_response", "has_entity"),
|
("model_and_version_response", "has_entity"),
|
||||||
@ -270,3 +276,27 @@ async def test_program_schedule_disabled(
|
|||||||
"friendly_name": "Rain Bird Controller",
|
"friendly_name": "Rain Bird Controller",
|
||||||
"icon": "mdi:sprinkler",
|
"icon": "mdi:sprinkler",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config_entry_unique_id"),
|
||||||
|
[
|
||||||
|
(None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_no_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
get_events: GetEventsFn,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test calendar entity with no unique id."""
|
||||||
|
|
||||||
|
assert await setup_integration()
|
||||||
|
|
||||||
|
state = hass.states.get(TEST_ENTITY)
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes.get("friendly_name") == "Rain Bird Controller"
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get(TEST_ENTITY)
|
||||||
|
assert not entity_entry
|
||||||
|
@ -106,7 +106,7 @@ async def test_controller_flow(
|
|||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"unique_id",
|
"config_entry_unique_id",
|
||||||
"config_entry_data",
|
"config_entry_data",
|
||||||
"config_flow_responses",
|
"config_flow_responses",
|
||||||
"expected_config_entry",
|
"expected_config_entry",
|
||||||
@ -154,7 +154,7 @@ async def test_multiple_config_entries(
|
|||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"unique_id",
|
"config_entry_unique_id",
|
||||||
"config_entry_data",
|
"config_entry_data",
|
||||||
"config_flow_responses",
|
"config_flow_responses",
|
||||||
),
|
),
|
||||||
|
@ -10,7 +10,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
ACK_ECHO,
|
ACK_ECHO,
|
||||||
@ -39,8 +39,9 @@ async def test_number_values(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_integration: ComponentSetup,
|
setup_integration: ComponentSetup,
|
||||||
expected_state: str,
|
expected_state: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test sensor platform."""
|
"""Test number platform."""
|
||||||
|
|
||||||
assert await setup_integration()
|
assert await setup_integration()
|
||||||
|
|
||||||
@ -57,6 +58,10 @@ async def test_number_values(
|
|||||||
"unit_of_measurement": "d",
|
"unit_of_measurement": "d",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("number.rain_bird_controller_rain_delay")
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.unique_id == "1263613994342-rain-delay"
|
||||||
|
|
||||||
|
|
||||||
async def test_set_value(
|
async def test_set_value(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -127,3 +132,28 @@ async def test_set_value_error(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert len(aioclient_mock.mock_calls) == 1
|
assert len(aioclient_mock.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config_entry_unique_id"),
|
||||||
|
[
|
||||||
|
(None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_no_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test number platform with no unique id."""
|
||||||
|
|
||||||
|
assert await setup_integration()
|
||||||
|
|
||||||
|
raindelay = hass.states.get("number.rain_bird_controller_rain_delay")
|
||||||
|
assert raindelay is not None
|
||||||
|
assert (
|
||||||
|
raindelay.attributes.get("friendly_name") == "Rain Bird Controller Rain delay"
|
||||||
|
)
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("number.rain_bird_controller_rain_delay")
|
||||||
|
assert not entity_entry
|
||||||
|
@ -5,8 +5,9 @@ import pytest
|
|||||||
|
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from .conftest import RAIN_DELAY, RAIN_DELAY_OFF, ComponentSetup
|
from .conftest import CONFIG_ENTRY_DATA, RAIN_DELAY, RAIN_DELAY_OFF, ComponentSetup
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -22,6 +23,7 @@ def platforms() -> list[str]:
|
|||||||
async def test_sensors(
|
async def test_sensors(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_integration: ComponentSetup,
|
setup_integration: ComponentSetup,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
expected_state: str,
|
expected_state: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test sensor platform."""
|
"""Test sensor platform."""
|
||||||
@ -35,3 +37,46 @@ async def test_sensors(
|
|||||||
"friendly_name": "Rain Bird Controller Raindelay",
|
"friendly_name": "Rain Bird Controller Raindelay",
|
||||||
"icon": "mdi:water-off",
|
"icon": "mdi:water-off",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("sensor.rain_bird_controller_raindelay")
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.unique_id == "1263613994342-raindelay"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config_entry_unique_id", "config_entry_data"),
|
||||||
|
[
|
||||||
|
# Config entry setup without a unique id since it had no serial number
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
{
|
||||||
|
**CONFIG_ENTRY_DATA,
|
||||||
|
"serial_number": 0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
# Legacy case for old config entries with serial number 0 preserves old behavior
|
||||||
|
(
|
||||||
|
"0",
|
||||||
|
{
|
||||||
|
**CONFIG_ENTRY_DATA,
|
||||||
|
"serial_number": 0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_sensor_no_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
config_entry_unique_id: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test sensor platform with no unique id."""
|
||||||
|
|
||||||
|
assert await setup_integration()
|
||||||
|
|
||||||
|
raindelay = hass.states.get("sensor.rain_bird_controller_raindelay")
|
||||||
|
assert raindelay is not None
|
||||||
|
assert raindelay.attributes.get("friendly_name") == "Rain Bird Controller Raindelay"
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("sensor.rain_bird_controller_raindelay")
|
||||||
|
assert (entity_entry is None) == (config_entry_unique_id is None)
|
||||||
|
@ -8,6 +8,7 @@ from homeassistant.components.rainbird import DOMAIN
|
|||||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
ACK_ECHO,
|
ACK_ECHO,
|
||||||
@ -57,6 +58,7 @@ async def test_no_zones(
|
|||||||
async def test_zones(
|
async def test_zones(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_integration: ComponentSetup,
|
setup_integration: ComponentSetup,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test switch platform with fake data that creates 7 zones with one enabled."""
|
"""Test switch platform with fake data that creates 7 zones with one enabled."""
|
||||||
|
|
||||||
@ -100,6 +102,10 @@ async def test_zones(
|
|||||||
|
|
||||||
assert not hass.states.get("switch.rain_bird_sprinkler_8")
|
assert not hass.states.get("switch.rain_bird_sprinkler_8")
|
||||||
|
|
||||||
|
# Verify unique id for one of the switches
|
||||||
|
entity_entry = entity_registry.async_get("switch.rain_bird_sprinkler_3")
|
||||||
|
assert entity_entry.unique_id == "1263613994342-3"
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_on(
|
async def test_switch_on(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -275,3 +281,29 @@ async def test_switch_error(
|
|||||||
with pytest.raises(HomeAssistantError, match=expected_msg):
|
with pytest.raises(HomeAssistantError, match=expected_msg):
|
||||||
await switch_common.async_turn_off(hass, "switch.rain_bird_sprinkler_3")
|
await switch_common.async_turn_off(hass, "switch.rain_bird_sprinkler_3")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config_entry_unique_id"),
|
||||||
|
[
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_no_unique_id(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
responses: list[AiohttpClientMockResponse],
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test an irrigation switch with no unique id."""
|
||||||
|
|
||||||
|
assert await setup_integration()
|
||||||
|
|
||||||
|
zone = hass.states.get("switch.rain_bird_sprinkler_3")
|
||||||
|
assert zone is not None
|
||||||
|
assert zone.attributes.get("friendly_name") == "Rain Bird Sprinkler 3"
|
||||||
|
assert zone.state == "off"
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("switch.rain_bird_sprinkler_3")
|
||||||
|
assert entity_entry is None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user