Files
core/tests/components/moon/test_trigger.py
T
2026-07-15 16:11:42 +02:00

104 lines
3.4 KiB
Python

"""Tests for the moon triggers."""
from datetime import datetime, timedelta
from typing import Any
from unittest.mock import patch
import pytest
from homeassistant.components import automation
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed
_PHASE = "homeassistant.components.moon.helpers.moon.phase"
@pytest.fixture(autouse=True)
async def setup_moon(hass: HomeAssistant, mock_config_entry: MockConfigEntry) -> None:
"""Set up the moon integration so its trigger platform is available."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
async def _arm(hass: HomeAssistant, options: dict[str, Any] | None = None) -> None:
"""Set up an automation with the moon phase_changed trigger."""
trigger: dict[str, Any] = {"platform": "moon.phase_changed"}
if options is not None:
trigger["options"] = options
await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": trigger,
"action": {
"service": "test.automation",
"data_template": {
"phase": "{{ trigger.phase }}",
"previous_phase": "{{ trigger.previous_phase }}",
},
},
}
},
)
await hass.async_block_till_done()
def _next_local_midnight() -> datetime:
"""Return the next local midnight, when the phase trigger re-evaluates."""
return dt_util.start_of_local_day() + timedelta(days=1)
async def test_phase_changed_fires_on_any_change(
hass: HomeAssistant, service_calls: list[ServiceCall]
) -> None:
"""Test the trigger fires on every phase change when unfiltered."""
with patch(_PHASE, return_value=0.0):
await _arm(hass)
assert len(service_calls) == 0
with patch(_PHASE, return_value=14.0):
async_fire_time_changed(hass, _next_local_midnight())
await hass.async_block_till_done()
assert len(service_calls) == 1
assert service_calls[0].data["phase"] == "full_moon"
assert service_calls[0].data["previous_phase"] == "new_moon"
async def test_phase_changed_ignores_same_phase(
hass: HomeAssistant, service_calls: list[ServiceCall]
) -> None:
"""Test the trigger does not fire when the phase is unchanged."""
with patch(_PHASE, return_value=14.0):
await _arm(hass)
async_fire_time_changed(hass, _next_local_midnight())
await hass.async_block_till_done()
assert len(service_calls) == 0
@pytest.mark.parametrize(
("new_value", "expected_calls"),
[(14.0, 1), (5.0, 0)],
)
async def test_phase_changed_with_phase_filter(
hass: HomeAssistant,
service_calls: list[ServiceCall],
new_value: float,
expected_calls: int,
) -> None:
"""Test the trigger only fires for the configured phase."""
with patch(_PHASE, return_value=0.0):
await _arm(hass, options={"phase": "full_moon"})
with patch(_PHASE, return_value=new_value):
async_fire_time_changed(hass, _next_local_midnight())
await hass.async_block_till_done()
assert len(service_calls) == expected_calls