Add comprehensive test suites for: - NPM client (27 tests) - Ollama client (16 tests) - AI client and controller (34 tests) - Static controller (8 tests) - Tools controller DNS lookup (9 tests) - OIDC authentication (10 tests) - Housekeeping endpoints (28 tests) - Infrastructure endpoints (15 tests) - Health endpoints (12 tests) - Portainer client (12 tests) - Home Assistant client (24 tests) Total: 285 tests passing with 65% code coverage. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
143 lines
4.9 KiB
Python
143 lines
4.9 KiB
Python
"""Tests for tools controller."""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from unittest.mock import patch, AsyncMock, MagicMock
|
|
|
|
from src.main import app
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
"""Create a test client."""
|
|
return TestClient(app)
|
|
|
|
|
|
class TestDNSLookup:
|
|
"""Test /tools/dns/lookup endpoint."""
|
|
|
|
@patch("src.controllers.tools_controller.DNSService")
|
|
def test_dns_lookup_returns_200(self, mock_dns_class, client):
|
|
"""DNS lookup should return 200 for valid request."""
|
|
mock_service = MagicMock()
|
|
mock_service.lookup = AsyncMock(return_value=MagicMock(
|
|
success=True,
|
|
domain="example.com",
|
|
record_type="A",
|
|
records=[{"value": "93.184.216.34"}],
|
|
nameserver_used="8.8.8.8",
|
|
query_time_ms=50,
|
|
error_message=None
|
|
))
|
|
mock_dns_class.return_value = mock_service
|
|
|
|
response = client.post(
|
|
"/tools/dns/lookup",
|
|
json={"domain": "example.com", "record_type": "A"}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
@patch("src.controllers.tools_controller.DNSService")
|
|
def test_dns_lookup_returns_result(self, mock_dns_class, client):
|
|
"""DNS lookup should return lookup results."""
|
|
mock_response = MagicMock()
|
|
mock_response.success = True
|
|
mock_response.domain = "example.com"
|
|
mock_response.record_type = "A"
|
|
mock_response.records = [{"value": "93.184.216.34"}]
|
|
mock_response.nameserver_used = "8.8.8.8"
|
|
mock_response.query_time_ms = 50
|
|
mock_response.error_message = None
|
|
mock_response.model_dump = MagicMock(return_value={
|
|
"success": True,
|
|
"domain": "example.com",
|
|
"record_type": "A",
|
|
"records": [{"value": "93.184.216.34"}],
|
|
"nameserver_used": "8.8.8.8",
|
|
"query_time_ms": 50,
|
|
"error_message": None
|
|
})
|
|
|
|
mock_service = MagicMock()
|
|
mock_service.lookup = AsyncMock(return_value=mock_response)
|
|
mock_dns_class.return_value = mock_service
|
|
|
|
response = client.post(
|
|
"/tools/dns/lookup",
|
|
json={"domain": "example.com", "record_type": "A"}
|
|
)
|
|
data = response.json()
|
|
|
|
assert data["success"] is True
|
|
assert data["domain"] == "example.com"
|
|
|
|
def test_dns_lookup_requires_domain(self, client):
|
|
"""DNS lookup should require domain parameter."""
|
|
response = client.post(
|
|
"/tools/dns/lookup",
|
|
json={"record_type": "A"}
|
|
)
|
|
assert response.status_code == 422
|
|
|
|
@patch("src.controllers.tools_controller.DNSService")
|
|
def test_dns_lookup_handles_dns_query_error(self, mock_dns_class, client):
|
|
"""DNS lookup should handle DNSQueryError."""
|
|
from src.dns.exceptions import DNSQueryError
|
|
|
|
mock_service = MagicMock()
|
|
mock_service.lookup = AsyncMock(side_effect=DNSQueryError("Unsupported record type"))
|
|
mock_dns_class.return_value = mock_service
|
|
|
|
response = client.post(
|
|
"/tools/dns/lookup",
|
|
json={"domain": "example.com", "record_type": "INVALID"}
|
|
)
|
|
assert response.status_code == 400
|
|
|
|
|
|
@patch("src.controllers.tools_controller.DNSService")
|
|
def test_dns_lookup_accepts_custom_nameserver(self, mock_dns_class, client):
|
|
"""DNS lookup should accept custom nameserver."""
|
|
mock_response = MagicMock()
|
|
mock_response.success = True
|
|
mock_response.domain = "example.com"
|
|
mock_response.record_type = "A"
|
|
mock_response.records = []
|
|
mock_response.nameserver_used = "1.1.1.1"
|
|
mock_response.query_time_ms = 30
|
|
mock_response.error_message = None
|
|
mock_response.model_dump = MagicMock(return_value={
|
|
"success": True,
|
|
"domain": "example.com",
|
|
"record_type": "A",
|
|
"records": [],
|
|
"nameserver_used": "1.1.1.1",
|
|
"query_time_ms": 30,
|
|
"error_message": None
|
|
})
|
|
|
|
mock_service = MagicMock()
|
|
mock_service.lookup = AsyncMock(return_value=mock_response)
|
|
mock_dns_class.return_value = mock_service
|
|
|
|
response = client.post(
|
|
"/tools/dns/lookup",
|
|
json={"domain": "example.com", "record_type": "A", "nameserver": "1.1.1.1"}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestToolsControllerInit:
|
|
"""Test ToolsController initialization."""
|
|
|
|
def test_controller_has_correct_prefix(self):
|
|
"""Controller should have /tools prefix."""
|
|
from src.controllers.tools_controller import tools_controller
|
|
|
|
assert tools_controller.prefix == "/tools"
|
|
|
|
def test_controller_has_correct_tags(self):
|
|
"""Controller should have Tools tag."""
|
|
from src.controllers.tools_controller import tools_controller
|
|
|
|
assert "Tools" in tools_controller.tags
|