async def test_state_change_handlers(hass):
    """Test AdaptiveLightingManager's EVENT_STATE_CHANGED listener.
    ======================
    Sequence of events:
    1. Transition from sleep mode to normal.
    2. Create simulated transition events for that adapt.
    3. Fire all simulated transition events.
    4. Assert all possible problems that would result.
    Also tests significant changes.
    """
    switch, (light, *_) = await setup_lights_and_switch(hass)
    context = switch.create_context("test")  # needs to be passed to update method

    # [Config options]:
    transition_used = 2
    total_events = 5

    async def set_brightness(val: int):
        # 'Unsafe' set but we know what we're doing.
        hass.states.async_set(
            ENTITY_LIGHT_1,
            "on",
            {ATTR_BRIGHTNESS: val, ATTR_SUPPORTED_FEATURES: 1},
        )
        await hass.async_block_till_done()
        # Call code in AdaptiveLightingManager
        hass.bus.async_fire(
            EVENT_STATE_CHANGED,
            {
                "new_state": {
                    ATTR_ENTITY_ID: ENTITY_LIGHT_1,
                    "state": "on",
                    ATTR_BRIGHTNESS: val,
                },
            },
        )
        await hass.async_block_till_done()

    async def turn_light(state, **kwargs):
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_ON if state else SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: ENTITY_LIGHT_1, **kwargs},
            blocking=True,
        )
        await hass.async_block_till_done()

    async def update(force: bool = False):
        await switch._update_attrs_and_maybe_adapt_lights(
            context=context,
            force=force,
            transition=0,
        )
        await hass.async_block_till_done()

    # 1. Adapt to sleep without a transition.
    # Should only be one state change.
    _LOGGER.debug('test_state_change_handling: Turn on "sleep mode"')
    await hass.services.async_call(
        SWITCH_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: ENTITY_SLEEP_MODE_SWITCH},
        blocking=True,
    )
    await hass.async_block_till_done()
    assert switch.manager.our_last_state_on_change.get(ENTITY_LIGHT_1)
    assert len(switch.manager.our_last_state_on_change[ENTITY_LIGHT_1]) == 1
    assert not switch.manager.transition_timers.get(ENTITY_LIGHT_1)
    last_service_data = deepcopy(switch.manager.last_service_data)
    assert last_service_data.get(ENTITY_LIGHT_1)

    # 2 Adapt from sleep with a 'transition'.
    await switch.sleep_mode_switch.async_turn_off()
    await switch._update_attrs_and_maybe_adapt_lights(
        context=context,
        force=False,
        transition=0,
    )
    await hass.async_block_till_done()
    current_service_data = switch.manager.last_service_data
    assert current_service_data != last_service_data

    for light in switch.lights:
        # current_service_data should have changed after the last update.
        assert current_service_data.get(light)
        assert last_service_data.get(light)
        assert current_service_data[light] != last_service_data[light]

        # Test same context id events.
        current_service_data[light][ATTR_TRANSITION] = transition_used
        hass.bus.async_fire(
            EVENT_STATE_CHANGED,
            {
                ATTR_ENTITY_ID: light,
                "old_state": State(light, "on", attributes=last_service_data),
                "new_state": State(
                    light,
                    "on",
                    attributes=current_service_data,
                    context=context,
                ),
            },
        )
        assert not switch.manager.transition_timers.get(light)

        # 2.3 Refire and overwrite the original state_changed event with our 'transition'
        hass.bus.async_fire(
            EVENT_STATE_CHANGED,
            {
                ATTR_ENTITY_ID: light,
                "old_state": State(light, "on", attributes=last_service_data),
                "new_state": State(
                    light,
                    "on",
                    attributes=current_service_data,
                    # We need to overwrite the old context_id
                    context=switch.create_context("test"),
                ),
            },
        )
        await hass.async_block_till_done()
        # Assert our transition timer was created.
        assert switch.manager.transition_timers.get(light)
        # 2.5 Simulate a transition. There's no other way to do this in the demo.
        events = create_transition_events(
            light=light,
            state=hass.states.get(light),
            last=last_service_data[light],
            current=current_service_data[light],
            total_events=total_events,
        )
        # 3. Fire simulated events for our AdaptiveLightingManager
        for event in events:
            _LOGGER.debug("Test EVENT_STATE_CHANGED listener")
            hass.bus.async_fire(EVENT_STATE_CHANGED, event)
            await hass.async_block_till_done()
            # On real systems HA fires transition state changes every ~3 seconds.
            # asyncio.sleep(3)
    # 4. Assert the transition timer started and everything was filled.
    listener = switch.manager
    assert listener.our_last_state_on_change.get(ENTITY_LIGHT_1)
    assert len(listener.our_last_state_on_change[ENTITY_LIGHT_1]) == total_events
    assert listener.transition_timers.get(ENTITY_LIGHT_1)

    # 5. Execute some checks during a transition
    _LOGGER.debug("Test detect_non_ha_changes:")
    switch._take_over_control = True
    assert switch._take_over_control
    switch._detect_non_ha_changes = True
    assert switch._detect_non_ha_changes
    await asyncio.sleep(transition_used / 3)
    # Ensure the timer still exists
    timer = listener.transition_timers.get(ENTITY_LIGHT_1)
    assert timer
    assert timer.is_running()
    last_service_data = deepcopy(current_service_data)
    await update()
    assert not switch.manager.manual_control[ENTITY_LIGHT_1]
    await update()
    assert not switch.manager.manual_control[ENTITY_LIGHT_1]
    timer = listener.transition_timers.get(ENTITY_LIGHT_1)
    assert timer
    assert timer.is_running()
    # Ensure the light did not adapt during the transition.
    assert last_service_data == current_service_data

    # 6. Assert everything after the transition finishes.
    await asyncio.sleep(transition_used)
    assert listener.our_last_state_on_change.get(ENTITY_LIGHT_1)
    assert len(listener.our_last_state_on_change[ENTITY_LIGHT_1]) == total_events
    # Timer should be done and reset now.
    # This is the assert that I can't fix.
    timer = listener.transition_timers.get(ENTITY_LIGHT_1)
    assert not timer or not timer.is_running()

    # build last service data
    await update(force=False)

    # force=True should not reset manual control.
    await turn_light(True, brightness=40)
    await turn_light(True, brightness=20)
    await update(force=False)
    assert switch.manager.manual_control[ENTITY_LIGHT_1]
    await update(force=True)
    assert switch.manager.manual_control[ENTITY_LIGHT_1]

    # turn light off then on should reset manual control.
    await turn_light(False)
    await turn_light(True)
    assert not switch.manager.manual_control[ENTITY_LIGHT_1]

    await turn_light(True, brightness=50)
    _LOGGER.debug("Test: Brightness set to %s", 50)

    # On next update ENTITY_LIGHT_1 should be marked as manually controlled
    await update(force=False)
    assert switch.manager.last_service_data.get(ENTITY_LIGHT_1) is not None
    assert switch.manager.our_last_state_on_change.get(ENTITY_LIGHT_1) is not None
    assert switch.manager.manual_control[ENTITY_LIGHT_1]
Test AdaptiveLightingManager's EVENT_STATE_CHANGED listener.
    ======================
    Sequence of events:
    1. Transition from sleep mode to normal.
    2. Create simulated transition events for that adapt.
    3. Fire all simulated transition events.
    4. Assert all possible problems that would result.
    Also tests significant changes.
    
tests/test_switch.py