Files
core/tests/components/omie/test_services.py
T
Abílio CostaGitHubClaude Opus 4.8copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
9004f3a89a Add get_prices_for_date service action to OMIE (#175820)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-07 15:49:00 +02:00

215 lines
6.4 KiB
Python

"""Test the OMIE - Spain and Portugal electricity prices services."""
import datetime as dt
from unittest.mock import MagicMock
import aiohttp
from pyomie.model import OMIEResults
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.omie.const import DOMAIN
from homeassistant.components.omie.services import (
ATTR_COUNTRIES,
SERVICE_GET_PRICES_FOR_DATE,
)
from homeassistant.const import ATTR_DATE
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from . import setup_integration, spot_price_fetcher
from tests.common import MockConfigEntry
TEST_DATE = "2025-10-15"
TEST_DST_DATE = "2025-10-26"
@pytest.mark.parametrize(
"countries",
[
pytest.param(["es"], id="spain"),
pytest.param(["pt"], id="portugal"),
pytest.param(["es", "pt"], id="both"),
],
)
async def test_get_prices_for_date(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_pyomie: MagicMock,
mock_omie_results_oct15: OMIEResults,
countries: list[str],
snapshot: SnapshotAssertion,
) -> None:
"""Test the get_prices_for_date service response."""
await setup_integration(hass, mock_config_entry)
mock_pyomie.spot_price.side_effect = spot_price_fetcher(
{TEST_DATE: mock_omie_results_oct15}
)
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: TEST_DATE, ATTR_COUNTRIES: countries},
blocking=True,
return_response=True,
)
assert response == snapshot
async def test_get_prices_for_date_default_country(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_pyomie: MagicMock,
mock_omie_results_oct15: OMIEResults,
) -> None:
"""Test the get_prices_for_date service returns both countries by default."""
await setup_integration(hass, mock_config_entry)
mock_pyomie.spot_price.side_effect = spot_price_fetcher(
{TEST_DATE: mock_omie_results_oct15}
)
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: TEST_DATE},
blocking=True,
return_response=True,
)
assert set(response) == {"es", "pt"}
async def test_get_prices_for_date_dst_fall_back(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_pyomie: MagicMock,
mock_omie_results_oct26_dst: OMIEResults,
) -> None:
"""Test interval ends on the 25-hour DST fall-back day."""
await setup_integration(hass, mock_config_entry)
mock_pyomie.spot_price.side_effect = spot_price_fetcher(
{TEST_DST_DATE: mock_omie_results_oct26_dst}
)
response = await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: TEST_DST_DATE, ATTR_COUNTRIES: ["es"]},
blocking=True,
return_response=True,
)
intervals = response["es"]
assert len(intervals) == 100
for interval in intervals:
start = dt.datetime.fromisoformat(interval["start"])
end = dt.datetime.fromisoformat(interval["end"])
assert end - start == dt.timedelta(minutes=15)
last_cest_quarter = next(
interval
for interval in intervals
if interval["start"] == "2025-10-26T02:45:00+02:00"
)
assert last_cest_quarter["end"] == "2025-10-26T02:00:00+01:00"
@pytest.mark.parametrize(
("side_effect", "expected_exception", "expected_translation_key"),
[
pytest.param(
aiohttp.ClientResponseError(
request_info=MagicMock(), history=(), status=404
),
ServiceValidationError,
"data_not_available",
id="not_published_yet",
),
pytest.param(
aiohttp.ClientResponseError(
request_info=MagicMock(), history=(), status=500
),
HomeAssistantError,
"cannot_connect",
id="server_error",
),
pytest.param(
aiohttp.ClientError("Connection error"),
HomeAssistantError,
"cannot_connect",
id="client_error",
),
pytest.param(
TimeoutError(),
HomeAssistantError,
"cannot_connect",
id="timeout",
),
],
)
async def test_get_prices_for_date_errors(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_pyomie: MagicMock,
side_effect: Exception,
expected_exception: type[HomeAssistantError],
expected_translation_key: str,
) -> None:
"""Test the get_prices_for_date service error handling."""
await setup_integration(hass, mock_config_entry)
mock_pyomie.spot_price.side_effect = side_effect
with pytest.raises(expected_exception) as err:
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: TEST_DATE},
blocking=True,
return_response=True,
)
assert err.value.translation_key == expected_translation_key
@pytest.mark.usefixtures("mock_pyomie")
async def test_get_prices_for_date_before_market_start(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the get_prices_for_date service with a date before the market start."""
await setup_integration(hass, mock_config_entry)
with pytest.raises(ServiceValidationError) as err:
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: "2024-01-15"},
blocking=True,
return_response=True,
)
assert err.value.translation_key == "date_before_market_start"
@pytest.mark.usefixtures("mock_pyomie")
async def test_get_prices_for_date_unloaded_config_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the get_prices_for_date service with no loaded config entry."""
await setup_integration(hass, mock_config_entry)
await hass.config_entries.async_unload(mock_config_entry.entry_id)
with pytest.raises(ServiceValidationError) as err:
await hass.services.async_call(
DOMAIN,
SERVICE_GET_PRICES_FOR_DATE,
{ATTR_DATE: TEST_DATE},
blocking=True,
return_response=True,
)
assert err.value.translation_key == "entry_not_loaded"