"""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", {})