Add entity translations to 17track (#116022)

This commit is contained in:
Joost Lekkerkerker 2024-04-23 22:30:20 +02:00 committed by GitHub
parent a22c221722
commit a45040af14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 101 additions and 72 deletions

View file

@ -0,0 +1,30 @@
{
"entity": {
"sensor": {
"not_found": {
"default": "mdi:package"
},
"in_transit": {
"default": "mdi:package"
},
"expired": {
"default": "mdi:package"
},
"ready_to_be_picked_up": {
"default": "mdi:package"
},
"undelivered": {
"default": "mdi:package"
},
"delivered": {
"default": "mdi:package"
},
"returned": {
"default": "mdi:package"
},
"package": {
"default": "mdi:package"
}
}
}
}

View file

@ -18,6 +18,7 @@ from homeassistant.const import (
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
@ -38,7 +39,6 @@ from .const import (
CONF_SHOW_ARCHIVED,
CONF_SHOW_DELIVERED,
DOMAIN,
ENTITY_ID_TEMPLATE,
LOGGER,
NOTIFICATION_DELIVERED_MESSAGE,
NOTIFICATION_DELIVERED_TITLE,
@ -150,7 +150,7 @@ async def async_setup_entry(
)
async_add_entities(
SeventeenTrackSummarySensor(status, summary_data["status_name"], coordinator)
SeventeenTrackSummarySensor(status, coordinator)
for status, summary_data in coordinator.data.summary.items()
)
@ -161,26 +161,37 @@ async def async_setup_entry(
)
class SeventeenTrackSummarySensor(
CoordinatorEntity[SeventeenTrackCoordinator], SensorEntity
):
"""Define a summary sensor."""
class SeventeenTrackSensor(CoordinatorEntity[SeventeenTrackCoordinator], SensorEntity):
"""Define a 17Track sensor."""
_attr_attribution = ATTRIBUTION
_attr_icon = "mdi:package"
_attr_has_entity_name = True
def __init__(self, coordinator: SeventeenTrackCoordinator) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, coordinator.account_id)},
entry_type=DeviceEntryType.SERVICE,
name="17Track",
)
class SeventeenTrackSummarySensor(SeventeenTrackSensor):
"""Define a summary sensor."""
_attr_native_unit_of_measurement = "packages"
def __init__(
self,
status: str,
status_name: str,
coordinator: SeventeenTrackCoordinator,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._status = status
self._attr_name = f"Seventeentrack Packages {status_name}"
self._attr_unique_id = f"summary_{coordinator.account_id}_{self._status}"
self._attr_translation_key = status
self._attr_unique_id = f"summary_{coordinator.account_id}_{status}"
@property
def available(self) -> bool:
@ -211,13 +222,10 @@ class SeventeenTrackSummarySensor(
}
class SeventeenTrackPackageSensor(
CoordinatorEntity[SeventeenTrackCoordinator], SensorEntity
):
class SeventeenTrackPackageSensor(SeventeenTrackSensor):
"""Define an individual package sensor."""
_attr_attribution = ATTRIBUTION
_attr_icon = "mdi:package"
_attr_translation_key = "package"
def __init__(
self,
@ -228,24 +236,19 @@ class SeventeenTrackPackageSensor(
super().__init__(coordinator)
self._tracking_number = tracking_number
self._previous_status = coordinator.data.live_packages[tracking_number].status
self.entity_id = ENTITY_ID_TEMPLATE.format(tracking_number)
self._attr_unique_id = UNIQUE_ID_TEMPLATE.format(
coordinator.account_id, tracking_number
)
package = coordinator.data.live_packages[tracking_number]
if not (name := package.friendly_name):
name = tracking_number
self._attr_translation_placeholders = {"name": name}
@property
def available(self) -> bool:
"""Return whether the entity is available."""
return self._tracking_number in self.coordinator.data.live_packages
@property
def name(self) -> str:
"""Return the name."""
package = self.coordinator.data.live_packages.get(self._tracking_number)
if package is None or not (name := package.friendly_name):
name = self._tracking_number
return f"Seventeentrack Package: {name}"
@property
def native_value(self) -> StateType:
"""Return the state."""

View file

@ -38,5 +38,33 @@
"title": "The 17Track YAML configuration import request failed due to invalid authentication",
"description": "Configuring 17Track using YAML is being removed but there were invalid credentials provided while importing your existing configuration.\nSetup will not proceed.\n\nVerify that your 17Track credentials are correct and restart Home Assistant to attempt the import again.\n\nAlternatively, you may remove the 17Track configuration from your YAML configuration entirely, restart Home Assistant, and add the 17Track integration manually."
}
},
"entity": {
"sensor": {
"not_found": {
"name": "Not found"
},
"in_transit": {
"name": "In transit"
},
"expired": {
"name": "Expired"
},
"ready_to_be_picked_up": {
"name": "Ready to be picked up"
},
"undelivered": {
"name": "Undelivered"
},
"delivered": {
"name": "Delivered"
},
"returned": {
"name": "Returned"
},
"package": {
"name": "Package {name}"
}
}
}
}

