"""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"] class TestSettingsEndpoint: def test_get_settings_without_token_returns_401(self, client: TestClient) -> None: response = client.get("/api/v1/settings") assert response.status_code == 401 def test_get_settings_with_valid_token(self, client: TestClient) -> None: os.environ["API_TOKEN"] = "settings-token" response = client.get( "/api/v1/settings", headers={"Authorization": "Bearer settings-token"}, ) assert response.status_code == 200 data = response.json() assert "dashboard_pin" in data assert "api_token" in data assert "host" in data assert "port" in data del os.environ["API_TOKEN"] def test_update_settings(self, client: TestClient) -> None: os.environ["API_TOKEN"] = "update-token" response = client.post( "/api/v1/settings", json={ "dashboard_pin": "9999", "api_token": "new-token", }, headers={"Authorization": "Bearer update-token"}, ) assert response.status_code == 200 data = response.json() assert data["dashboard_pin"] == "9999" assert data["api_token"] == "new-token" del os.environ["API_TOKEN"] class TestStatusEndpoint: def test_status_returns_subsystems(self, client: TestClient) -> None: # Ensure subsystems are initialized if not hasattr(app.state, "subsystems"): app.state.subsystems = {} response = client.get("/api/v1/status") assert response.status_code == 200 data = response.json() assert "subsystems" in data assert "config" in data assert "pin_configured" in data["config"] assert "token_configured" in data["config"]