generated from personal-projects/leo-claude-mktplace
Create test suite for wrapper functionality
This commit implements a comprehensive test suite for the HTTP wrapper components. Test coverage: - test_config.py: Configuration loader and validation tests - Required field validation - URL validation and formatting - Port range validation - Tool list parsing (enabled/disabled) - Environment variable generation - .env file loading - test_filtering.py: Tool filtering tests - Passthrough mode (no filtering) - Whitelist mode (enabled_tools) - Blacklist mode (disabled_tools) - Tool list filtering - MCP response filtering - Edge cases (empty lists, missing names) - test_middleware.py: HTTP authentication tests - BearerAuthMiddleware with/without token - Valid/invalid token handling - Missing/malformed Authorization headers - HTTP status codes (401, 403) - HealthCheckBypassMiddleware - Custom health check paths - Middleware ordering Test infrastructure: - conftest.py: Shared fixtures for common test data - pytest.ini: Test configuration and markers - Updated dev dependencies with test frameworks Test execution: - Run all tests: pytest - Run with coverage: pytest --cov=gitea_http_wrapper - Run specific test: pytest src/gitea_http_wrapper/tests/test_config.py This test suite validates all wrapper components except the main server (which would require integration tests with a real Gitea MCP server). Closes #17 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
162
src/gitea_http_wrapper/tests/test_middleware.py
Normal file
162
src/gitea_http_wrapper/tests/test_middleware.py
Normal file
@@ -0,0 +1,162 @@
|
||||
"""Tests for HTTP authentication middleware."""
|
||||
|
||||
import pytest
|
||||
from starlette.applications import Starlette
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import Route
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from gitea_http_wrapper.middleware import (
|
||||
BearerAuthMiddleware,
|
||||
HealthCheckBypassMiddleware,
|
||||
)
|
||||
|
||||
|
||||
# Test application endpoint
|
||||
async def test_endpoint(request):
|
||||
return JSONResponse({"message": "success"})
|
||||
|
||||
|
||||
class TestBearerAuthMiddleware:
|
||||
"""Test BearerAuthMiddleware."""
|
||||
|
||||
def test_no_auth_configured(self):
|
||||
"""Test that requests pass through when no auth token is configured."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token=None)
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/test")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["message"] == "success"
|
||||
|
||||
def test_auth_configured_valid_token(self):
|
||||
"""Test successful authentication with valid token."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/test", headers={"Authorization": "Bearer secret_token"})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["message"] == "success"
|
||||
|
||||
def test_auth_configured_missing_header(self):
|
||||
"""Test rejection when Authorization header is missing."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/test")
|
||||
|
||||
assert response.status_code == 401
|
||||
assert "Missing Authorization header" in response.json()["message"]
|
||||
|
||||
def test_auth_configured_invalid_format(self):
|
||||
"""Test rejection when Authorization header has wrong format."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
# Test with wrong scheme
|
||||
response = client.get("/test", headers={"Authorization": "Basic secret_token"})
|
||||
assert response.status_code == 401
|
||||
assert "Bearer scheme" in response.json()["message"]
|
||||
|
||||
# Test with no scheme
|
||||
response = client.get("/test", headers={"Authorization": "secret_token"})
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_auth_configured_invalid_token(self):
|
||||
"""Test rejection when token is invalid."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/test", headers={"Authorization": "Bearer wrong_token"})
|
||||
|
||||
assert response.status_code == 403
|
||||
assert "Invalid authentication token" in response.json()["message"]
|
||||
|
||||
def test_auth_case_sensitive_token(self):
|
||||
"""Test that token comparison is case-sensitive."""
|
||||
app = Starlette(routes=[Route("/test", test_endpoint)])
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="Secret_Token")
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
# Correct case
|
||||
response = client.get("/test", headers={"Authorization": "Bearer Secret_Token"})
|
||||
assert response.status_code == 200
|
||||
|
||||
# Wrong case
|
||||
response = client.get("/test", headers={"Authorization": "Bearer secret_token"})
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
class TestHealthCheckBypassMiddleware:
|
||||
"""Test HealthCheckBypassMiddleware."""
|
||||
|
||||
def test_default_health_check_paths(self):
|
||||
"""Test that default health check paths bypass auth."""
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Route("/health", test_endpoint),
|
||||
Route("/healthz", test_endpoint),
|
||||
Route("/ping", test_endpoint),
|
||||
Route("/test", test_endpoint),
|
||||
]
|
||||
)
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
app.add_middleware(HealthCheckBypassMiddleware)
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
# Health checks should work without auth
|
||||
assert client.get("/health").status_code == 200
|
||||
assert client.get("/healthz").status_code == 200
|
||||
assert client.get("/ping").status_code == 200
|
||||
|
||||
# Regular endpoint should require auth
|
||||
assert client.get("/test").status_code == 401
|
||||
|
||||
def test_custom_health_check_paths(self):
|
||||
"""Test custom health check paths."""
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Route("/custom-health", test_endpoint),
|
||||
Route("/test", test_endpoint),
|
||||
]
|
||||
)
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
app.add_middleware(
|
||||
HealthCheckBypassMiddleware,
|
||||
health_check_paths=["/custom-health"],
|
||||
)
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
# Custom health check should work without auth
|
||||
assert client.get("/custom-health").status_code == 200
|
||||
|
||||
# Regular endpoint should require auth
|
||||
assert client.get("/test").status_code == 401
|
||||
|
||||
def test_middleware_order(self):
|
||||
"""Test that middleware order is correct."""
|
||||
# HealthCheckBypass should be added BEFORE BearerAuth
|
||||
# so it can bypass the auth check
|
||||
|
||||
app = Starlette(routes=[Route("/health", test_endpoint)])
|
||||
|
||||
# Correct order: HealthCheck bypass first, then Auth
|
||||
app.add_middleware(BearerAuthMiddleware, auth_token="secret_token")
|
||||
app.add_middleware(HealthCheckBypassMiddleware)
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/health")
|
||||
|
||||
# Should succeed without auth
|
||||
assert response.status_code == 200
|
||||
Reference in New Issue
Block a user