View file

@ -75,7 +75,7 @@ async def test_add_package(
mock_seventeentrack.return_value.profile.packages.return_value = [package]
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456")
assert hass.states.get("sensor.17track_package_friendly_name_1")
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
package2 = get_package(
@ -89,7 +89,7 @@ async def test_add_package(
await goto_future(hass, freezer)
assert hass.states.get("sensor.seventeentrack_package_789") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 2
@ -103,9 +103,9 @@ async def test_add_package_default_friendly_name(
mock_seventeentrack.return_value.profile.packages.return_value = [package]
await init_integration(hass, mock_config_entry)
state_456 = hass.states.get("sensor.seventeentrack_package_456")
state_456 = hass.states.get("sensor.17track_package_456")
assert state_456 is not None
assert state_456.attributes["friendly_name"] == "Seventeentrack Package: 456"
assert state_456.attributes["friendly_name"] == "17Track Package 456"
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
@ -132,16 +132,16 @@ async def test_remove_package(
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
assert hass.states.get("sensor.seventeentrack_package_789") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is not None
assert hass.states.get("sensor.17track_package_friendly_name_2") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 2
mock_seventeentrack.return_value.profile.packages.return_value = [package2]
await goto_future(hass, freezer)
assert hass.states.get("sensor.seventeentrack_package_456") is None
assert hass.states.get("sensor.seventeentrack_package_789") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is None
assert hass.states.get("sensor.17track_package_friendly_name_2") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
@ -157,35 +157,7 @@ async def test_package_error(
mock_seventeentrack.return_value.profile.summary.return_value = {}
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456") is None
async def test_friendly_name_changed(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_seventeentrack: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test friendly name change."""
package = get_package()
mock_seventeentrack.return_value.profile.packages.return_value = [package]
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
package = get_package(friendly_name="friendly name 2")
mock_seventeentrack.return_value.profile.packages.return_value = [package]
await goto_future(hass, freezer)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
entity = hass.data["entity_components"]["sensor"].get_entity(
"sensor.seventeentrack_package_456"
)
assert entity.name == "Seventeentrack Package: friendly name 2"
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
assert hass.states.get("sensor.17track_package_friendly_name_1") is None
async def test_delivered_not_shown(
@ -204,7 +176,7 @@ async def test_delivered_not_shown(
await init_integration(hass, mock_config_entry_with_default_options)
await goto_future(hass, freezer)
assert hass.states.get("sensor.seventeentrack_package_456") is None
assert hass.states.get("sensor.17track_package_friendly_name_1") is None
persistent_notification_mock.create.assert_called()
@ -222,7 +194,7 @@ async def test_delivered_shown(
) as persistent_notification_mock:
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
persistent_notification_mock.create.assert_not_called()
@ -239,7 +211,7 @@ async def test_becomes_delivered_not_shown_notification(
await init_integration(hass, mock_config_entry_with_default_options)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
package_delivered = get_package(status=40)
@ -268,9 +240,7 @@ async def test_summary_correctly_updated(
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
state_ready_picked = hass.states.get(
"sensor.seventeentrack_packages_ready_to_be_picked_up"
)
state_ready_picked = hass.states.get("sensor.17track_ready_to_be_picked_up")
assert state_ready_picked is not None
assert len(state_ready_picked.attributes["packages"]) == 1
@ -283,9 +253,7 @@ async def test_summary_correctly_updated(
for state in hass.states.async_all():
assert state.state == "1"
state_ready_picked = hass.states.get(
"sensor.seventeentrack_packages_ready_to_be_picked_up"
)
state_ready_picked = hass.states.get("sensor.17track_ready_to_be_picked_up")
assert state_ready_picked is not None
assert len(state_ready_picked.attributes["packages"]) == 0
@ -323,9 +291,9 @@ async def test_utc_timestamp(
await init_integration(hass, mock_config_entry)
assert hass.states.get("sensor.seventeentrack_package_456") is not None
assert hass.states.get("sensor.17track_package_friendly_name_1") is not None
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
state_456 = hass.states.get("sensor.seventeentrack_package_456")
state_456 = hass.states.get("sensor.17track_package_friendly_name_1")
assert state_456 is not None
assert str(state_456.attributes.get("timestamp")) == "2020-08-10 03:32:00+00:00"