* Mark executor jobs as background unless created from a tracked task If the current task is not tracked the executor job should not be a background task to avoid delaying startup and shutdown. Currently any executor job created in a untracked task or background task would end up being tracked and delaying startup/shutdown * import exec has the same issue * Avoid tracking import executor jobs There is no reason to track these jobs as they are always awaited and we do not want to support fire and forget import executor jobs * fix xiaomi_miio * lots of fire time changed without background await * revert changes moved to other PR * more * more * more * m * m * p * fix fire and forget tests * scrape * sonos * system * more * capture callback before block * coverage * more * more races * more races * more * missed some * more fixes * missed some more * fix * remove unneeded * one more race * two
694 lines
20 KiB
Python
694 lines
20 KiB
Python
"""Test the SoundTouch component."""
|
|
|
|
from datetime import timedelta
|
|
from typing import Any
|
|
|
|
from requests_mock import Mocker
|
|
|
|
from homeassistant.components.media_player import (
|
|
ATTR_INPUT_SOURCE,
|
|
ATTR_MEDIA_ALBUM_NAME,
|
|
ATTR_MEDIA_ARTIST,
|
|
ATTR_MEDIA_CONTENT_ID,
|
|
ATTR_MEDIA_CONTENT_TYPE,
|
|
ATTR_MEDIA_DURATION,
|
|
ATTR_MEDIA_TITLE,
|
|
ATTR_MEDIA_TRACK,
|
|
ATTR_MEDIA_VOLUME_MUTED,
|
|
DOMAIN as MEDIA_PLAYER_DOMAIN,
|
|
)
|
|
from homeassistant.components.soundtouch.const import (
|
|
DOMAIN,
|
|
SERVICE_ADD_ZONE_SLAVE,
|
|
SERVICE_CREATE_ZONE,
|
|
SERVICE_PLAY_EVERYWHERE,
|
|
SERVICE_REMOVE_ZONE_SLAVE,
|
|
)
|
|
from homeassistant.components.soundtouch.media_player import (
|
|
ATTR_SOUNDTOUCH_GROUP,
|
|
ATTR_SOUNDTOUCH_ZONE,
|
|
)
|
|
from homeassistant.config_entries import RELOAD_AFTER_UPDATE_DELAY
|
|
from homeassistant.const import STATE_OFF, STATE_PAUSED, STATE_PLAYING
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from .conftest import DEVICE_1_ENTITY_ID, DEVICE_2_ENTITY_ID
|
|
|
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
|
|
|
|
|
async def setup_soundtouch(hass: HomeAssistant, *mock_entries: MockConfigEntry):
|
|
"""Initialize media_player for tests."""
|
|
assert await async_setup_component(hass, MEDIA_PLAYER_DOMAIN, {})
|
|
|
|
for mock_entry in mock_entries:
|
|
mock_entry.add_to_hass(hass)
|
|
assert await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def _test_key_service(
|
|
hass: HomeAssistant,
|
|
requests_mock_key,
|
|
service: str,
|
|
service_data: dict[str, Any],
|
|
key_name: str,
|
|
):
|
|
"""Test API calls that use the /key endpoint to emulate physical button clicks."""
|
|
requests_mock_key.reset()
|
|
await hass.services.async_call("media_player", service, service_data, True)
|
|
assert requests_mock_key.call_count == 2
|
|
assert f">{key_name}</key>" in requests_mock_key.last_request.text
|
|
|
|
|
|
async def test_playing_media(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
) -> None:
|
|
"""Test playing media info."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_PLAYING
|
|
assert entity_state.attributes[ATTR_MEDIA_TITLE] == "MockArtist - MockTrack"
|
|
assert entity_state.attributes[ATTR_MEDIA_TRACK] == "MockTrack"
|
|
assert entity_state.attributes[ATTR_MEDIA_ARTIST] == "MockArtist"
|
|
assert entity_state.attributes[ATTR_MEDIA_ALBUM_NAME] == "MockAlbum"
|
|
assert entity_state.attributes[ATTR_MEDIA_DURATION] == 42
|
|
|
|
|
|
async def test_playing_radio(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_radio,
|
|
) -> None:
|
|
"""Test playing radio info."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_PLAYING
|
|
assert entity_state.attributes[ATTR_MEDIA_TITLE] == "MockStation"
|
|
|
|
|
|
async def test_playing_aux(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_aux,
|
|
) -> None:
|
|
"""Test playing AUX info."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_PLAYING
|
|
assert entity_state.attributes[ATTR_INPUT_SOURCE] == "AUX"
|
|
|
|
|
|
async def test_playing_bluetooth(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_bluetooth,
|
|
) -> None:
|
|
"""Test playing Bluetooth info."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_PLAYING
|
|
assert entity_state.attributes[ATTR_INPUT_SOURCE] == "BLUETOOTH"
|
|
assert entity_state.attributes[ATTR_MEDIA_TRACK] == "MockTrack"
|
|
assert entity_state.attributes[ATTR_MEDIA_ARTIST] == "MockArtist"
|
|
assert entity_state.attributes[ATTR_MEDIA_ALBUM_NAME] == "MockAlbum"
|
|
|
|
|
|
async def test_get_volume_level(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
) -> None:
|
|
"""Test volume level."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.attributes["volume_level"] == 0.12
|
|
|
|
|
|
async def test_get_state_off(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
) -> None:
|
|
"""Test state device is off."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_OFF
|
|
|
|
|
|
async def test_get_state_pause(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp_paused,
|
|
) -> None:
|
|
"""Test state device is paused."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.state == STATE_PAUSED
|
|
|
|
|
|
async def test_is_muted(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_volume_muted: str,
|
|
) -> None:
|
|
"""Test device volume is muted."""
|
|
with Mocker(real_http=True) as mocker:
|
|
mocker.get("/volume", text=device1_volume_muted)
|
|
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
entity_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_state.attributes[ATTR_MEDIA_VOLUME_MUTED]
|
|
|
|
|
|
async def test_should_turn_off(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test device is turned off."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"turn_off",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"POWER",
|
|
)
|
|
|
|
|
|
async def test_should_turn_on(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test device is turned on."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"turn_on",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"POWER",
|
|
)
|
|
|
|
|
|
async def test_volume_up(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test volume up."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"volume_up",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"VOLUME_UP",
|
|
)
|
|
|
|
|
|
async def test_volume_down(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test volume down."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"volume_down",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"VOLUME_DOWN",
|
|
)
|
|
|
|
|
|
async def test_set_volume_level(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_volume,
|
|
) -> None:
|
|
"""Test set volume level."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert device1_requests_mock_volume.call_count == 0
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"volume_set",
|
|
{"entity_id": DEVICE_1_ENTITY_ID, "volume_level": 0.17},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_volume.call_count == 1
|
|
assert "<volume>17</volume>" in device1_requests_mock_volume.last_request.text
|
|
|
|
|
|
async def test_mute(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test mute volume."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"volume_mute",
|
|
{"entity_id": DEVICE_1_ENTITY_ID, "is_volume_muted": True},
|
|
"MUTE",
|
|
)
|
|
|
|
|
|
async def test_play(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp_paused,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test play command."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"media_play",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"PLAY",
|
|
)
|
|
|
|
|
|
async def test_pause(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test pause command."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"media_pause",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"PAUSE",
|
|
)
|
|
|
|
|
|
async def test_play_pause(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test play/pause."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"media_play_pause",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"PLAY_PAUSE",
|
|
)
|
|
|
|
|
|
async def test_next_previous_track(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_upnp,
|
|
device1_requests_mock_key,
|
|
) -> None:
|
|
"""Test next/previous track."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"media_next_track",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"NEXT_TRACK",
|
|
)
|
|
|
|
await _test_key_service(
|
|
hass,
|
|
device1_requests_mock_key,
|
|
"media_previous_track",
|
|
{"entity_id": DEVICE_1_ENTITY_ID},
|
|
"PREV_TRACK",
|
|
)
|
|
|
|
|
|
async def test_play_media(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_select,
|
|
) -> None:
|
|
"""Test play preset 1."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert device1_requests_mock_select.call_count == 0
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"play_media",
|
|
{
|
|
"entity_id": DEVICE_1_ENTITY_ID,
|
|
ATTR_MEDIA_CONTENT_TYPE: "PLAYLIST",
|
|
ATTR_MEDIA_CONTENT_ID: 1,
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_select.call_count == 1
|
|
assert (
|
|
'location="http://homeassistant:8123/media/local/test.mp3"'
|
|
in device1_requests_mock_select.last_request.text
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"play_media",
|
|
{
|
|
"entity_id": DEVICE_1_ENTITY_ID,
|
|
ATTR_MEDIA_CONTENT_TYPE: "PLAYLIST",
|
|
ATTR_MEDIA_CONTENT_ID: 2,
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_select.call_count == 2
|
|
assert "MockStation" in device1_requests_mock_select.last_request.text
|
|
|
|
|
|
async def test_play_media_url(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_dlna,
|
|
) -> None:
|
|
"""Test play preset 1."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert device1_requests_mock_dlna.call_count == 0
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"play_media",
|
|
{
|
|
"entity_id": DEVICE_1_ENTITY_ID,
|
|
ATTR_MEDIA_CONTENT_TYPE: "MUSIC",
|
|
ATTR_MEDIA_CONTENT_ID: "http://fqdn/file.mp3",
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_dlna.call_count == 1
|
|
assert "http://fqdn/file.mp3" in device1_requests_mock_dlna.last_request.text
|
|
|
|
|
|
async def test_select_source_aux(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_select,
|
|
) -> None:
|
|
"""Test select AUX."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert device1_requests_mock_select.call_count == 0
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"select_source",
|
|
{"entity_id": DEVICE_1_ENTITY_ID, ATTR_INPUT_SOURCE: "AUX"},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_select.call_count == 1
|
|
assert "AUX" in device1_requests_mock_select.last_request.text
|
|
|
|
|
|
async def test_select_source_bluetooth(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_select,
|
|
) -> None:
|
|
"""Test select Bluetooth."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert device1_requests_mock_select.call_count == 0
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"select_source",
|
|
{"entity_id": DEVICE_1_ENTITY_ID, ATTR_INPUT_SOURCE: "BLUETOOTH"},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_select.call_count == 1
|
|
assert "BLUETOOTH" in device1_requests_mock_select.last_request.text
|
|
|
|
|
|
async def test_select_source_invalid_source(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device1_requests_mock_select,
|
|
) -> None:
|
|
"""Test select unsupported source."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
assert not device1_requests_mock_select.called
|
|
await hass.services.async_call(
|
|
"media_player",
|
|
"select_source",
|
|
{
|
|
"entity_id": DEVICE_1_ENTITY_ID,
|
|
ATTR_INPUT_SOURCE: "SOMETHING_UNSUPPORTED",
|
|
},
|
|
True,
|
|
)
|
|
assert not device1_requests_mock_select.called
|
|
|
|
|
|
async def test_play_everywhere(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device2_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device2_requests_mock_standby,
|
|
device1_requests_mock_set_zone,
|
|
) -> None:
|
|
"""Test play everywhere."""
|
|
await setup_soundtouch(hass, device1_config)
|
|
|
|
# no slaves, set zone must not be called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_PLAY_EVERYWHERE,
|
|
{"master": DEVICE_1_ENTITY_ID},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 0
|
|
|
|
await setup_soundtouch(hass, device2_config)
|
|
|
|
# one master, one slave => set zone
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_PLAY_EVERYWHERE,
|
|
{"master": DEVICE_1_ENTITY_ID},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 1
|
|
|
|
# unknown master, set zone must not be called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_PLAY_EVERYWHERE,
|
|
{"master": "media_player.entity_X"},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 1
|
|
|
|
|
|
async def test_create_zone(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device2_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device2_requests_mock_standby,
|
|
device1_requests_mock_set_zone,
|
|
) -> None:
|
|
"""Test creating a zone."""
|
|
await setup_soundtouch(hass, device1_config, device2_config)
|
|
|
|
assert device1_requests_mock_set_zone.call_count == 0
|
|
|
|
# one master, one slave => set zone
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_CREATE_ZONE,
|
|
{
|
|
"master": DEVICE_1_ENTITY_ID,
|
|
"slaves": [DEVICE_2_ENTITY_ID],
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 1
|
|
|
|
# unknown master, set zone must not be called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_CREATE_ZONE,
|
|
{"master": "media_player.entity_X", "slaves": [DEVICE_2_ENTITY_ID]},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 1
|
|
|
|
# no slaves, set zone must not be called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_CREATE_ZONE,
|
|
{"master": DEVICE_1_ENTITY_ID, "slaves": []},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_set_zone.call_count == 1
|
|
|
|
|
|
async def test_remove_zone_slave(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device2_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device2_requests_mock_standby,
|
|
device1_requests_mock_remove_zone_slave,
|
|
) -> None:
|
|
"""Test removing a slave from an existing zone."""
|
|
await setup_soundtouch(hass, device1_config, device2_config)
|
|
|
|
# remove one slave
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_REMOVE_ZONE_SLAVE,
|
|
{
|
|
"master": DEVICE_1_ENTITY_ID,
|
|
"slaves": [DEVICE_2_ENTITY_ID],
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_remove_zone_slave.call_count == 1
|
|
|
|
# unknown master, remove zone slave is not called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_REMOVE_ZONE_SLAVE,
|
|
{"master": "media_player.entity_X", "slaves": [DEVICE_2_ENTITY_ID]},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_remove_zone_slave.call_count == 1
|
|
|
|
# no slave to remove, remove zone slave is not called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_REMOVE_ZONE_SLAVE,
|
|
{"master": DEVICE_1_ENTITY_ID, "slaves": []},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_remove_zone_slave.call_count == 1
|
|
|
|
|
|
async def test_add_zone_slave(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device2_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device2_requests_mock_standby,
|
|
device1_requests_mock_add_zone_slave,
|
|
) -> None:
|
|
"""Test adding a slave to a zone."""
|
|
await setup_soundtouch(hass, device1_config, device2_config)
|
|
|
|
# add one slave
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_ADD_ZONE_SLAVE,
|
|
{
|
|
"master": DEVICE_1_ENTITY_ID,
|
|
"slaves": [DEVICE_2_ENTITY_ID],
|
|
},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_add_zone_slave.call_count == 1
|
|
|
|
# unknown master, add zone slave is not called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_ADD_ZONE_SLAVE,
|
|
{"master": "media_player.entity_X", "slaves": [DEVICE_2_ENTITY_ID]},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_add_zone_slave.call_count == 1
|
|
|
|
# no slave to add, add zone slave is not called
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_ADD_ZONE_SLAVE,
|
|
{"master": DEVICE_1_ENTITY_ID, "slaves": ["media_player.entity_X"]},
|
|
True,
|
|
)
|
|
assert device1_requests_mock_add_zone_slave.call_count == 1
|
|
|
|
|
|
async def test_zone_attributes(
|
|
hass: HomeAssistant,
|
|
device1_config: MockConfigEntry,
|
|
device2_config: MockConfigEntry,
|
|
device1_requests_mock_standby,
|
|
device2_requests_mock_standby,
|
|
) -> None:
|
|
"""Test zone attributes."""
|
|
await setup_soundtouch(hass, device1_config, device2_config)
|
|
|
|
# Fast-forward time to allow all entities to be set up and updated again
|
|
async_fire_time_changed(
|
|
hass,
|
|
dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
|
|
)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
entity_1_state = hass.states.get(DEVICE_1_ENTITY_ID)
|
|
assert entity_1_state.attributes[ATTR_SOUNDTOUCH_ZONE]["is_master"]
|
|
assert (
|
|
entity_1_state.attributes[ATTR_SOUNDTOUCH_ZONE]["master"] == DEVICE_1_ENTITY_ID
|
|
)
|
|
assert entity_1_state.attributes[ATTR_SOUNDTOUCH_ZONE]["slaves"] == [
|
|
DEVICE_2_ENTITY_ID
|
|
]
|
|
assert entity_1_state.attributes[ATTR_SOUNDTOUCH_GROUP] == [
|
|
DEVICE_1_ENTITY_ID,
|
|
DEVICE_2_ENTITY_ID,
|
|
]
|
|
|
|
entity_2_state = hass.states.get(DEVICE_2_ENTITY_ID)
|
|
assert not entity_2_state.attributes[ATTR_SOUNDTOUCH_ZONE]["is_master"]
|
|
assert (
|
|
entity_2_state.attributes[ATTR_SOUNDTOUCH_ZONE]["master"] == DEVICE_1_ENTITY_ID
|
|
)
|
|
assert entity_2_state.attributes[ATTR_SOUNDTOUCH_ZONE]["slaves"] == [
|
|
DEVICE_2_ENTITY_ID
|
|
]
|
|
assert entity_2_state.attributes[ATTR_SOUNDTOUCH_GROUP] == [
|
|
DEVICE_1_ENTITY_ID,
|
|
DEVICE_2_ENTITY_ID,
|
|
]
|