mirror of
https://github.com/home-assistant/core.git
synced 2026-09-16 21:48:38 +01:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
225 lines
6.8 KiB
Python
225 lines
6.8 KiB
Python
"""Tests for the Collection Image integration services."""
|
|
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
from homeassistant.components.collection_image.const import DOMAIN
|
|
from homeassistant.components.collection_image.image import CollectionImageImageEntity
|
|
from homeassistant.components.collection_image.services import (
|
|
CollectionImageService,
|
|
CollectionImageServiceArgument,
|
|
)
|
|
from homeassistant.components.media_source import PlayMedia
|
|
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from .conftest import MediaSourceMocks, MediaSourceState
|
|
from .const import DEFAULT_ENTITY_ID, MOCK_MEDIA_DIR_URI_1
|
|
from .helpers import directory, image
|
|
|
|
from tests.common import Mock, MockConfigEntry
|
|
|
|
|
|
async def _setup_integration(
|
|
hass: HomeAssistant,
|
|
config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Set up the Collection Image integration."""
|
|
config_entry.add_to_hass(hass)
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def test_shuffle_action(
|
|
hass: HomeAssistant,
|
|
config_entry: MockConfigEntry,
|
|
mock_media_source,
|
|
) -> None:
|
|
"""Test that shuffle calls get_random_image on the target entity."""
|
|
await _setup_integration(hass, config_entry)
|
|
|
|
with patch.object(
|
|
CollectionImageImageEntity,
|
|
"get_random_image",
|
|
new_callable=AsyncMock,
|
|
) as mock_get_random_image:
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
"shuffle",
|
|
{ATTR_ENTITY_ID: DEFAULT_ENTITY_ID},
|
|
blocking=True,
|
|
)
|
|
|
|
mock_get_random_image.assert_awaited_once()
|
|
|
|
|
|
async def test_navigation(
|
|
hass: HomeAssistant,
|
|
config_entry: MockConfigEntry,
|
|
media_source_state: MediaSourceState,
|
|
mock_media_source: MediaSourceMocks,
|
|
) -> None:
|
|
"""Test first/last/next/previous actions."""
|
|
|
|
images = [
|
|
image("media-source://mymedia/1"),
|
|
image("media-source://mymedia/2"),
|
|
image("media-source://mymedia/3"),
|
|
]
|
|
|
|
media_source_state.browse_results = {
|
|
MOCK_MEDIA_DIR_URI_1: directory("My pictures", *images)
|
|
}
|
|
media_source_state.resolve_results = {
|
|
img.media_content_id: PlayMedia(
|
|
url="",
|
|
mime_type="image/png",
|
|
)
|
|
for img in images
|
|
}
|
|
|
|
with patch(
|
|
"homeassistant.components.collection_image.image.random.choice",
|
|
new=Mock(return_value=images[1]),
|
|
):
|
|
await _setup_integration(hass, config_entry)
|
|
await hass.async_block_till_done()
|
|
|
|
assert mock_media_source.image_browse.call_count == 1
|
|
assert mock_media_source.resolve.call_count == 1
|
|
|
|
def assert_resolve_index(idx: int):
|
|
args, _kwargs = mock_media_source.resolve.call_args
|
|
assert args[1] == images[idx].media_content_id
|
|
|
|
assert_resolve_index(1)
|
|
|
|
wrap = {CollectionImageServiceArgument.WRAP: True}
|
|
steps = (
|
|
(CollectionImageService.SELECT_FIRST, {}, 0),
|
|
(CollectionImageService.SELECT_LAST, {}, 2),
|
|
(CollectionImageService.SELECT_PREVIOUS, {}, 1),
|
|
(CollectionImageService.SELECT_PREVIOUS, {}, 0),
|
|
(CollectionImageService.SELECT_PREVIOUS, {}, 0),
|
|
(CollectionImageService.SELECT_PREVIOUS, wrap, 2),
|
|
(CollectionImageService.SELECT_PREVIOUS, wrap, 1),
|
|
(CollectionImageService.SELECT_PREVIOUS, wrap, 0),
|
|
(CollectionImageService.SELECT_NEXT, {}, 1),
|
|
(CollectionImageService.SELECT_NEXT, {}, 2),
|
|
(CollectionImageService.SELECT_NEXT, {}, 2),
|
|
(CollectionImageService.SELECT_NEXT, wrap, 0),
|
|
(CollectionImageService.SELECT_NEXT, wrap, 1),
|
|
)
|
|
|
|
for service, wrap, expected_index in steps:
|
|
data = {ATTR_ENTITY_ID: DEFAULT_ENTITY_ID, **wrap}
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
service,
|
|
data,
|
|
blocking=True,
|
|
)
|
|
assert_resolve_index(expected_index)
|
|
|
|
# Change to new images and verify that next resets count to 0
|
|
images = [
|
|
image("media-source://mymedia/4"),
|
|
image("media-source://mymedia/5"),
|
|
image("media-source://mymedia/6"),
|
|
]
|
|
|
|
media_source_state.browse_results = {
|
|
MOCK_MEDIA_DIR_URI_1: directory("My pictures", *images)
|
|
}
|
|
media_source_state.resolve_results = {
|
|
img.media_content_id: PlayMedia(
|
|
url="",
|
|
mime_type="image/png",
|
|
)
|
|
for img in images
|
|
}
|
|
|
|
data = {ATTR_ENTITY_ID: DEFAULT_ENTITY_ID}
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
CollectionImageService.SELECT_NEXT,
|
|
data,
|
|
blocking=True,
|
|
)
|
|
assert_resolve_index(0)
|
|
|
|
# Change to new images and verify that previous resets count to -1
|
|
images = [
|
|
image("media-source://mymedia/7"),
|
|
image("media-source://mymedia/8"),
|
|
image("media-source://mymedia/9"),
|
|
]
|
|
|
|
media_source_state.browse_results = {
|
|
MOCK_MEDIA_DIR_URI_1: directory("My pictures", *images)
|
|
}
|
|
media_source_state.resolve_results = {
|
|
img.media_content_id: PlayMedia(
|
|
url="",
|
|
mime_type="image/png",
|
|
)
|
|
for img in images
|
|
}
|
|
|
|
data = {ATTR_ENTITY_ID: DEFAULT_ENTITY_ID}
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
CollectionImageService.SELECT_PREVIOUS,
|
|
data,
|
|
blocking=True,
|
|
)
|
|
assert_resolve_index(2)
|
|
|
|
# Now there are no images, go to unavailable
|
|
media_source_state.browse_results = {MOCK_MEDIA_DIR_URI_1: directory("My pictures")}
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
CollectionImageService.SELECT_NEXT,
|
|
data,
|
|
blocking=True,
|
|
)
|
|
|
|
state = hass.states.get(DEFAULT_ENTITY_ID)
|
|
assert state and state.state == STATE_UNAVAILABLE
|
|
|
|
|
|
async def test_first_unavailable(
|
|
hass: HomeAssistant,
|
|
config_entry: MockConfigEntry,
|
|
media_source_state: MediaSourceState,
|
|
mock_media_source: MediaSourceMocks,
|
|
) -> None:
|
|
"""Check that calling first on empty directory sets unavailable."""
|
|
images = [
|
|
image("media-source://mymedia/1"),
|
|
]
|
|
media_source_state.browse_results = {
|
|
MOCK_MEDIA_DIR_URI_1: directory("My pictures", *images)
|
|
}
|
|
media_source_state.resolve_results = {
|
|
img.media_content_id: PlayMedia(
|
|
url="",
|
|
mime_type="image/png",
|
|
)
|
|
for img in images
|
|
}
|
|
await _setup_integration(hass, config_entry)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(DEFAULT_ENTITY_ID)
|
|
assert state and state.state != STATE_UNAVAILABLE
|
|
|
|
media_source_state.browse_results = {MOCK_MEDIA_DIR_URI_1: directory("My pictures")}
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
CollectionImageService.SELECT_FIRST,
|
|
{ATTR_ENTITY_ID: DEFAULT_ENTITY_ID},
|
|
blocking=True,
|
|
)
|
|
state = hass.states.get(DEFAULT_ENTITY_ID)
|
|
assert state and state.state == STATE_UNAVAILABLE
|