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,94 @@
|
||||
"""Tests for the FastAPI application endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ..main import app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client() -> TestClient:
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
class TestHealth:
|
||||
def test_health_returns_ok(self, client: TestClient) -> None:
|
||||
response = client.get("/health")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
||||
|
||||
class TestGetState:
|
||||
def test_get_state_returns_dict(self, client: TestClient) -> None:
|
||||
with (
|
||||
patch.object(app.state, "media", create=True),
|
||||
patch.object(app.state, "audio", create=True),
|
||||
patch.object(app.state, "notifications", create=True),
|
||||
patch.object(app.state, "telemetry", create=True),
|
||||
):
|
||||
app.state.media.get_state = lambda: {"title": "Test"}
|
||||
app.state.audio.get_state = lambda: {"backend": "windows"}
|
||||
app.state.notifications.get_active = list
|
||||
app.state.telemetry.get_state = dict
|
||||
|
||||
response = client.get("/api/v1/state")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "media" in data
|
||||
assert "audio" in data
|
||||
assert "notifications" in data
|
||||
assert "telemetry" in data
|
||||
|
||||
|
||||
class TestNotifyEndpoint:
|
||||
def test_notify_without_token_returns_401(self, client: TestClient) -> None:
|
||||
response = client.post(
|
||||
"/api/v1/notify",
|
||||
json={
|
||||
"type": "alert",
|
||||
"title": "Test",
|
||||
"message": "Hello",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_notify_with_valid_token(self, client: TestClient) -> None:
|
||||
os.environ["API_TOKEN"] = "test-token-123"
|
||||
|
||||
with patch.object(app.state, "notifications", create=True) as mock_notif:
|
||||
mock_notif.create = AsyncMock()
|
||||
mock_notif.create.return_value = type(
|
||||
"Notification", (), {"id": "test-id"}
|
||||
)()
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/notify",
|
||||
json={
|
||||
"type": "alert",
|
||||
"title": "Build Complete",
|
||||
"message": "Success",
|
||||
},
|
||||
headers={"Authorization": "Bearer test-token-123"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["status"] == "created"
|
||||
|
||||
# Cleanup
|
||||
del os.environ["API_TOKEN"]
|
||||
|
||||
def test_notify_with_wrong_token_returns_401(self, client: TestClient) -> None:
|
||||
os.environ["API_TOKEN"] = "correct-token"
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/notify",
|
||||
json={"type": "alert", "title": "Test", "message": "Hello"},
|
||||
headers={"Authorization": "Bearer wrong-token"},
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
del os.environ["API_TOKEN"]
|
||||
Reference in New Issue
Block a user