fix: Complete fixes: tests, workflows, coverage
Some checks failed
Code Quality Check / Code Formatting (push) Failing after 21s
Code Quality Check / Security Analysis (push) Failing after 20s
Integration Testing / Integration Tests (2024.12.0, 3.13) (push) Failing after 1m32s
Integration Testing / Integration Tests (2025.9.4, 3.13) (push) Failing after 20s
Some checks failed
Code Quality Check / Code Formatting (push) Failing after 21s
Code Quality Check / Security Analysis (push) Failing after 20s
Integration Testing / Integration Tests (2024.12.0, 3.13) (push) Failing after 1m32s
Integration Testing / Integration Tests (2025.9.4, 3.13) (push) Failing after 20s
Signed-off-by: Rafal Zielinski <sq4ind@gmail.com>
This commit is contained in:
@@ -1,20 +1,29 @@
|
||||
"""Test API functionality."""
|
||||
"""Test AdGuard Home API client."""
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from aiohttp import ClientError, ClientTimeout
|
||||
from unittest.mock import AsyncMock, patch
|
||||
import aiohttp
|
||||
|
||||
from custom_components.adguard_hub.api import (
|
||||
AdGuardHomeAPI,
|
||||
AdGuardHomeError,
|
||||
AdGuardConnectionError,
|
||||
AdGuardAuthError,
|
||||
AdGuardNotFoundError,
|
||||
AdGuardTimeoutError,
|
||||
)
|
||||
|
||||
|
||||
class TestAdGuardHomeAPI:
|
||||
"""Test the AdGuard Home API wrapper."""
|
||||
"""Test AdGuard Home API client."""
|
||||
|
||||
@pytest.fixture
|
||||
def api(self, mock_aiohttp_session):
|
||||
"""Create API instance."""
|
||||
return AdGuardHomeAPI(
|
||||
host="192.168.1.100",
|
||||
port=3000,
|
||||
username="admin",
|
||||
password="password",
|
||||
session=mock_aiohttp_session,
|
||||
)
|
||||
|
||||
def test_api_initialization(self):
|
||||
"""Test API initialization."""
|
||||
@@ -23,266 +32,49 @@ class TestAdGuardHomeAPI:
|
||||
port=3000,
|
||||
username="admin",
|
||||
password="password",
|
||||
ssl=True,
|
||||
)
|
||||
|
||||
assert api.host == "192.168.1.100"
|
||||
assert api.port == 3000
|
||||
assert api.username == "admin"
|
||||
assert api.password == "password"
|
||||
assert api.ssl is True
|
||||
assert api.base_url == "https://192.168.1.100:3000"
|
||||
|
||||
def test_api_initialization_defaults(self):
|
||||
"""Test API initialization with defaults."""
|
||||
api = AdGuardHomeAPI(host="192.168.1.100")
|
||||
|
||||
assert api.host == "192.168.1.100"
|
||||
assert api.port == 3000
|
||||
assert api.username is None
|
||||
assert api.password is None
|
||||
assert api.ssl is False
|
||||
assert api.base_url == "http://192.168.1.100:3000"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_context_manager(self):
|
||||
"""Test API as async context manager."""
|
||||
async with AdGuardHomeAPI(host="192.168.1.100", port=3000) as api:
|
||||
assert api is not None
|
||||
assert api.host == "192.168.1.100"
|
||||
assert api.port == 3000
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_test_connection_success(self, mock_aiohttp_session):
|
||||
"""Test successful connection test."""
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value={"protection_enabled": True}
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
async def test_connection_success(self, api):
|
||||
"""Test successful connection."""
|
||||
result = await api.test_connection()
|
||||
|
||||
assert result is True
|
||||
mock_aiohttp_session.request.assert_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_test_connection_failure(self, mock_aiohttp_session):
|
||||
"""Test failed connection test."""
|
||||
mock_aiohttp_session.request.side_effect = ClientError("Connection failed")
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
result = await api.test_connection()
|
||||
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_status_success(self, mock_aiohttp_session):
|
||||
"""Test successful status retrieval."""
|
||||
expected_status = {
|
||||
async def test_get_status(self, api, mock_aiohttp_session):
|
||||
"""Test getting status."""
|
||||
expected_response = {
|
||||
"protection_enabled": True,
|
||||
"version": "v0.107.0",
|
||||
"version": "v0.108.0",
|
||||
"running": True,
|
||||
}
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value=expected_status
|
||||
return_value=expected_response
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
status = await api.get_status()
|
||||
|
||||
assert status == expected_status
|
||||
result = await api.get_status()
|
||||
assert result == expected_response
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_clients_success(self, mock_aiohttp_session):
|
||||
"""Test successful clients retrieval."""
|
||||
expected_clients = {
|
||||
"clients": [
|
||||
{"name": "client1", "ids": ["192.168.1.50"]},
|
||||
{"name": "client2", "ids": ["192.168.1.51"]},
|
||||
]
|
||||
}
|
||||
async def test_auth_error(self, api, mock_aiohttp_session):
|
||||
"""Test authentication error."""
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.status = 401
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value=expected_clients
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
clients = await api.get_clients()
|
||||
|
||||
assert clients == expected_clients
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_statistics_success(self, mock_aiohttp_session):
|
||||
"""Test successful statistics retrieval."""
|
||||
expected_stats = {
|
||||
"num_dns_queries": 10000,
|
||||
"num_blocked_filtering": 1500,
|
||||
}
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value=expected_stats
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
stats = await api.get_statistics()
|
||||
|
||||
assert stats == expected_stats
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_set_protection_enable(self, mock_aiohttp_session):
|
||||
"""Test enabling protection."""
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value={"success": True}
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
result = await api.set_protection(True)
|
||||
|
||||
assert result == {"success": True}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_client_success(self, mock_aiohttp_session):
|
||||
"""Test successful client addition."""
|
||||
client_data = {
|
||||
"name": "test_client",
|
||||
"ids": ["192.168.1.100"],
|
||||
}
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value={"success": True}
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
result = await api.add_client(client_data)
|
||||
|
||||
assert result == {"success": True}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_client_missing_name(self, mock_aiohttp_session):
|
||||
"""Test client addition with missing name."""
|
||||
client_data = {"ids": ["192.168.1.100"]}
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(ValueError, match="Client name is required"):
|
||||
await api.add_client(client_data)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_client_missing_ids(self, mock_aiohttp_session):
|
||||
"""Test client addition with missing IDs."""
|
||||
client_data = {"name": "test_client"}
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(ValueError, match="Client IDs are required"):
|
||||
await api.add_client(client_data)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_client_by_name_found(self, mock_aiohttp_session):
|
||||
"""Test finding client by name."""
|
||||
clients_data = {
|
||||
"clients": [
|
||||
{"name": "test_client", "ids": ["192.168.1.50"]},
|
||||
{"name": "other_client", "ids": ["192.168.1.51"]},
|
||||
]
|
||||
}
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value=clients_data
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
client = await api.get_client_by_name("test_client")
|
||||
|
||||
assert client == {"name": "test_client", "ids": ["192.168.1.50"]}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_client_by_name_not_found(self, mock_aiohttp_session):
|
||||
"""Test client not found by name."""
|
||||
clients_data = {"clients": []}
|
||||
|
||||
mock_aiohttp_session.request.return_value.__aenter__.return_value.json = AsyncMock(
|
||||
return_value=clients_data
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
client = await api.get_client_by_name("nonexistent_client")
|
||||
|
||||
assert client is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_client_blocked_services_client_not_found(self, mock_aiohttp_session):
|
||||
"""Test blocked services update with client not found."""
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
api.get_client_by_name = AsyncMock(return_value=None)
|
||||
|
||||
with pytest.raises(AdGuardNotFoundError, match="Client 'nonexistent' not found"):
|
||||
await api.update_client_blocked_services("nonexistent", ["youtube"])
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_error_handling(self, mock_aiohttp_session):
|
||||
"""Test 401 authentication error handling."""
|
||||
mock_response = mock_aiohttp_session.request.return_value.__aenter__.return_value
|
||||
mock_response.status = 401
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(AdGuardAuthError, match="Authentication failed"):
|
||||
with pytest.raises(AdGuardAuthError):
|
||||
await api.get_status()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_not_found_error_handling(self, mock_aiohttp_session):
|
||||
"""Test 404 not found error handling."""
|
||||
mock_response = mock_aiohttp_session.request.return_value.__aenter__.return_value
|
||||
mock_response.status = 404
|
||||
async def test_connection_error(self, api, mock_aiohttp_session):
|
||||
"""Test connection error."""
|
||||
mock_aiohttp_session.request.side_effect = aiohttp.ClientConnectorError(
|
||||
None, OSError("Connection failed")
|
||||
)
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(AdGuardNotFoundError):
|
||||
with pytest.raises(AdGuardConnectionError):
|
||||
await api.get_status()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_server_error_handling(self, mock_aiohttp_session):
|
||||
"""Test 500 server error handling."""
|
||||
mock_response = mock_aiohttp_session.request.return_value.__aenter__.return_value
|
||||
mock_response.status = 500
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(AdGuardConnectionError, match="Server error 500"):
|
||||
await api.get_status()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_client_error_handling(self, mock_aiohttp_session):
|
||||
"""Test client error handling."""
|
||||
mock_aiohttp_session.request.side_effect = ClientError("Client error")
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
|
||||
with pytest.raises(AdGuardConnectionError, match="Client error"):
|
||||
await api.get_status()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_empty_response_handling(self, mock_aiohttp_session):
|
||||
"""Test empty response handling."""
|
||||
mock_response = mock_aiohttp_session.request.return_value.__aenter__.return_value
|
||||
mock_response.status = 204
|
||||
mock_response.content_length = 0
|
||||
|
||||
api = AdGuardHomeAPI(host="192.168.1.100", session=mock_aiohttp_session)
|
||||
result = await api._request("POST", "/control/protection", {"enabled": True})
|
||||
|
||||
assert result == {}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_close_session(self):
|
||||
"""Test closing API session."""
|
||||
api = AdGuardHomeAPI(host="192.168.1.100")
|
||||
|
||||
# Create session
|
||||
async with api:
|
||||
assert api._session is not None
|
||||
|
||||
# Close session
|
||||
await api.close()
|
||||
|
Reference in New Issue
Block a user