feat: comprehensive test infrastructure improvements
- Fix unit test imports: add env setup in conftest.py before module imports - Add 24 new auth router tests (RBAC, preferences, password validation) - Add 16 new tests for litellm and chat_summary routers - Apply black formatting and ruff linting across codebase - Add pre-commit hooks configuration (black, ruff, file checks) - Increase CI coverage threshold from 40% to 50% Test Results: - 206 tests passing (91 unit + 115 integration) - Coverage: 58.79% on core modules - auth.py: 57% → 85%, litellm.py: 23% → 87%, chat_summary.py: 41% → 100% - auth_service: 96.51%, config: 100%, rbac: 93.48%
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
"""
|
||||
Integration tests for system operations.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import os
|
||||
from unittest.mock import patch, Mock
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestSystemStats:
|
||||
@@ -17,7 +19,7 @@ class TestSystemStats:
|
||||
mock_disk.used = 500000000000
|
||||
mock_disk.free = 500000000000
|
||||
|
||||
with patch('shutil.disk_usage', return_value=mock_disk):
|
||||
with patch("shutil.disk_usage", return_value=mock_disk):
|
||||
response = test_app.get("/api/system/stats", headers=admin_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -81,11 +83,7 @@ class TestAuditLog:
|
||||
|
||||
def test_get_audit_log_with_limit(self, test_app, admin_headers, temp_volume_root):
|
||||
"""Test getting audit log with line limit."""
|
||||
response = test_app.get(
|
||||
"/api/system/audit-log",
|
||||
headers=admin_headers,
|
||||
params={"lines": 50}
|
||||
)
|
||||
response = test_app.get("/api/system/audit-log", headers=admin_headers, params={"lines": 50})
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
@@ -104,22 +102,14 @@ class TestNotification:
|
||||
@pytest.mark.skip(reason="Requires Telegram bot token and makes external API call")
|
||||
def test_send_notification_success(self, test_app, admin_headers):
|
||||
"""Test sending a notification."""
|
||||
response = test_app.post(
|
||||
"/api/system/notify",
|
||||
headers=admin_headers,
|
||||
json={"message": "Test notification"}
|
||||
)
|
||||
response = test_app.post("/api/system/notify", headers=admin_headers, json={"message": "Test notification"})
|
||||
|
||||
# This will fail without proper Telegram config
|
||||
assert response.status_code in [200, 400]
|
||||
|
||||
def test_send_notification_without_message(self, test_app, admin_headers):
|
||||
"""Test sending notification without message."""
|
||||
response = test_app.post(
|
||||
"/api/system/notify",
|
||||
headers=admin_headers,
|
||||
json={}
|
||||
)
|
||||
response = test_app.post("/api/system/notify", headers=admin_headers, json={})
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
@@ -127,10 +117,7 @@ class TestNotification:
|
||||
|
||||
def test_send_notification_without_auth(self, test_app):
|
||||
"""Test sending notification without authentication."""
|
||||
response = test_app.post(
|
||||
"/api/system/notify",
|
||||
json={"message": "Test"}
|
||||
)
|
||||
response = test_app.post("/api/system/notify", json={"message": "Test"})
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
@@ -140,6 +127,7 @@ class TestOpenClawToken:
|
||||
|
||||
def test_get_openclaw_token_as_admin(self, test_app, admin_headers, mock_config, monkeypatch):
|
||||
"""Test getting OpenClaw token as admin from LAN."""
|
||||
|
||||
# Mock the IP check to return a LAN IP
|
||||
def mock_get_client_ip(request):
|
||||
return "192.168.1.100"
|
||||
@@ -148,6 +136,7 @@ class TestOpenClawToken:
|
||||
return True
|
||||
|
||||
import config
|
||||
|
||||
monkeypatch.setattr(config, "get_client_ip", mock_get_client_ip)
|
||||
monkeypatch.setattr(config, "is_lan_ip", mock_is_lan_ip)
|
||||
|
||||
@@ -159,6 +148,7 @@ class TestOpenClawToken:
|
||||
|
||||
def test_get_openclaw_token_non_lan(self, test_app, admin_headers, monkeypatch):
|
||||
"""Test getting OpenClaw token from non-LAN IP."""
|
||||
|
||||
# Mock the IP check to return a non-LAN IP
|
||||
def mock_get_client_ip(request):
|
||||
return "1.2.3.4"
|
||||
@@ -167,6 +157,7 @@ class TestOpenClawToken:
|
||||
return False
|
||||
|
||||
import config
|
||||
|
||||
monkeypatch.setattr(config, "get_client_ip", mock_get_client_ip)
|
||||
monkeypatch.setattr(config, "is_lan_ip", mock_is_lan_ip)
|
||||
|
||||
@@ -176,12 +167,12 @@ class TestOpenClawToken:
|
||||
|
||||
def test_get_openclaw_token_as_member(self, test_app, mock_config, temp_auth_file, temp_rbac_file):
|
||||
"""Test that non-admin cannot get OpenClaw token."""
|
||||
from auth_service import create_access_token
|
||||
from datetime import timedelta
|
||||
|
||||
from auth_service import create_access_token
|
||||
|
||||
member_token = create_access_token(
|
||||
data={"sub": "memberuser", "role": "member"},
|
||||
expires_delta=timedelta(minutes=30)
|
||||
data={"sub": "memberuser", "role": "member"}, expires_delta=timedelta(minutes=30)
|
||||
)
|
||||
headers = {"Authorization": f"Bearer {member_token}"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user