Files
gitea-mcp-remote/src/gitea_http_wrapper/tests/test_middleware.py
lmiranda 4e81b9bb96 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>
2026-02-03 16:55:49 -05:00

163 lines
5.8 KiB
Python

"""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