"""Unit-тесты consumer-PII scrubber для GlitchTip (#396).""" import os os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test") from app.observability.sentry_scrub import scrub_pii_event def test_redacts_pii_in_request_data() -> None: event = { "request": { "data": { "client_name": "Иван Иванов", "client_phone": "+79991234567", "client_email": "ivan@example.com", "address": "Екатеринбург, ул. Ленина 1", } } } out = scrub_pii_event(event, {}) data = out["request"]["data"] assert data["client_name"] == "[REDACTED]" assert data["client_phone"] == "[REDACTED]" assert data["client_email"] == "[REDACTED]" # non-PII поле не трогаем assert data["address"] == "Екатеринбург, ул. Ленина 1" def test_redacts_pii_in_extra() -> None: event = { "extra": { "phone": "+79990000000", "email": "x@y.ru", "name": "Пётр", "estimate_id": 42, } } out = scrub_pii_event(event, {}) extra = out["extra"] assert extra["phone"] == "[REDACTED]" assert extra["email"] == "[REDACTED]" assert extra["name"] == "[REDACTED]" assert extra["estimate_id"] == 42 def test_redact_is_case_insensitive() -> None: event = {"extra": {"Client_Name": "Анна", "CLIENT_PHONE": "+7900"}} out = scrub_pii_event(event, {}) assert out["extra"]["Client_Name"] == "[REDACTED]" assert out["extra"]["CLIENT_PHONE"] == "[REDACTED]" def test_redacts_nested_pii_in_contexts() -> None: event = {"contexts": {"trace": {"op": "http"}, "consumer": {"client_email": "z@z.ru"}}} out = scrub_pii_event(event, {}) assert out["contexts"]["consumer"]["client_email"] == "[REDACTED]" # вложенный non-PII контекст не трогаем assert out["contexts"]["trace"]["op"] == "http" def test_leaves_non_pii_untouched() -> None: event = { "request": {"data": {"region": "66", "area_sqm": 50}}, "extra": {"job": "geocode"}, "level": "error", } out = scrub_pii_event(event, {}) assert out["request"]["data"] == {"region": "66", "area_sqm": 50} assert out["extra"] == {"job": "geocode"} assert out["level"] == "error" def test_handles_missing_sections() -> None: out = scrub_pii_event({}, {}) assert out == {} def test_handles_none_and_non_dict_sections() -> None: event = {"request": None, "extra": None, "contexts": "not-a-dict"} # не должно бросать исключений out = scrub_pii_event(event, {}) assert out is event def test_returns_event_not_none() -> None: """before_send должен вернуть event (не None) — иначе SDK дропнет отчёт.""" event = {"request": {"data": {"client_name": "X"}}} out = scrub_pii_event(event, {}) assert out is not None assert out is event