wrongmove/tests/unit/test_security_headers.py
Viktor Barzin 492921424e
Add security regression tests for all hardening fixes
- New: test_security_headers.py — verify all headers present, HSTS conditional on HTTPS
- New: test_passkey_error_handling.py — generic vs user-facing error messages
- New: test_poi_validation.py — field length and coordinate range constraints
- Extend test_rate_limiter.py — client IP depth selection, in-memory fallback enforcement
- Extend test_models.py — sqm range validation
- Extend test_task_service.py — IDOR 404, ownership 200, traceback suppression in production
2026-02-08 19:42:53 +00:00

56 lines
2 KiB
Python

"""Unit tests for api/security_headers.py."""
from starlette.testclient import TestClient
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route
from api.security_headers import SecurityHeadersMiddleware
async def _ok_endpoint(request: Request) -> JSONResponse:
return JSONResponse({"ok": True})
def _build_app() -> Starlette:
app = Starlette(routes=[Route("/test", _ok_endpoint)])
app.add_middleware(SecurityHeadersMiddleware)
return app
class TestSecurityHeaders:
"""Tests for SecurityHeadersMiddleware."""
def test_x_content_type_options(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test")
assert resp.headers["X-Content-Type-Options"] == "nosniff"
def test_x_frame_options(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test")
assert resp.headers["X-Frame-Options"] == "DENY"
def test_referrer_policy(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test")
assert resp.headers["Referrer-Policy"] == "strict-origin-when-cross-origin"
def test_content_security_policy(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test")
assert "Content-Security-Policy" in resp.headers
csp = resp.headers["Content-Security-Policy"]
assert "default-src 'self'" in csp
assert "frame-ancestors 'none'" in csp
def test_hsts_set_for_https(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test", headers={"x-forwarded-proto": "https"})
assert "Strict-Transport-Security" in resp.headers
assert "max-age=" in resp.headers["Strict-Transport-Security"]
def test_hsts_not_set_for_http(self) -> None:
client = TestClient(_build_app())
resp = client.get("/test")
assert "Strict-Transport-Security" not in resp.headers