feat: initial project scaffold — server, client, Android APK
- FastAPI server with audio mixer (Windows + Voicemeeter), media tracking, notifications (progress + alerts), telemetry, and system tray .exe build - Test suite covering notifications, audio mixer, media, telemetry, and API - E-Ink web client (vanilla JS, DOM API, block meters, swipe gestures) - Android WebView APK for BOOX Go 7 Color Gen II (Android 13, Kotlin) - Design decision records in .pi/docs/design/ - PyInstaller build script for server .exe
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
"""Tests for the notification system."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ..notifications import Notification, NotificationManager, ProgressState
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager() -> NotificationManager:
|
||||
return NotificationManager()
|
||||
|
||||
|
||||
class TestNotificationCreation:
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_alert(self, manager: NotificationManager) -> None:
|
||||
notif = Notification(
|
||||
type="alert",
|
||||
title="Build Complete",
|
||||
message="Deployment succeeded.",
|
||||
priority="info",
|
||||
)
|
||||
result = await manager.create(notif)
|
||||
assert result.id
|
||||
assert result.type == "alert"
|
||||
assert result.title == "Build Complete"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_progress(self, manager: NotificationManager) -> None:
|
||||
notif = Notification(
|
||||
type="progress",
|
||||
title="Backup",
|
||||
message="Uploading...",
|
||||
progress=ProgressState(current=50, min=0, max=100, unit="MB"),
|
||||
)
|
||||
result = await manager.create(notif)
|
||||
assert result.type == "progress"
|
||||
assert result.progress is not None
|
||||
progress = result.progress
|
||||
assert progress.percentage == 50.0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_existing_notification(
|
||||
self, manager: NotificationManager
|
||||
) -> None:
|
||||
notif = Notification(
|
||||
id="test_01",
|
||||
type="progress",
|
||||
title="Backup",
|
||||
progress=ProgressState(current=10, max=100),
|
||||
)
|
||||
await manager.create(notif)
|
||||
|
||||
notif.progress = ProgressState(current=50, max=100)
|
||||
result = await manager.create(notif)
|
||||
assert result.progress is not None
|
||||
assert result.progress.percentage == 50.0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_active_returns_list(self, manager: NotificationManager) -> None:
|
||||
await manager.create(Notification(title="Test"))
|
||||
active = manager.get_active()
|
||||
assert len(active) == 1
|
||||
assert active[0]["title"] == "Test"
|
||||
|
||||
|
||||
class TestNotificationPruning:
|
||||
@pytest.mark.asyncio
|
||||
async def test_prunes_old_notifications(self) -> None:
|
||||
manager = NotificationManager()
|
||||
manager._max_active = 3
|
||||
|
||||
for i in range(5):
|
||||
await manager.create(Notification(id=f"n{i}", title=f"Msg {i}"))
|
||||
|
||||
active = manager.get_active()
|
||||
assert len(active) == 3
|
||||
ids = [n["id"] for n in active]
|
||||
assert "n0" not in ids
|
||||
assert "n4" in ids
|
||||
|
||||
|
||||
class TestNotificationDismiss:
|
||||
@pytest.mark.asyncio
|
||||
async def test_dismiss_removes_notification(
|
||||
self, manager: NotificationManager
|
||||
) -> None:
|
||||
notif = Notification(id="dismiss_me", title="Temp")
|
||||
await manager.create(notif)
|
||||
assert len(manager.get_active()) == 1
|
||||
|
||||
result = await manager.dismiss("dismiss_me")
|
||||
assert result
|
||||
assert len(manager.get_active()) == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dismiss_nonexistent_returns_false(
|
||||
self, manager: NotificationManager
|
||||
) -> None:
|
||||
result = await manager.dismiss("does_not_exist")
|
||||
assert not result
|
||||
|
||||
|
||||
class TestProgressState:
|
||||
def test_percentage_calculation(self) -> None:
|
||||
p = ProgressState(current=75, min=0, max=100)
|
||||
assert p.percentage == 75.0
|
||||
|
||||
def test_percentage_clamped_at_zero(self) -> None:
|
||||
p = ProgressState(current=-10, min=0, max=100)
|
||||
assert p.percentage == 0.0
|
||||
|
||||
def test_percentage_clamped_at_hundred(self) -> None:
|
||||
p = ProgressState(current=150, min=0, max=100)
|
||||
assert p.percentage == 100.0
|
||||
|
||||
def test_zero_range_returns_zero(self) -> None:
|
||||
p = ProgressState(current=50, min=0, max=0)
|
||||
assert p.percentage == 0.0
|
||||
Reference in New Issue
Block a user