Address late seventeentrack review (#116792)

This commit is contained in:
Shai Ungar 2024-06-22 11:46:31 +03:00 committed by GitHub
parent a76fa9f3bf
commit 03aba7e7ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 119 additions and 6 deletions

View File

@ -1,9 +1,13 @@
"""The seventeentrack component.""" """The seventeentrack component."""
from typing import Final
from py17track import Client as SeventeenTrackClient from py17track import Client as SeventeenTrackClient
from py17track.errors import SeventeenTrackError from py17track.errors import SeventeenTrackError
from py17track.package import PACKAGE_STATUS_MAP
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import ( from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_FRIENDLY_NAME,
ATTR_LOCATION, ATTR_LOCATION,
@ -17,8 +21,8 @@ from homeassistant.core import (
ServiceResponse, ServiceResponse,
SupportsResponse, SupportsResponse,
) )
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady, ServiceValidationError
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv, selector
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import slugify from homeassistant.util import slugify
@ -39,6 +43,27 @@ PLATFORMS: list[Platform] = [Platform.SENSOR]
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN) CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
SERVICE_SCHEMA: Final = vol.Schema(
{
vol.Required(ATTR_CONFIG_ENTRY_ID): selector.ConfigEntrySelector(
{
"integration": DOMAIN,
}
),
vol.Optional(ATTR_PACKAGE_STATE): selector.SelectSelector(
selector.SelectSelectorConfig(
multiple=True,
options=[
value.lower().replace(" ", "_")
for value in PACKAGE_STATUS_MAP.values()
],
mode=selector.SelectSelectorMode.DROPDOWN,
translation_key=ATTR_PACKAGE_STATE,
)
),
}
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the 17Track component.""" """Set up the 17Track component."""
@ -47,6 +72,26 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Get packages from 17Track.""" """Get packages from 17Track."""
config_entry_id = call.data[ATTR_CONFIG_ENTRY_ID] config_entry_id = call.data[ATTR_CONFIG_ENTRY_ID]
package_states = call.data.get(ATTR_PACKAGE_STATE, []) package_states = call.data.get(ATTR_PACKAGE_STATE, [])
entry: ConfigEntry | None = hass.config_entries.async_get_entry(config_entry_id)
if not entry:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_config_entry",
translation_placeholders={
"config_entry_id": config_entry_id,
},
)
if entry.state != ConfigEntryState.LOADED:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="unloaded_config_entry",
translation_placeholders={
"config_entry_id": entry.title,
},
)
seventeen_coordinator: SeventeenTrackCoordinator = hass.data[DOMAIN][ seventeen_coordinator: SeventeenTrackCoordinator = hass.data[DOMAIN][
config_entry_id config_entry_id
] ]
@ -75,6 +120,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
DOMAIN, DOMAIN,
SERVICE_GET_PACKAGES, SERVICE_GET_PACKAGES,
get_packages, get_packages,
schema=SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY, supports_response=SupportsResponse.ONLY,
) )
return True return True

View File

@ -18,6 +18,14 @@
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]"
} }
}, },
"exceptions": {
"invalid_config_entry": {
"message": "Invalid config entry provided. Got {config_entry_id}"
},
"unloaded_config_entry": {
"message": "Invalid config entry provided. {config_entry_id} is not loaded."
}
},
"options": { "options": {
"step": { "step": {
"init": { "init": {

View File

@ -2,10 +2,14 @@
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.seventeentrack import DOMAIN, SERVICE_GET_PACKAGES from homeassistant.components.seventeentrack import DOMAIN, SERVICE_GET_PACKAGES
from homeassistant.core import HomeAssistant, SupportsResponse from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
from . import init_integration from . import init_integration
from .conftest import get_package from .conftest import get_package
@ -30,7 +34,7 @@ async def test_get_packages_from_list(
"package_state": ["in_transit", "delivered"], "package_state": ["in_transit", "delivered"],
}, },
blocking=True, blocking=True,
return_response=SupportsResponse.ONLY, return_response=True,
) )
assert service_response == snapshot assert service_response == snapshot
@ -52,12 +56,67 @@ async def test_get_all_packages(
"config_entry_id": mock_config_entry.entry_id, "config_entry_id": mock_config_entry.entry_id,
}, },
blocking=True, blocking=True,
return_response=SupportsResponse.ONLY, return_response=True,
) )
assert service_response == snapshot assert service_response == snapshot
async def test_service_called_with_unloaded_entry(
hass: HomeAssistant,
mock_seventeentrack: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test service call with not ready config entry."""
await init_integration(hass, mock_config_entry)
mock_config_entry.mock_state(hass, ConfigEntryState.SETUP_ERROR)
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PACKAGES,
{
"config_entry_id": mock_config_entry.entry_id,
},
blocking=True,
return_response=True,
)
async def test_service_called_with_non_17track_device(
hass: HomeAssistant,
mock_seventeentrack: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test service calls with non 17Track device."""
await init_integration(hass, mock_config_entry)
other_domain = "Not17Track"
other_config_id = "555"
other_mock_config_entry = MockConfigEntry(
title="Not 17Track", domain=other_domain, entry_id=other_config_id
)
other_mock_config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(
config_entry_id=other_config_id,
identifiers={(other_domain, "1")},
)
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PACKAGES,
{
"config_entry_id": device_entry.id,
},
blocking=True,
return_response=True,
)
async def _mock_packages(mock_seventeentrack): async def _mock_packages(mock_seventeentrack):
package1 = get_package(status=10) package1 = get_package(status=10)
package2 = get_package( package2 = get_package(