core/tests/components/immich/conftest.py

329 lines
10 KiB
Python

"""Common fixtures for the Immich tests."""
from collections.abc import AsyncGenerator, Generator
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock, patch
from aioimmich import (
ImmichAlbums,
ImmichAssests,
ImmichPeople,
ImmichSearch,
ImmichServer,
ImmichTags,
ImmichUsers,
)
from aioimmich.albums.models import ImmichAddAssetsToAlbumResponse
from aioimmich.assets.models import ImmichAssetUploadResponse
from aioimmich.people.models import ImmichPerson
from aioimmich.server.models import (
ImmichServerAbout,
ImmichServerStatistics,
ImmichServerStorage,
ImmichServerVersionCheck,
)
from aioimmich.tags.models import ImmichTag
from aioimmich.users.models import ImmichUserObject
import pytest
from homeassistant.components.immich.const import DOMAIN
from homeassistant.components.media_source import PlayMedia
from homeassistant.const import (
CONF_API_KEY,
CONF_HOST,
CONF_PORT,
CONF_SSL,
CONF_VERIFY_SSL,
)
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from homeassistant.util.aiohttp import MockStreamReaderChunked
from .const import (
MOCK_ALBUM_WITH_ASSETS,
MOCK_ALBUM_WITHOUT_ASSETS,
MOCK_PEOPLE_ASSETS,
MOCK_TAGS_ASSETS,
)
from tests.common import MockConfigEntry
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.immich.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
domain=DOMAIN,
data={
CONF_HOST: "localhost",
CONF_PORT: 80,
CONF_SSL: False,
CONF_API_KEY: "api_key",
CONF_VERIFY_SSL: True,
},
unique_id="e7ef5713-9dab-4bd4-b899-715b0ca4379e",
title="Someone",
)
@pytest.fixture
def mock_immich_albums() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichAlbums)
mock.async_get_all_albums.return_value = [MOCK_ALBUM_WITHOUT_ASSETS]
mock.async_get_album_info.return_value = MOCK_ALBUM_WITH_ASSETS
mock.async_add_assets_to_album.return_value = [
ImmichAddAssetsToAlbumResponse.from_dict(
{"id": "abcdef-0123456789", "success": True}
)
]
return mock
@pytest.fixture
def mock_immich_assets() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichAssests)
mock.async_view_asset.return_value = b"xxxx"
mock.async_play_video_stream.return_value = MockStreamReaderChunked(b"xxxx")
mock.async_upload_asset.return_value = ImmichAssetUploadResponse.from_dict(
{"id": "abcdef-0123456789", "status": "created"}
)
return mock
@pytest.fixture
def mock_immich_people() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichPeople)
mock.async_get_all_people.return_value = [
ImmichPerson.from_dict(
{
"id": "6176838a-ac5a-4d1f-9a35-91c591d962d8",
"name": "Me",
"birthDate": None,
"thumbnailPath": "upload/thumbs/e7ef5713-9dab-4bd4-b899-715b0ca4379e/61/76/6176838a-ac5a-4d1f-9a35-91c591d962d8.jpeg",
"isHidden": False,
"isFavorite": False,
"updatedAt": "2025-05-11T11:07:41.651Z",
}
),
ImmichPerson.from_dict(
{
"id": "3e66aa4a-a4a8-41a4-86fe-2ae5e490078f",
"name": "I",
"birthDate": None,
"thumbnailPath": "upload/thumbs/e7ef5713-9dab-4bd4-b899-715b0ca4379e/3e/66/3e66aa4a-a4a8-41a4-86fe-2ae5e490078f.jpeg",
"isHidden": False,
"isFavorite": False,
"updatedAt": "2025-05-19T22:10:21.953Z",
}
),
ImmichPerson.from_dict(
{
"id": "a3c83297-684a-4576-82dc-b07432e8a18f",
"name": "Myself",
"birthDate": None,
"thumbnailPath": "upload/thumbs/e7ef5713-9dab-4bd4-b899-715b0ca4379e/a3/c8/a3c83297-684a-4576-82dc-b07432e8a18f.jpeg",
"isHidden": False,
"isFavorite": False,
"updatedAt": "2025-05-12T21:07:04.044Z",
}
),
]
mock.async_get_person_thumbnail.return_value = b"yyyy"
return mock
@pytest.fixture
def mock_immich_search() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichSearch)
mock.async_get_all_by_person_ids.return_value = MOCK_PEOPLE_ASSETS
mock.async_get_all_by_tag_ids.return_value = MOCK_TAGS_ASSETS
return mock
@pytest.fixture
def mock_immich_server() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichServer)
mock.async_get_about_info.return_value = ImmichServerAbout.from_dict(
{
"version": "v1.134.0",
"versionUrl": "https://github.com/immich-app/immich/releases/tag/v1.134.0",
"licensed": False,
"build": "15281783550",
"buildUrl": "https://github.com/immich-app/immich/actions/runs/15281783550",
"buildImage": "v1.134.0",
"buildImageUrl": "https://github.com/immich-app/immich/pkgs/container/immich-server",
"repository": "immich-app/immich",
"repositoryUrl": "https://github.com/immich-app/immich",
"sourceRef": "v1.134.0",
"sourceCommit": "58ae77ec9204a2e43a8cb2f1fd27482af40d0891",
"sourceUrl": "https://github.com/immich-app/immich/commit/58ae77ec9204a2e43a8cb2f1fd27482af40d0891",
"nodejs": "v22.14.0",
"exiftool": "13.00",
"ffmpeg": "7.0.2-9",
"libvips": "8.16.1",
"imagemagick": "7.1.1-47",
}
)
mock.async_get_storage_info.return_value = ImmichServerStorage.from_dict(
{
"diskSize": "294.2 GiB",
"diskUse": "142.9 GiB",
"diskAvailable": "136.3 GiB",
"diskSizeRaw": 315926315008,
"diskUseRaw": 153400406016,
"diskAvailableRaw": 146403004416,
"diskUsagePercentage": 48.56,
}
)
mock.async_get_server_statistics.return_value = ImmichServerStatistics.from_dict(
{
"photos": 27038,
"videos": 1836,
"usage": 119525451912,
"usagePhotos": 54291170551,
"usageVideos": 65234281361,
"usageByUser": [
{
"userId": "e7ef5713-9dab-4bd4-b899-715b0ca4379e",
"userName": "admin",
"photos": 27038,
"videos": 1836,
"usage": 119525451912,
"usagePhotos": 54291170551,
"usageVideos": 65234281361,
"quotaSizeInBytes": None,
}
],
}
)
mock.async_get_version_check.return_value = ImmichServerVersionCheck.from_dict(
{
"checkedAt": "2025-06-21T16:35:10.352Z",
"releaseVersion": "v1.135.3",
}
)
return mock
@pytest.fixture
def mock_immich_tags() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichTags)
mock.async_get_all_tags.return_value = [
ImmichTag.from_dict(
{
"id": "67301cb8-cb73-4e8a-99e9-475cb3f7e7b5",
"name": "Halloween",
"value": "Halloween",
"createdAt": "2025-05-12T20:00:45.220Z",
"updatedAt": "2025-05-12T20:00:47.224Z",
},
),
ImmichTag.from_dict(
{
"id": "69bd487f-dc1e-4420-94c6-656f0515773d",
"name": "Holidays",
"value": "Holidays",
"createdAt": "2025-05-12T20:00:49.967Z",
"updatedAt": "2025-05-12T20:00:55.575Z",
},
),
]
return mock
@pytest.fixture
def mock_immich_user() -> AsyncMock:
"""Mock the Immich server."""
mock = AsyncMock(spec=ImmichUsers)
mock.async_get_my_user.return_value = ImmichUserObject.from_dict(
{
"id": "e7ef5713-9dab-4bd4-b899-715b0ca4379e",
"email": "user@immich.local",
"name": "user",
"profileImagePath": "",
"avatarColor": "primary",
"profileChangedAt": "2025-05-11T10:07:46.866Z",
"storageLabel": "user",
"shouldChangePassword": True,
"isAdmin": True,
"createdAt": "2025-05-11T10:07:46.866Z",
"deletedAt": None,
"updatedAt": "2025-05-18T00:59:55.547Z",
"oauthId": "",
"quotaSizeInBytes": None,
"quotaUsageInBytes": 119526467534,
"status": "active",
"license": None,
}
)
return mock
@pytest.fixture
async def mock_immich(
mock_immich_albums: AsyncMock,
mock_immich_assets: AsyncMock,
mock_immich_people: AsyncMock,
mock_immich_search: AsyncMock,
mock_immich_server: AsyncMock,
mock_immich_tags: AsyncMock,
mock_immich_user: AsyncMock,
) -> AsyncGenerator[AsyncMock]:
"""Mock the Immich API."""
with (
patch("homeassistant.components.immich.Immich", autospec=True) as mock_immich,
patch("homeassistant.components.immich.config_flow.Immich", new=mock_immich),
):
client = mock_immich.return_value
client.albums = mock_immich_albums
client.assets = mock_immich_assets
client.people = mock_immich_people
client.search = mock_immich_search
client.server = mock_immich_server
client.tags = mock_immich_tags
client.users = mock_immich_user
yield client
@pytest.fixture
async def mock_non_admin_immich(mock_immich: AsyncMock) -> AsyncMock:
"""Mock the Immich API."""
mock_immich.users.async_get_my_user.return_value.is_admin = False
return mock_immich
@pytest.fixture
def mock_media_source() -> Generator[MagicMock]:
"""Mock the media source."""
with patch(
"homeassistant.components.immich.services.async_resolve_media",
return_value=PlayMedia(
url="media-source://media_source/local/screenshot.jpg",
mime_type="image/jpeg",
path=Path("/media/screenshot.jpg"),
),
) as mock_media:
yield mock_media
@pytest.fixture
async def setup_media_source(hass: HomeAssistant) -> None:
"""Set up media source."""
assert await async_setup_component(hass, "media_source", {})