135 lines
4.2 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.

import asyncio
from contextlib import contextmanager
import os
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import text
from src.db.base import SessionLocal
from src.db.session import get_db
from src.main import app
@pytest.fixture
def client():
db_ref = SessionLocal()
loop_ref = None
async def _get_db():
nonlocal loop_ref
loop_ref = asyncio.get_running_loop()
try:
yield db_ref
await db_ref.flush()
except:
await db_ref.rollback()
raise
app.dependency_overrides[get_db] = _get_db
with TestClient(app) as test_client:
try:
test_client.db_session = db_ref
yield test_client
finally:
if db_ref is not None and loop_ref:
async def cleanup():
await db_ref.rollback()
await db_ref.close()
future = asyncio.run_coroutine_threadsafe(cleanup(), loop_ref)
future.result()
app.dependency_overrides.clear()
@pytest.fixture
def admin_password() -> str:
# Пароль админа берём из окружения, чтобы не хардкодить локальные отличия.
return os.getenv("OPENBAO__TEST_ADMIN_PASSWORD", "admin123")
@pytest.fixture
def isp_password() -> str:
# Пароль админа берём из окружения, чтобы не хардкодить локальные отличия.
return os.getenv("OPENBAO__TEST_EXECUTOR_PASSWORD", "admin123")
@pytest.fixture
def admin_tokens(client, admin_password: str):
response = client.post(
"/api/v1/auth/login",
json={"username": "admin", "password": admin_password},
)
assert response.status_code == 200
return response.json()
@pytest.fixture
def auth_headers():
def _build(tokens: dict) -> dict:
return {"Authorization": f"Bearer {tokens['access_token']}"}
return _build
@pytest.fixture
def isp_tokens(client, isp_password: str):
response = client.post(
"/api/v1/auth/login",
json={"username": "isp1", "password": isp_password},
)
assert response.status_code == 200
return response.json()
SVOD2_YEAR = 2031
SVOD2_SEED_PATH = os.path.join(os.path.dirname(__file__), "..", "sqls", "svod2_seed.sql")
def legacy_full(client, sheet: str, headers: dict, org_ids=None) -> list[dict]:
"""Прежний ответ свода 2 без параметров нового режима (оракульная база)."""
url = f"/api/v1/svod/2/{sheet}/{SVOD2_YEAR}"
if org_ids is not None:
url += f"?org_ids={org_ids}"
response = client.get(url, headers=headers)
assert response.status_code == 200, response.text
return response.json()["result"]
@pytest.fixture
def svod2_sql(client):
"""Выполняет text(sql) на сессии клиента (тот же цикл событий, что у запросов)."""
def _run(sql: str, params: dict | None = None):
async def _exec():
result = await client.db_session.execute(text(sql), params or {})
return list(result.fetchall()) if result.returns_rows else []
return client.portal.call(_exec)
return _run
@pytest.fixture
def svod2_data(client, svod2_sql) -> dict:
"""Засевает данные свода 2 (откатываются вместе с сессией клиента)."""
with open(SVOD2_SEED_PATH, "r", encoding="utf-8") as f:
script = f.read()
for statement in script.split(";"):
statement = statement.strip()
if statement:
svod2_sql(statement)
# id строки contract_detail: contract_detail.line_id = 910002, технический id,
# который попадает в шапку строки, — expense_item_id этой строки
cd_id = svod2_sql("SELECT expense_item_id FROM v3.budget_line WHERE id = 910002")[0][0]
return {
"year": SVOD2_YEAR,
"org_a": 910001,
"org_b": 910002,
"org_b_twin": 910003,
"org_b_case": 910004,
"cd_id": cd_id,
"ckk_only_value": "777.25",
}