gendesign/backend/tests/api/v1/test_admin_ekburg_permits.py
Light1YT e9585bcd3b
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 1m8s
Deploy / build-backend (push) Successful in 36s
Deploy / deploy (push) Successful in 1m13s
test(suite): re-align drifted tests with current code (CI-rehab 2/3)
Suite was uncollectable for a while → code evolved, mocks didn't (42 failed /
5 errors → 1687 passed / 0 failed / 0 errors). TEST-ONLY, no app code changed,
no real bugs found (code-reviewed  — no test weakened to fake-green).

- best_layouts: sum_deals→deals_window rename; velocity-scaling direction for
  new SF-01 divisors (last_month=1.0/last_year=12.0)
- quarter_dump_lookup: 7→10-tuple mock rows (risks/opportunity/red_lines cols);
  fix early-exit call-counts for the cad_zouit fallback (#232)
- cadastre_bulk: add xmin/ymin/xmax/ymax to harvest-quarter db mock
- nspd_client: add required QuarterDump.opportunity
- TopLayoutRow: add required is_oversold
- analyze_{market_price,recent_permits,inline_weights}: SQL-signature dispatch
  instead of fragile positional db.execute indices (SF-B5 query reorder; also
  fixes a double-POST geom-starvation false-negative)
- custom_pois: move centroid >15km so center_bonus=0 isolates custom-POI delta
- layout/report PDF: runtime WeasyPrint probe (skip macOS dev, RUN on CI)
- mv_layout SQL: normalize +psycopg DSN + connectivity-probe skipif
- admin token tests: skip (X-Admin-Token gate removed #437/#426; protection is
  Caddy basic_auth + RBAC, covered by test_rbac)

Refs #944.
2026-06-03 19:05:43 +05:00

91 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Тесты для POST /admin/scrape/ekburg-permits.
Проверяет:
- валидный запрос без year → scope all_years_2022_2026, task_id в ответе
- валидный запрос с year=2026 → scope year_2026
- year < 2022 или > 2030 → 422
- отсутствие X-Admin-Token → 401/503
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import pytest
from fastapi.testclient import TestClient
from app.main import app
ADMIN_TOKEN = "test-admin-token"
ADMIN_HEADERS = {"X-Admin-Token": ADMIN_TOKEN}
ENDPOINT = "/api/v1/admin/scrape/ekburg-permits"
def _mock_task(task_id: str = "fake-task-id-123") -> MagicMock:
result = MagicMock()
result.id = task_id
return result
@patch("app.core.config.settings.scrape_admin_token", ADMIN_TOKEN)
def test_trigger_refresh_all_returns_task_id() -> None:
"""POST без year → refresh_all queued, scope=all_years_2022_2026."""
mock_result = _mock_task("task-all-001")
with (
patch("app.workers.tasks.ekburg_permits_sync.refresh_all") as mock_refresh_all,
patch("app.workers.tasks.ekburg_permits_sync.refresh_year"),
):
mock_refresh_all.apply_async.return_value = mock_result
client = TestClient(app)
response = client.post(ENDPOINT, json={}, headers=ADMIN_HEADERS)
assert response.status_code == 200, response.text
body = response.json()
assert body["task_id"] == "task-all-001"
assert body["scope"] == "all_years_2022_2026"
assert "queued_at" in body
@patch("app.core.config.settings.scrape_admin_token", ADMIN_TOKEN)
def test_trigger_refresh_year_returns_task_id() -> None:
"""POST year=2026 → refresh_year queued, scope=year_2026."""
mock_result = _mock_task("task-year-002")
with (
patch("app.workers.tasks.ekburg_permits_sync.refresh_year") as mock_refresh_year,
patch("app.workers.tasks.ekburg_permits_sync.refresh_all"),
):
mock_refresh_year.apply_async.return_value = mock_result
client = TestClient(app)
response = client.post(ENDPOINT, json={"year": 2026}, headers=ADMIN_HEADERS)
assert response.status_code == 200, response.text
body = response.json()
assert body["task_id"] == "task-year-002"
assert body["scope"] == "year_2026"
@pytest.mark.parametrize("bad_year", [2021, 2031, 1999, 9999])
@patch("app.core.config.settings.scrape_admin_token", ADMIN_TOKEN)
def test_trigger_invalid_year_returns_422(bad_year: int) -> None:
"""year вне диапазона [2022, 2030] → 422 Unprocessable Entity."""
client = TestClient(app)
response = client.post(ENDPOINT, json={"year": bad_year}, headers=ADMIN_HEADERS)
assert response.status_code == 422, f"year={bad_year} должен возвращать 422"
@pytest.mark.skip(
reason=(
"X-Admin-Token gate удалён в #437 (refactor(security): убрать X-Admin-Token — "
"Caddy basic_auth + RBAC middleware достаточны). trigger_ekburg_permits больше не "
"несёт verify_admin_token dependency; защита — на уровне Caddy/RBAC. В test-mode "
"RBAC bypass'ится (CI-rehab 1/3), поэтому 401/503 здесь больше недостижим без "
"реверта security-решения #437. Тест проверял удалённое поведение."
)
)
def test_trigger_no_token_returns_401_or_503() -> None:
"""Без X-Admin-Token → 401 или 503 (устарело: токен-гейт удалён в #437)."""
client = TestClient(app)
response = client.post(ENDPOINT, json={})
assert response.status_code in (401, 503), response.text