Files
consentos/apps/api/tests/test_cors.py
James Cottrill fbf26453f2 feat: initial public release
ConsentOS — a privacy-first cookie consent management platform.

Self-hosted, source-available alternative to OneTrust, Cookiebot, and
CookieYes. Full standards coverage (IAB TCF v2.2, GPP v1, Google
Consent Mode v2, GPC, Shopify Customer Privacy API), multi-tenant
architecture with role-based access, configuration cascade
(system → org → group → site → region), dark-pattern detection in
the scanner, and a tamper-evident consent record audit trail.

This is the initial public release. Prior development history is
retained internally.

See README.md for the feature list, architecture overview, and
quick-start instructions. Licensed under the Elastic Licence 2.0 —
self-host freely; do not resell as a managed service.
2026-04-14 09:18:18 +00:00

223 lines
5.9 KiB
Python

"""Tests for the dynamic CORS origin validation service."""
from unittest.mock import AsyncMock, MagicMock
import pytest
from src.services.cors import extract_domain_from_origin, get_allowed_domains, is_origin_allowed
class TestExtractDomainFromOrigin:
def test_https_origin(self):
assert extract_domain_from_origin("https://example.com") == "example.com"
def test_http_origin(self):
assert extract_domain_from_origin("http://example.com") == "example.com"
def test_origin_with_port(self):
assert extract_domain_from_origin("https://example.com:443") == "example.com"
def test_origin_with_subdomain(self):
assert extract_domain_from_origin("https://www.example.com") == "www.example.com"
def test_localhost(self):
assert extract_domain_from_origin("http://localhost:5173") == "localhost"
def test_empty_string(self):
assert extract_domain_from_origin("") is None
def test_invalid_url(self):
# urlparse is lenient, but hostname may be None for really bad input
result = extract_domain_from_origin("not-a-url")
# urlparse("not-a-url") sets hostname to None
assert result is None
class TestIsOriginAllowed:
def test_static_origin_exact_match(self):
assert (
is_origin_allowed(
"http://localhost:5173",
["http://localhost:5173"],
set(),
)
is True
)
def test_static_origin_no_match(self):
assert (
is_origin_allowed(
"https://evil.com",
["http://localhost:5173"],
set(),
)
is False
)
def test_wildcard_allows_everything(self):
assert (
is_origin_allowed(
"https://anything.com",
["*"],
set(),
)
is True
)
def test_registered_domain_match(self):
assert (
is_origin_allowed(
"https://example.com",
[],
{"example.com", "other.com"},
)
is True
)
def test_registered_domain_case_insensitive(self):
assert (
is_origin_allowed(
"https://Example.COM",
[],
{"example.com"},
)
is True
)
def test_registered_domain_no_match(self):
assert (
is_origin_allowed(
"https://evil.com",
[],
{"example.com"},
)
is False
)
def test_static_takes_priority(self):
assert (
is_origin_allowed(
"http://localhost:5173",
["http://localhost:5173"],
{"example.com"},
)
is True
)
def test_origin_with_port_matches_domain(self):
assert (
is_origin_allowed(
"https://example.com:8443",
[],
{"example.com"},
)
is True
)
def test_subdomain_matches_if_registered(self):
# www.example.com only matches if explicitly registered
assert (
is_origin_allowed(
"https://www.example.com",
[],
{"example.com"},
)
is False
)
def test_subdomain_matches_when_registered(self):
assert (
is_origin_allowed(
"https://www.example.com",
[],
{"www.example.com"},
)
is True
)
def test_empty_origin(self):
assert (
is_origin_allowed(
"",
[],
{"example.com"},
)
is False
)
def test_empty_lists(self):
assert (
is_origin_allowed(
"https://example.com",
[],
set(),
)
is False
)
class TestGetAllowedDomains:
@pytest.mark.asyncio
async def test_returns_primary_domains(self):
row1 = MagicMock()
row1.domain = "example.com"
row1.additional_domains = None
row2 = MagicMock()
row2.domain = "other.com"
row2.additional_domains = None
mock_result = MagicMock()
mock_result.all.return_value = [row1, row2]
db = AsyncMock()
db.execute = AsyncMock(return_value=mock_result)
domains = await get_allowed_domains(db)
assert "example.com" in domains
assert "other.com" in domains
@pytest.mark.asyncio
async def test_includes_additional_domains(self):
row = MagicMock()
row.domain = "example.com"
row.additional_domains = ["www.example.com", "app.example.com"]
mock_result = MagicMock()
mock_result.all.return_value = [row]
db = AsyncMock()
db.execute = AsyncMock(return_value=mock_result)
domains = await get_allowed_domains(db)
assert "example.com" in domains
assert "www.example.com" in domains
assert "app.example.com" in domains
@pytest.mark.asyncio
async def test_lowercases_domains(self):
row = MagicMock()
row.domain = "Example.COM"
row.additional_domains = ["WWW.Example.COM"]
mock_result = MagicMock()
mock_result.all.return_value = [row]
db = AsyncMock()
db.execute = AsyncMock(return_value=mock_result)
domains = await get_allowed_domains(db)
assert "example.com" in domains
assert "www.example.com" in domains
@pytest.mark.asyncio
async def test_empty_result(self):
mock_result = MagicMock()
mock_result.all.return_value = []
db = AsyncMock()
db.execute = AsyncMock(return_value=mock_result)
domains = await get_allowed_domains(db)
assert domains == set()