Repository: home-assistant/core
File: tests/components/light/test_condition.py (Python)

Code before:
    service_calls: list[ServiceCall],
    target_lights: list[str],
    target_switches: list[str],
    condition_target_config: dict,
    entity_id: str,
    entities_in_target: int,
    condition: str,
    target_state: str,
    other_state: str,
) -> None:
    """Test the light state condition with the 'any' behavior."""
    other_entity_ids = set(target_lights) - {entity_id}

    # Set all lights, including the tested light, to the initial state
    for eid in target_lights:
        set_or_remove_state(hass, eid, other_state)
        await hass.async_block_till_done()

    await setup_automation_with_light_condition(
        hass,
        condition=condition,
        target=condition_target_config,
        behavior="any",
    )

    # Set state for switches to ensure that they don't impact the condition
    for eid in target_switches:
        set_or_remove_state(hass, eid, other_state)
    await hass.async_block_till_done()
    assert not await has_call_after_trigger(hass, service_calls)

    for eid in target_switches:
        set_or_remove_state(hass, eid, target_state)
    await hass.async_block_till_done()
    assert not await has_call_after_trigger(hass, service_calls)

    # Set one light to the condition state -> condition pass
    set_or_remove_state(hass, entity_id, target_state)
    assert await has_call_after_trigger(hass, service_calls)

    # Set all remaining lights to the condition state -> condition pass
    for eid in other_entity_ids:
        set_or_remove_state(hass, eid, target_state)
    assert await has_call_after_trigger(hass, service_calls)

    for invalid_state in INVALID_STATES:
        # Set one light to the invalid state -> condition pass if there are
        # other lights in the condition state
        set_or_remove_state(hass, entity_id, invalid_state)
        assert await has_call_after_trigger(hass, service_calls) == bool(
            entities_in_target - 1

Review comment (suggestion):
the downside of this approach is that if it got 2 calls, this will also pass. I would suggest keeping it as it was here.

maybe keep the old method `calls_after_trigger()`, and make `has_single_call_after_trigger()` just call it too, to that the rest of the test is kept simple.

Code after:
    entities_in_target: int,
    condition: str,
    condition_options: dict[str, Any],
    states: list[ConditionStateDescription],
) -> None:
    """Test the light state condition with the 'any' behavior."""
    other_entity_ids = set(target_lights) - {entity_id}

    # Set all lights, including the tested light, to the initial state
    for eid in target_lights:
        set_or_remove_state(hass, eid, states[0]["included"])
        await hass.async_block_till_done()

    await setup_automation_with_light_condition(
        hass,
        condition=condition,
        target=condition_target_config,
        behavior="any",
    )

    # Set state for switches to ensure that they don't impact the condition
    for state in states:
        for eid in target_switches:
            set_or_remove_state(hass, eid, state["included"])
        await hass.async_block_till_done()
        assert not await has_single_call_after_trigger(hass, service_calls)

    for state in states:
        included_state = state["included"]
        set_or_remove_state(hass, entity_id, included_state)
        await hass.async_block_till_done()
        assert (
            await has_single_call_after_trigger(hass, service_calls)
            == state["condition_true"]
        )

        # Check if changing other lights also passes the condition
        for other_entity_id in other_entity_ids:
            set_or_remove_state(hass, other_entity_id, included_state)
            await hass.async_block_till_done()
        assert (
            await has_single_call_after_trigger(hass, service_calls)
            == state["condition_true"]
        )


@pytest.mark.usefixtures("enable_experimental_triggers_conditions")
@pytest.mark.parametrize(
    ("condition_target_config", "entity_id", "entities_in_target"),
    parametrize_target_entities("light"),
)