Some checks failed
Validate / Hassfest (push) Has been cancelled
Extract HA-independent logic from the integration into packages/core/ as a standalone Python library (immich-watcher-core). This is the first phase of restructuring the project to support a standalone web app alongside the existing HAOS integration. Core library modules: - models: SharedLinkInfo, AssetInfo, AlbumData, AlbumChange dataclasses - immich_client: Async Immich API client (aiohttp, session-injected) - change_detector: Pure function for album change detection - asset_utils: Filtering, sorting, URL building utilities - telegram/client: Full Telegram Bot API (text, photo, video, media groups) - telegram/cache: File ID cache with pluggable storage backend - telegram/media: Media size checks, URL extraction, group splitting - notifications/queue: Persistent notification queue - storage: StorageBackend protocol + JSON file implementation All modules have zero Home Assistant imports. 50 unit tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
2.5 KiB
Python
84 lines
2.5 KiB
Python
"""Tests for notification queue."""
|
|
|
|
import pytest
|
|
from typing import Any
|
|
|
|
from immich_watcher_core.notifications.queue import NotificationQueue
|
|
|
|
|
|
class InMemoryBackend:
|
|
"""In-memory storage backend for testing."""
|
|
|
|
def __init__(self, initial_data: dict[str, Any] | None = None):
|
|
self._data = initial_data
|
|
|
|
async def load(self) -> dict[str, Any] | None:
|
|
return self._data
|
|
|
|
async def save(self, data: dict[str, Any]) -> None:
|
|
self._data = data
|
|
|
|
async def remove(self) -> None:
|
|
self._data = None
|
|
|
|
|
|
@pytest.fixture
|
|
def backend():
|
|
return InMemoryBackend()
|
|
|
|
|
|
class TestNotificationQueue:
|
|
@pytest.mark.asyncio
|
|
async def test_empty_queue(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
assert not queue.has_pending()
|
|
assert queue.get_all() == []
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_enqueue_and_get(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
await queue.async_enqueue({"chat_id": "123", "text": "Hello"})
|
|
assert queue.has_pending()
|
|
items = queue.get_all()
|
|
assert len(items) == 1
|
|
assert items[0]["params"]["chat_id"] == "123"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_multiple_enqueue(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
await queue.async_enqueue({"msg": "first"})
|
|
await queue.async_enqueue({"msg": "second"})
|
|
assert len(queue.get_all()) == 2
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_clear(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
await queue.async_enqueue({"msg": "test"})
|
|
await queue.async_clear()
|
|
assert not queue.has_pending()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_indices(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
await queue.async_enqueue({"msg": "first"})
|
|
await queue.async_enqueue({"msg": "second"})
|
|
await queue.async_enqueue({"msg": "third"})
|
|
# Remove indices in descending order
|
|
await queue.async_remove_indices([2, 0])
|
|
items = queue.get_all()
|
|
assert len(items) == 1
|
|
assert items[0]["params"]["msg"] == "second"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_all(self, backend):
|
|
queue = NotificationQueue(backend)
|
|
await queue.async_load()
|
|
await queue.async_enqueue({"msg": "test"})
|
|
await queue.async_remove()
|
|
assert backend._data is None
|