diff --git a/homeassistant/components/schedule/__init__.py b/homeassistant/components/schedule/__init__.py index c698993440a..6ad3bcff58e 100644 --- a/homeassistant/components/schedule/__init__.py +++ b/homeassistant/components/schedule/__init__.py @@ -303,7 +303,7 @@ class Schedule(Entity): # Find next event in the schedule, loop over each day (starting with # the current day) until the next event has been found. next_event = None - for day in range(8): # 8 because we need to search same weekday next week + for day in range(8): # 8 because we need to search today's weekday next week day_schedule = self._config.get( WEEKDAY_TO_CONF[(now.weekday() + day) % 7], [] ) diff --git a/tests/components/schedule/test_init.py b/tests/components/schedule/test_init.py index 825bac5686c..5d5de581349 100644 --- a/tests/components/schedule/test_init.py +++ b/tests/components/schedule/test_init.py @@ -34,11 +34,11 @@ from homeassistant.const import ( STATE_OFF, STATE_ON, ) -from homeassistant.core import Context, HomeAssistant +from homeassistant.core import EVENT_STATE_CHANGED, Context, HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component -from tests.common import MockUser, async_fire_time_changed +from tests.common import MockUser, async_capture_events, async_fire_time_changed @pytest.fixture @@ -225,6 +225,88 @@ async def test_events_one_day( assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T07:00:00-07:00" +@pytest.mark.parametrize( + "sun_schedule, mon_schedule", + ( + ( + {CONF_FROM: "23:00:00", CONF_TO: "24:00:00"}, + {CONF_FROM: "00:00:00", CONF_TO: "01:00:00"}, + ), + ), +) +async def test_adjacent( + hass: HomeAssistant, + schedule_setup: Callable[..., Coroutine[Any, Any, bool]], + caplog: pytest.LogCaptureFixture, + sun_schedule: dict[str, str], + mon_schedule: dict[str, str], + freezer, +) -> None: + """Test adjacent events don't toggle on->off->on.""" + freezer.move_to("2022-08-30 13:20:00-07:00") + + assert await schedule_setup( + config={ + DOMAIN: { + "from_yaml": { + CONF_NAME: "from yaml", + CONF_ICON: "mdi:party-popper", + CONF_SUNDAY: sun_schedule, + CONF_MONDAY: mon_schedule, + } + } + }, + items=[], + ) + + state = hass.states.get(f"{DOMAIN}.from_yaml") + assert state + assert state.state == STATE_OFF + assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T23:00:00-07:00" + + state_changes = async_capture_events(hass, EVENT_STATE_CHANGED) + + freezer.move_to(state.attributes[ATTR_NEXT_EVENT]) + async_fire_time_changed(hass) + + state = hass.states.get(f"{DOMAIN}.from_yaml") + assert state + assert state.state == STATE_ON + assert ( + state.attributes[ATTR_NEXT_EVENT].isoformat() + == "2022-09-04T23:59:59.999999-07:00" + ) + + freezer.move_to(state.attributes[ATTR_NEXT_EVENT]) + async_fire_time_changed(hass) + + state = hass.states.get(f"{DOMAIN}.from_yaml") + assert state + assert state.state == STATE_ON + assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T00:00:00-07:00" + + freezer.move_to(state.attributes[ATTR_NEXT_EVENT]) + async_fire_time_changed(hass) + + state = hass.states.get(f"{DOMAIN}.from_yaml") + assert state + assert state.state == STATE_ON + assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T01:00:00-07:00" + + freezer.move_to(state.attributes[ATTR_NEXT_EVENT]) + async_fire_time_changed(hass) + + state = hass.states.get(f"{DOMAIN}.from_yaml") + assert state + assert state.state == STATE_ON + assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T23:00:00-07:00" + + await hass.async_block_till_done() + assert len(state_changes) == 4 + for event in state_changes: + assert event.data["new_state"].state == STATE_ON + + @pytest.mark.parametrize( "schedule", (