1
0
mirror of https://github.com/home-assistant/core.git synced 2026-06-02 13:44:32 +01:00
Files
core/tests/components/media_player/test_condition.py
T
2026-05-06 13:15:01 +02:00

314 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Test media player conditions."""
from typing import Any
import pytest
from homeassistant.components.media_player import (
ATTR_MEDIA_VOLUME_LEVEL,
ATTR_MEDIA_VOLUME_MUTED,
)
from homeassistant.components.media_player.const import MediaPlayerState
from homeassistant.core import HomeAssistant
from tests.components.common import (
ConditionStateDescription,
assert_condition_behavior_all,
assert_condition_behavior_any,
assert_condition_gated_by_labs_flag,
assert_condition_options_supported,
other_states,
parametrize_condition_states_all,
parametrize_condition_states_any,
parametrize_numerical_attribute_condition_above_below_all,
parametrize_numerical_attribute_condition_above_below_any,
parametrize_target_entities,
target_entities,
)
# Volume is stored as 0.01.0 but the threshold is in percent.
_VOLUME_VALUE_SCALE = 0.01
_IS_VOLUME_THRESHOLD = {"threshold": {"type": "above", "value": {"number": 50}}}
# is_muted=True states (mute attr True OR volume_level == 0)
_IS_MUTED_STATES = [
(MediaPlayerState.PLAYING, {ATTR_MEDIA_VOLUME_MUTED: True}),
(MediaPlayerState.PLAYING, {ATTR_MEDIA_VOLUME_LEVEL: 0}),
(
MediaPlayerState.PLAYING,
{ATTR_MEDIA_VOLUME_LEVEL: 0, ATTR_MEDIA_VOLUME_MUTED: True},
),
(
MediaPlayerState.PLAYING,
{ATTR_MEDIA_VOLUME_LEVEL: 0, ATTR_MEDIA_VOLUME_MUTED: False},
),
(
MediaPlayerState.PLAYING,
{ATTR_MEDIA_VOLUME_LEVEL: 1, ATTR_MEDIA_VOLUME_MUTED: True},
),
]
# is_muted=False states (mute attr False/missing AND volume_level != 0)
_IS_NOT_MUTED_STATES = [
(MediaPlayerState.PLAYING, {ATTR_MEDIA_VOLUME_MUTED: False}),
(MediaPlayerState.PLAYING, {ATTR_MEDIA_VOLUME_LEVEL: 1}),
(
MediaPlayerState.PLAYING,
{ATTR_MEDIA_VOLUME_LEVEL: 1, ATTR_MEDIA_VOLUME_MUTED: False},
),
]
def parametrize_muted_condition_states_any(
condition: str, target_muted: bool
) -> list[tuple[str, dict[str, Any], list[ConditionStateDescription]]]:
"""Parametrize behavior=any condition states for is_muted/is_unmuted."""
return parametrize_condition_states_any(
condition=condition,
target_states=_IS_MUTED_STATES if target_muted else _IS_NOT_MUTED_STATES,
other_states=_IS_NOT_MUTED_STATES if target_muted else _IS_MUTED_STATES,
extra_excluded_states=[
# State without any volume attributes — filtered by _should_include
MediaPlayerState.PLAYING,
],
)
def parametrize_muted_condition_states_all(
condition: str, target_muted: bool
) -> list[tuple[str, dict[str, Any], list[ConditionStateDescription]]]:
"""Parametrize behavior=all condition states for is_muted/is_unmuted."""
return parametrize_condition_states_all(
condition=condition,
target_states=_IS_MUTED_STATES if target_muted else _IS_NOT_MUTED_STATES,
other_states=_IS_NOT_MUTED_STATES if target_muted else _IS_MUTED_STATES,
extra_excluded_states=[
# State without any volume attributes — filtered by _should_include
MediaPlayerState.PLAYING,
],
)
@pytest.fixture
async def target_media_players(hass: HomeAssistant) -> dict[str, list[str]]:
"""Create multiple media player entities associated with different targets."""
return await target_entities(hass, "media_player")
@pytest.mark.parametrize(
"condition",
[
"media_player.is_muted",
"media_player.is_off",
"media_player.is_on",
"media_player.is_not_playing",
"media_player.is_paused",
"media_player.is_playing",
"media_player.is_unmuted",
"media_player.is_volume",
],
)
async def test_media_player_conditions_gated_by_labs_flag(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, condition: str
) -> None:
"""Test the media player conditions are gated by the labs flag."""
await assert_condition_gated_by_labs_flag(hass, caplog, condition)
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("condition_key", "base_options", "supports_behavior", "supports_duration"),
[
("media_player.is_muted", {}, True, True),
("media_player.is_off", {}, True, True),
("media_player.is_on", {}, True, True),
("media_player.is_not_playing", {}, True, True),
("media_player.is_paused", {}, True, True),
("media_player.is_playing", {}, True, True),
("media_player.is_unmuted", {}, True, True),
("media_player.is_volume", _IS_VOLUME_THRESHOLD, True, True),
],
)
async def test_media_player_condition_options_validation(
hass: HomeAssistant,
condition_key: str,
base_options: dict[str, Any] | None,
supports_behavior: bool,
supports_duration: bool,
) -> None:
"""Test that media_player conditions support the expected options."""
await assert_condition_options_supported(
hass,
condition_key,
base_options,
supports_behavior=supports_behavior,
supports_duration=supports_duration,
)
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("condition_target_config", "entity_id", "entities_in_target"),
parametrize_target_entities("media_player"),
)
@pytest.mark.parametrize(
("condition", "condition_options", "states"),
[
*parametrize_muted_condition_states_any(
"media_player.is_muted", target_muted=True
),
*parametrize_condition_states_any(
condition="media_player.is_off",
target_states=[MediaPlayerState.OFF],
other_states=other_states(MediaPlayerState.OFF),
),
*parametrize_condition_states_any(
condition="media_player.is_on",
target_states=[
MediaPlayerState.BUFFERING,
MediaPlayerState.IDLE,
MediaPlayerState.ON,
MediaPlayerState.PAUSED,
MediaPlayerState.PLAYING,
],
other_states=[MediaPlayerState.OFF],
),
*parametrize_condition_states_any(
condition="media_player.is_not_playing",
target_states=[
MediaPlayerState.BUFFERING,
MediaPlayerState.IDLE,
MediaPlayerState.OFF,
MediaPlayerState.ON,
MediaPlayerState.PAUSED,
],
other_states=[MediaPlayerState.PLAYING],
),
*parametrize_condition_states_any(
condition="media_player.is_paused",
target_states=[MediaPlayerState.PAUSED],
other_states=other_states(MediaPlayerState.PAUSED),
),
*parametrize_condition_states_any(
condition="media_player.is_playing",
target_states=[MediaPlayerState.PLAYING],
other_states=other_states(MediaPlayerState.PLAYING),
),
*parametrize_muted_condition_states_any(
"media_player.is_unmuted", target_muted=False
),
*parametrize_numerical_attribute_condition_above_below_any(
"media_player.is_volume",
MediaPlayerState.PLAYING,
ATTR_MEDIA_VOLUME_LEVEL,
attribute_required=True,
attribute_value_scale=_VOLUME_VALUE_SCALE,
),
],
)
async def test_media_player_state_condition_behavior_any(
hass: HomeAssistant,
target_media_players: dict[str, list[str]],
condition_target_config: dict,
entity_id: str,
entities_in_target: int,
condition: str,
condition_options: dict[str, Any],
states: list[ConditionStateDescription],
) -> None:
"""Test the media player state condition with the 'any' behavior."""
await assert_condition_behavior_any(
hass,
target_entities=target_media_players,
condition_target_config=condition_target_config,
entity_id=entity_id,
entities_in_target=entities_in_target,
condition=condition,
condition_options=condition_options,
states=states,
)
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("condition_target_config", "entity_id", "entities_in_target"),
parametrize_target_entities("media_player"),
)
@pytest.mark.parametrize(
("condition", "condition_options", "states"),
[
*parametrize_muted_condition_states_all(
"media_player.is_muted", target_muted=True
),
*parametrize_condition_states_all(
condition="media_player.is_off",
target_states=[MediaPlayerState.OFF],
other_states=other_states(MediaPlayerState.OFF),
),
*parametrize_condition_states_all(
condition="media_player.is_on",
target_states=[
MediaPlayerState.BUFFERING,
MediaPlayerState.IDLE,
MediaPlayerState.ON,
MediaPlayerState.PAUSED,
MediaPlayerState.PLAYING,
],
other_states=[MediaPlayerState.OFF],
),
*parametrize_condition_states_all(
condition="media_player.is_not_playing",
target_states=[
MediaPlayerState.BUFFERING,
MediaPlayerState.IDLE,
MediaPlayerState.OFF,
MediaPlayerState.ON,
MediaPlayerState.PAUSED,
],
other_states=[MediaPlayerState.PLAYING],
),
*parametrize_condition_states_all(
condition="media_player.is_paused",
target_states=[MediaPlayerState.PAUSED],
other_states=other_states(MediaPlayerState.PAUSED),
),
*parametrize_condition_states_all(
condition="media_player.is_playing",
target_states=[MediaPlayerState.PLAYING],
other_states=other_states(MediaPlayerState.PLAYING),
),
*parametrize_muted_condition_states_all(
"media_player.is_unmuted", target_muted=False
),
*parametrize_numerical_attribute_condition_above_below_all(
"media_player.is_volume",
MediaPlayerState.PLAYING,
ATTR_MEDIA_VOLUME_LEVEL,
attribute_required=True,
attribute_value_scale=_VOLUME_VALUE_SCALE,
),
],
)
async def test_media_player_state_condition_behavior_all(
hass: HomeAssistant,
target_media_players: dict[str, list[str]],
condition_target_config: dict,
entity_id: str,
entities_in_target: int,
condition: str,
condition_options: dict[str, Any],
states: list[ConditionStateDescription],
) -> None:
"""Test the media player state condition with the 'all' behavior."""
await assert_condition_behavior_all(
hass,
target_entities=target_media_players,
condition_target_config=condition_target_config,
entity_id=entity_id,
entities_in_target=entities_in_target,
condition=condition,
condition_options=condition_options,
states=states,
)