core/tests/components/nordpool/test_services.py

248 lines
7.0 KiB
Python

"""Test services in Nord Pool."""
import json
from unittest.mock import patch
from pynordpool import (
API,
NordPoolAuthenticationError,
NordPoolEmptyResponseError,
NordPoolError,
)
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.nordpool.const import DOMAIN
from homeassistant.components.nordpool.services import (
ATTR_AREAS,
ATTR_CONFIG_ENTRY,
ATTR_CURRENCY,
ATTR_RESOLUTION,
SERVICE_GET_PRICE_INDICES_FOR_DATE,
SERVICE_GET_PRICES_FOR_DATE,
)
from homeassistant.const import ATTR_DATE
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from tests.common import MockConfigEntry, async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
TEST_SERVICE_DATA = {
ATTR_CONFIG_ENTRY: "to_replace",
ATTR_DATE: "2024-11-05",
ATTR_AREAS: "SE3",
ATTR_CURRENCY: "EUR",
}
TEST_SERVICE_DATA_USE_DEFAULTS = {
ATTR_CONFIG_ENTRY: "to_replace",
ATTR_DATE: "2024-11-05",
}
TEST_SERVICE_INDICES_DATA_60 = {
ATTR_CONFIG_ENTRY: "to_replace",
ATTR_DATE: "2025-07-06",
ATTR_AREAS: "SE3",
ATTR_CURRENCY: "SEK",
ATTR_RESOLUTION: 60,
}
TEST_SERVICE_INDICES_DATA_15 = {
ATTR_CONFIG_ENTRY: "to_replace",
ATTR_DATE: "2025-07-06",
ATTR_AREAS: "SE3",
ATTR_CURRENCY: "SEK",
ATTR_RESOLUTION: 15,
}
@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_service_call(
hass: HomeAssistant,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test get_prices_for_date service call."""
service_data = TEST_SERVICE_DATA.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert response == snapshot
price_value = response["SE3"][0]["price"]
service_data = TEST_SERVICE_DATA_USE_DEFAULTS.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert "SE3" in response
assert response["SE3"][0]["price"] == price_value
@pytest.mark.parametrize(
("error", "key"),
[
(NordPoolAuthenticationError, "authentication_error"),
(NordPoolError, "connection_error"),
],
)
@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_service_call_failures(
hass: HomeAssistant,
load_int: MockConfigEntry,
error: Exception,
key: str,
) -> None:
"""Test get_prices_for_date service call when it fails."""
service_data = TEST_SERVICE_DATA.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
with (
patch(
"homeassistant.components.nordpool.coordinator.NordPoolClient.async_get_delivery_period",
side_effect=error,
),
pytest.raises(ServiceValidationError) as err,
):
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert err.value.translation_key == key
@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_empty_response_returns_empty_list(
hass: HomeAssistant,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test get_prices_for_date service call return empty list for empty response."""
service_data = TEST_SERVICE_DATA.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
with (
patch(
"homeassistant.components.nordpool.coordinator.NordPoolClient.async_get_delivery_period",
side_effect=NordPoolEmptyResponseError,
),
):
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert response == snapshot
@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_service_call_config_entry_bad_state(
hass: HomeAssistant,
load_int: MockConfigEntry,
) -> None:
"""Test get_prices_for_date service call when config entry bad state."""
with pytest.raises(ServiceValidationError) as err:
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
TEST_SERVICE_DATA,
blocking=True,
return_response=True,
)
assert err.value.translation_key == "entry_not_found"
service_data = TEST_SERVICE_DATA.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
await hass.config_entries.async_unload(load_int.entry_id)
await hass.async_block_till_done()
with pytest.raises(ServiceValidationError) as err:
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert err.value.translation_key == "entry_not_loaded"
@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_service_call_for_price_indices(
hass: HomeAssistant,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test get_price_indices_for_date service call."""
fixture_60 = json.loads(await async_load_fixture(hass, "indices_60.json", DOMAIN))
fixture_15 = json.loads(await async_load_fixture(hass, "indices_15.json", DOMAIN))
aioclient_mock.request(
"GET",
url=API + "/DayAheadPriceIndices",
params={
"date": "2025-07-06",
"market": "DayAhead",
"indexNames": "SE3",
"currency": "SEK",
"resolutionInMinutes": "60",
},
json=fixture_60,
)
aioclient_mock.request(
"GET",
url=API + "/DayAheadPriceIndices",
params={
"date": "2025-07-06",
"market": "DayAhead",
"indexNames": "SE3",
"currency": "SEK",
"resolutionInMinutes": "15",
},
json=fixture_15,
)
service_data = TEST_SERVICE_INDICES_DATA_60.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICE_INDICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert response == snapshot(name="get_price_indices_for_date_60")
service_data = TEST_SERVICE_INDICES_DATA_15.copy()
service_data[ATTR_CONFIG_ENTRY] = load_int.entry_id
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICE_INDICES_FOR_DATE,
service_data,
blocking=True,
return_response=True,
)
assert response == snapshot(name="get_price_indices_for_date_15")