Files
ipam_control/tests/conftest.py
T
ayurishchevandClaude Sonnet 5 a846d30872 IPAM Manager: API, UI-админка, журнал аудита
Backend (FastAPI, SQLAlchemy 2, Alembic, PostgreSQL 16):
- организации, VRF, префиксы (дерево, использование, автоназначение),
  адреса, операторы связи, устройства и типы устройств; JWT, роли admin/viewer;
- VRF принадлежит организации (составной FK), смена VRF у префикса
  переносит поддерево, имя VRF уникально в организации;
- журнал аудита: поиск и фильтры, ротация (срок/количество), очистка
  по паролю с блокировкой, IP клиента и метаданные запроса
  (X-Forwarded-For только от TRUSTED_PROXIES).

UI (web/, без сборки): экраны и диалоги по макетам «IPAM Manager»,
кликабельные строки реестров, локальные шрифты IBM Plex,
собственные выпадающие списки.

Окружение: docker-compose (postgres + app), миграции Alembic 0001-0004,
scripts/gen_env.py, scripts/seed_demo.py, 11 автотестов (pytest).
Документация: README.md и docs/changes/001-005 (планы и итоги).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 12:27:47 +03:00

45 lines
2.0 KiB
Python

"""Тесты идут против приложения в контейнерах (docker compose up -d) с учётными данными из .env."""
import pathlib
import random
import uuid
import httpx
import pytest
ENV = dict(l.split("=", 1) for l in pathlib.Path(__file__).resolve().parent.parent.joinpath(".env").read_text().split() if "=" in l)
BASE = f"http://127.0.0.1:{ENV['APP_PORT']}/api/v1"
@pytest.fixture(scope="session")
def client():
c = httpx.Client(base_url=BASE, timeout=30)
tok = c.post("/auth/login", json={"username": ENV["ADMIN_USERNAME"], "password": ENV["ADMIN_PASSWORD"]}).json()["access_token"]
c.headers["Authorization"] = f"Bearer {tok}"
return c
@pytest.fixture
def org(client):
"""Временная организация с дефолтным VRF; после теста удаляется вместе с содержимым."""
o = client.post("/organizations", json={"name": f"test-{uuid.uuid4().hex[:8]}", "inn": "".join(random.choices("0123456789", k=10))}).json()
o["vrf_id"] = client.get("/vrfs", params={"organization_id": o["id"]}).json()["items"][0]["id"]
yield o
for p in client.get("/prefixes", params={"organization_id": o["id"]}).json()["items"]:
client.delete(f"/prefixes/{p['id']}", params={"force": True})
for d in client.get("/devices", params={"organization_id": o["id"]}).json()["items"]:
client.delete(f"/devices/{d['id']}")
for v in client.get("/vrfs", params={"organization_id": o["id"]}).json()["items"]:
client.delete(f"/vrfs/{v['id']}")
client.delete(f"/organizations/{o['id']}")
DSN = f"postgresql://{ENV['POSTGRES_USER']}:{ENV['POSTGRES_PASSWORD']}@127.0.0.1:{ENV['DB_HOST_PORT']}/{ENV['POSTGRES_DB']}"
@pytest.fixture
def db():
"""Прямое подключение к БД — для сценариев, недоступных через API (старые записи, временные пользователи)."""
import psycopg
with psycopg.connect(DSN, autocommit=True) as conn:
yield conn