Consolidating controller tests. Fixing controller test cleanup which slowed down tests significantly.
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Controller Tests / controller-tests (push) Has been cancelled
Jest Tests / jest-tests (push) Has been cancelled

This commit is contained in:
Roland 2026-05-15 21:10:30 -06:00
parent b0be30c3d6
commit 2806673e25
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
11 changed files with 366 additions and 970 deletions

View file

@ -2,233 +2,61 @@
Integration tests for Controller admin API endpoints.
"""
import pytest
class TestHotspotStatusEndpoint:
"""Tests for /api/hotspot/status endpoint."""
def test_hotspot_status_returns_200(self, test_client):
"""Hotspot status endpoint should return 200 OK."""
response = test_client.get("/api/hotspot/status")
class TestStatusEndpoints:
"""Status endpoints (hotspot/bluetooth/throttle/timezone) — shape + docker behaviour."""
@pytest.mark.parametrize("endpoint,required_fields", [
("/api/hotspot/status", ["enabled", "available"]),
("/api/bluetooth/status", ["enabled", "available"]),
("/api/throttle/status", ["enabled", "available"]),
("/api/timezone/status", ["available", "timezone"]),
])
def test_status_endpoint_shape(self, test_client, endpoint, required_fields):
"""Each status endpoint should return 200 with the documented fields."""
response = test_client.get(endpoint)
assert response.status_code == 200
def test_hotspot_status_returns_expected_fields(self, test_client):
"""Hotspot status should return enabled and available fields."""
response = test_client.get("/api/hotspot/status")
data = response.json()
assert "enabled" in data
assert "available" in data
for field in required_fields:
assert field in data, f"{endpoint} missing field {field!r}"
def test_hotspot_status_shows_unavailable_in_docker(self, test_client_docker_mode):
"""Hotspot should be unavailable in Docker mode."""
response = test_client_docker_mode.get("/api/hotspot/status")
data = response.json()
@pytest.mark.parametrize("endpoint", [
"/api/hotspot/status",
"/api/bluetooth/status",
"/api/throttle/status",
"/api/timezone/status",
])
def test_status_endpoint_unavailable_in_docker(self, test_client_docker_mode, endpoint):
"""Status endpoints should report available=False in Docker mode."""
data = test_client_docker_mode.get(endpoint).json()
assert data["available"] is False
class TestHotspotEnableEndpoint:
"""Tests for /api/hotspot/enable endpoint."""
class TestDockerModeRejectsAdminActions:
"""Admin action endpoints should reject requests when running in Docker."""
def test_hotspot_enable_fails_in_docker(self, test_client_docker_mode):
"""Hotspot enable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/hotspot/enable")
assert response.status_code == 500
@pytest.mark.parametrize("method,endpoint,expected_status,payload", [
# Subsystem enable/disable — return 500 with a Docker-flavoured error.
("post", "/api/hotspot/enable", 500, None),
("post", "/api/hotspot/disable", 500, None),
("post", "/api/bluetooth/enable", 500, None),
("post", "/api/bluetooth/disable", 500, None),
("post", "/api/throttle/enable", 500, None),
("post", "/api/throttle/disable", 500, None),
("post", "/api/timezone/set", 500, {"timezone": "America/Denver"}),
# System control — return 501 (not implemented under Docker).
("post", "/api/shutdown", 501, None),
("post", "/api/reboot", 501, None),
("post", "/api/restart", 501, None),
])
def test_action_rejected_in_docker(self, test_client_docker_mode, method, endpoint, expected_status, payload):
"""Admin endpoints should reject Docker-mode requests with a Docker-mentioning error."""
client_call = getattr(test_client_docker_mode, method)
response = client_call(endpoint, json=payload) if payload else client_call(endpoint)
assert response.status_code == expected_status
assert "Docker" in response.json()["detail"]
class TestHotspotDisableEndpoint:
"""Tests for /api/hotspot/disable endpoint."""
def test_hotspot_disable_fails_in_docker(self, test_client_docker_mode):
"""Hotspot disable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/hotspot/disable")
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestBluetoothStatusEndpoint:
"""Tests for /api/bluetooth/status endpoint."""
def test_bluetooth_status_returns_200(self, test_client):
"""Bluetooth status endpoint should return 200 OK."""
response = test_client.get("/api/bluetooth/status")
assert response.status_code == 200
def test_bluetooth_status_returns_expected_fields(self, test_client):
"""Bluetooth status should return enabled and available fields."""
response = test_client.get("/api/bluetooth/status")
data = response.json()
assert "enabled" in data
assert "available" in data
def test_bluetooth_status_shows_unavailable_in_docker(self, test_client_docker_mode):
"""Bluetooth should be unavailable in Docker mode."""
response = test_client_docker_mode.get("/api/bluetooth/status")
data = response.json()
assert data["available"] is False
class TestBluetoothEnableEndpoint:
"""Tests for /api/bluetooth/enable endpoint."""
def test_bluetooth_enable_fails_in_docker(self, test_client_docker_mode):
"""Bluetooth enable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/bluetooth/enable")
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestBluetoothDisableEndpoint:
"""Tests for /api/bluetooth/disable endpoint."""
def test_bluetooth_disable_fails_in_docker(self, test_client_docker_mode):
"""Bluetooth disable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/bluetooth/disable")
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestThrottleStatusEndpoint:
"""Tests for /api/throttle/status endpoint."""
def test_throttle_status_returns_200(self, test_client):
"""Throttle status endpoint should return 200 OK."""
response = test_client.get("/api/throttle/status")
assert response.status_code == 200
def test_throttle_status_returns_expected_fields(self, test_client):
"""Throttle status should return enabled and available fields."""
response = test_client.get("/api/throttle/status")
data = response.json()
assert "enabled" in data
assert "available" in data
def test_throttle_status_shows_unavailable_in_docker(self, test_client_docker_mode):
"""Throttle should be unavailable in Docker mode."""
response = test_client_docker_mode.get("/api/throttle/status")
data = response.json()
assert data["available"] is False
class TestThrottleEnableEndpoint:
"""Tests for /api/throttle/enable endpoint."""
def test_throttle_enable_fails_in_docker(self, test_client_docker_mode):
"""Throttle enable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/throttle/enable")
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestThrottleDisableEndpoint:
"""Tests for /api/throttle/disable endpoint."""
def test_throttle_disable_fails_in_docker(self, test_client_docker_mode):
"""Throttle disable should fail in Docker mode."""
response = test_client_docker_mode.post("/api/throttle/disable")
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestShutdownEndpoint:
"""Tests for /api/shutdown endpoint."""
def test_shutdown_returns_501_in_docker(self, test_client_docker_mode):
"""Shutdown should return 501 in Docker mode."""
response = test_client_docker_mode.post("/api/shutdown")
assert response.status_code == 501
assert "Docker" in response.json()["detail"]
class TestRebootEndpoint:
"""Tests for /api/reboot endpoint."""
def test_reboot_returns_501_in_docker(self, test_client_docker_mode):
"""Reboot should return 501 in Docker mode."""
response = test_client_docker_mode.post("/api/reboot")
assert response.status_code == 501
assert "Docker" in response.json()["detail"]
class TestRestartEndpoint:
"""Tests for /api/restart endpoint."""
def test_restart_returns_501_in_docker(self, test_client_docker_mode):
"""Restart should return 501 in Docker mode."""
response = test_client_docker_mode.post("/api/restart")
assert response.status_code == 501
assert "Docker" in response.json()["detail"]
class TestTimezoneStatusEndpoint:
"""Tests for /api/timezone/status endpoint."""
def test_timezone_status_returns_200(self, test_client):
"""Timezone status endpoint should return 200 OK."""
response = test_client.get("/api/timezone/status")
assert response.status_code == 200
def test_timezone_status_returns_expected_fields(self, test_client):
"""Timezone status should return available and timezone fields."""
response = test_client.get("/api/timezone/status")
data = response.json()
assert "available" in data
assert "timezone" in data
def test_timezone_status_shows_unavailable_in_docker(self, test_client_docker_mode):
"""Timezone should be unavailable in Docker mode."""
response = test_client_docker_mode.get("/api/timezone/status")
data = response.json()
assert data["available"] is False
class TestTimezoneSetEndpoint:
"""Tests for /api/timezone/set endpoint."""
def test_timezone_set_fails_in_docker(self, test_client_docker_mode):
"""Timezone set should fail in Docker mode."""
response = test_client_docker_mode.post("/api/timezone/set", json={"timezone": "America/Denver"})
assert response.status_code == 500
assert "Docker" in response.json()["detail"]
class TestOpenAPIIncludesAdminEndpoints:
"""Tests that OpenAPI documentation includes admin endpoints."""
def test_openapi_has_hotspot_paths(self, test_client):
"""OpenAPI schema should include hotspot paths."""
response = test_client.get("/openapi.json")
data = response.json()
assert "/api/hotspot/status" in data["paths"]
assert "/api/hotspot/enable" in data["paths"]
assert "/api/hotspot/disable" in data["paths"]
def test_openapi_has_bluetooth_paths(self, test_client):
"""OpenAPI schema should include bluetooth paths."""
response = test_client.get("/openapi.json")
data = response.json()
assert "/api/bluetooth/status" in data["paths"]
assert "/api/bluetooth/enable" in data["paths"]
assert "/api/bluetooth/disable" in data["paths"]
def test_openapi_has_throttle_paths(self, test_client):
"""OpenAPI schema should include throttle paths."""
response = test_client.get("/openapi.json")
data = response.json()
assert "/api/throttle/status" in data["paths"]
assert "/api/throttle/enable" in data["paths"]
assert "/api/throttle/disable" in data["paths"]
def test_openapi_has_timezone_paths(self, test_client):
"""OpenAPI schema should include timezone paths."""
response = test_client.get("/openapi.json")
data = response.json()
assert "/api/timezone/status" in data["paths"]
assert "/api/timezone/set" in data["paths"]
def test_openapi_has_system_control_paths(self, test_client):
"""OpenAPI schema should include system control paths."""
response = test_client.get("/openapi.json")
data = response.json()
assert "/api/shutdown" in data["paths"]
assert "/api/reboot" in data["paths"]
assert "/api/restart" in data["paths"]
# OpenAPI endpoint-presence tests are consolidated in test_api.py::TestOpenAPI.