Files

126 lines
5.3 KiB
Python
Raw Permalink Normal View History

"""Unit tests for CORS middleware.
WHAT: Tests for the CORS middleware configuration, including wildcard
origin handling, credentials support, and preflight responses.
WHY: CORS misconfiguration can break browser clients or leak credentials.
EXPECTED: Correct Access-Control-* headers for all origin configurations.
"""
import pytest
from flask import Flask
from gatehouse_app.middleware.cors import (
_is_origin_allowed,
_cors_origin_header,
setup_cors,
)
# ---------------------------------------------------------------------------
# _is_origin_allowed
# ---------------------------------------------------------------------------
class TestIsOriginAllowed:
def test_empty_origin_rejected(self):
"""TEST: CORS-01 -- Empty origin is never allowed."""
assert _is_origin_allowed("", ["https://example.com"]) is False
assert _is_origin_allowed(None, "*") is False
def test_wildcard_string(self):
"""TEST: CORS-02 -- Wildcard string allows any origin."""
assert _is_origin_allowed("https://evil.com", "*") is True
def test_wildcard_in_list(self):
"""TEST: CORS-03 -- Wildcard in list allows any origin."""
assert _is_origin_allowed("https://evil.com", ["*", "https://example.com"]) is True
def test_explicit_origin_match(self):
"""TEST: CORS-04 -- Explicit list matches exact origin."""
origins = ["https://example.com", "http://localhost:3000"]
assert _is_origin_allowed("https://example.com", origins) is True
assert _is_origin_allowed("https://evil.com", origins) is False
def test_empty_origins_list(self):
"""TEST: CORS-05 -- Empty list rejects everything."""
assert _is_origin_allowed("https://example.com", []) is False
# ---------------------------------------------------------------------------
# _cors_origin_header
# ---------------------------------------------------------------------------
class TestCorsOriginHeader:
def test_wildcard_with_origin_echoes(self):
"""TEST: CORS-HDR-01 -- Wildcard echoes request origin (for credentials)."""
assert _cors_origin_header("*", "https://example.com") == "https://example.com"
def test_wildcard_without_origin(self):
"""TEST: CORS-HDR-02 -- Wildcard with no origin returns *."""
assert _cors_origin_header("*", None) == "*"
def test_wildcard_in_list_with_origin(self):
"""TEST: CORS-HDR-03 -- Wildcard in list echoes request origin."""
result = _cors_origin_header(["*", "https://example.com"], "https://any.com")
assert result == "https://any.com"
def test_specific_origin_match(self):
"""TEST: CORS-HDR-04 -- Matching origin is echoed."""
origins = ["https://example.com"]
assert _cors_origin_header(origins, "https://example.com") == "https://example.com"
def test_specific_origin_no_match(self):
"""TEST: CORS-HDR-05 -- Non-matching origin returns None."""
origins = ["https://example.com"]
assert _cors_origin_header(origins, "https://evil.com") is None
def test_no_origin_no_match(self):
"""TEST: CORS-HDR-06 -- No origin with specific list returns None."""
origins = ["https://example.com"]
assert _cors_origin_header(origins, None) is None
# ---------------------------------------------------------------------------
# Integration: preflight response
# ---------------------------------------------------------------------------
class TestPreflightIntegration:
@pytest.fixture
def app_wildcard(self):
app = Flask(__name__)
app.config["CORS_ORIGINS"] = "*"
app.config["CORS_SUPPORTS_CREDENTIALS"] = True
setup_cors(app)
app.config["TESTING"] = True
return app
@pytest.fixture
def app_specific(self):
app = Flask(__name__)
app.config["CORS_ORIGINS"] = ["https://example.com"]
app.config["CORS_SUPPORTS_CREDENTIALS"] = True
setup_cors(app)
app.config["TESTING"] = True
return app
def test_wildcard_preflight_echoes_origin(self, app_wildcard):
"""TEST: CORS-PF-01 -- Wildcard preflight echoes request origin."""
with app_wildcard.test_client() as client:
resp = client.options("/", headers={"Origin": "https://example.com"})
assert resp.status_code == 204
assert resp.headers.get("Access-Control-Allow-Origin") == "https://example.com"
assert resp.headers.get("Access-Control-Allow-Credentials") == "true"
def test_specific_origin_preflight(self, app_specific):
"""TEST: CORS-PF-02 -- Specific origin preflight allows matching origin."""
with app_specific.test_client() as client:
resp = client.options("/", headers={"Origin": "https://example.com"})
assert resp.status_code == 204
assert resp.headers.get("Access-Control-Allow-Origin") == "https://example.com"
assert resp.headers.get("Access-Control-Allow-Credentials") == "true"
def test_specific_origin_rejects_unknown(self, app_specific):
"""TEST: CORS-PF-03 -- Non-matching origin gets no CORS headers."""
with app_specific.test_client() as client:
resp = client.options("/", headers={"Origin": "https://evil.com"})
# No preflight handler runs, Flask returns default
assert resp.headers.get("Access-Control-Allow-Origin") is None