mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 10:51:36 -04:00
165 lines
6.7 KiB
Python
165 lines
6.7 KiB
Python
"""
|
|
Integration tests for Controller services API endpoints.
|
|
"""
|
|
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
|
|
class TestServicesListEndpoint:
|
|
"""Tests for /api/services endpoint."""
|
|
|
|
def test_services_list_returns_200(self, test_client):
|
|
"""Services list endpoint should return 200 OK."""
|
|
response = test_client.get("/api/services")
|
|
assert response.status_code == 200
|
|
|
|
def test_services_list_returns_list_or_error(self, test_client):
|
|
"""Services list should return list of services or error object."""
|
|
response = test_client.get("/api/services")
|
|
data = response.json()
|
|
# Should be a list (when docker can manage) or error dict
|
|
assert isinstance(data, (list, dict))
|
|
|
|
|
|
class TestServicesListDockerMode:
|
|
"""Tests for /api/services in Docker mode."""
|
|
|
|
def test_returns_containers_when_docker_available(self, test_client_docker_mode):
|
|
"""Should return container status when Docker is available."""
|
|
mock_containers = [
|
|
{"name": "api", "status": "running", "container_name": "wrolpi-api-1"}
|
|
]
|
|
with mock.patch(
|
|
"controller.lib.docker_services.can_manage_containers",
|
|
return_value=True
|
|
):
|
|
with mock.patch(
|
|
"controller.lib.docker_services.get_all_containers_status",
|
|
return_value=mock_containers
|
|
):
|
|
# Also patch in the main module
|
|
with mock.patch(
|
|
"controller.main.can_manage_containers",
|
|
return_value=True
|
|
):
|
|
with mock.patch(
|
|
"controller.main.get_all_containers_status",
|
|
return_value=mock_containers
|
|
):
|
|
with mock.patch(
|
|
"controller.api.services.can_manage_containers",
|
|
return_value=True
|
|
):
|
|
with mock.patch(
|
|
"controller.api.services.get_all_containers_status",
|
|
return_value=mock_containers
|
|
):
|
|
response = test_client_docker_mode.get("/api/services")
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestServiceStatusEndpoint:
|
|
"""Tests for /api/services/{name} endpoint."""
|
|
|
|
def test_service_status_returns_status(self, test_client):
|
|
"""Should return service status."""
|
|
with mock.patch(
|
|
"controller.api.services.get_service_status",
|
|
return_value={
|
|
"name": "wrolpi-api",
|
|
"status": "running",
|
|
"systemd_name": "wrolpi-api.service",
|
|
}
|
|
):
|
|
response = test_client.get("/api/services/wrolpi-api")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["name"] == "wrolpi-api"
|
|
|
|
def test_unknown_service_returns_404(self, test_client):
|
|
"""Should return 404 for unknown service."""
|
|
with mock.patch(
|
|
"controller.api.services.get_service_status",
|
|
return_value={"error": "Unknown service: nonexistent"}
|
|
):
|
|
response = test_client.get("/api/services/nonexistent")
|
|
assert response.status_code == 404
|
|
|
|
|
|
class TestServiceActionEndpoints:
|
|
"""Tests for service action endpoints (start, stop, restart, enable, disable)."""
|
|
|
|
@pytest.mark.parametrize("action,endpoint,mock_func", [
|
|
("start", "/api/services/wrolpi-api/start", "start_service"),
|
|
("stop", "/api/services/wrolpi-api/stop", "stop_service"),
|
|
("restart", "/api/services/wrolpi-api/restart", "restart_service"),
|
|
("enable", "/api/services/wrolpi-api/enable", "enable_service"),
|
|
("disable", "/api/services/wrolpi-api/disable", "disable_service"),
|
|
])
|
|
def test_action_success(self, test_client, action, endpoint, mock_func):
|
|
"""Should perform service action successfully."""
|
|
with mock.patch(
|
|
f"controller.api.services.{mock_func}",
|
|
return_value={"success": True, "service": "wrolpi-api", "action": action}
|
|
):
|
|
response = test_client.post(endpoint)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert data["action"] == action
|
|
|
|
def test_start_failure_returns_500(self, test_client):
|
|
"""Should return 500 on start failure."""
|
|
with mock.patch(
|
|
"controller.api.services.start_service",
|
|
return_value={"success": False, "error": "Failed to start"}
|
|
):
|
|
response = test_client.post("/api/services/wrolpi-api/start")
|
|
assert response.status_code == 500
|
|
|
|
@pytest.mark.parametrize("endpoint", [
|
|
"/api/services/wrolpi-api/enable",
|
|
"/api/services/wrolpi-api/disable",
|
|
])
|
|
def test_enable_disable_not_available_in_docker(self, test_client_docker_mode, endpoint):
|
|
"""Should return 501 in Docker mode for enable/disable."""
|
|
response = test_client_docker_mode.post(endpoint)
|
|
assert response.status_code == 501
|
|
|
|
|
|
class TestServiceLogsEndpoint:
|
|
"""Tests for /api/services/{name}/logs endpoint."""
|
|
|
|
def test_logs_returns_200(self, test_client):
|
|
"""Should return logs successfully."""
|
|
with mock.patch(
|
|
"controller.api.services.get_service_logs",
|
|
return_value={"service": "wrolpi-api", "lines": 100, "logs": "test logs"}
|
|
):
|
|
response = test_client.get("/api/services/wrolpi-api/logs")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "logs" in data
|
|
|
|
def test_logs_accepts_lines_parameter(self, test_client):
|
|
"""Should accept lines query parameter."""
|
|
with mock.patch(
|
|
"controller.api.services.get_service_logs",
|
|
return_value={"service": "wrolpi-api", "lines": 50, "logs": "logs"}
|
|
):
|
|
response = test_client.get("/api/services/wrolpi-api/logs?lines=50")
|
|
assert response.status_code == 200
|
|
|
|
def test_logs_accepts_since_parameter(self, test_client):
|
|
"""Should accept since query parameter."""
|
|
with mock.patch(
|
|
"controller.api.services.get_service_logs",
|
|
return_value={"service": "wrolpi-api", "lines": 100, "since": "1h", "logs": "logs"}
|
|
):
|
|
response = test_client.get("/api/services/wrolpi-api/logs?since=1h")
|
|
assert response.status_code == 200
|
|
|
|
|
|
# OpenAPI endpoint-presence tests are consolidated in test_api.py::TestOpenAPI.
|