mirror of
https://github.com/home-assistant/core.git
synced 2026-08-09 14:53:57 +01:00
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>
215 lines
6.4 KiB
Python
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"
|