Первоначальная версия VidConf
This commit is contained in:
608
backend/tests/test_admin_api.py
Normal file
608
backend/tests/test_admin_api.py
Normal file
@@ -0,0 +1,608 @@
|
||||
"""Интеграционные тесты `/api/v1/admin/*` («Админ-API», блок C).
|
||||
|
||||
Покрывает: 403 не-админу на все эндпоинты; CRUD конференций (реюз
|
||||
`ConferenceService`); PATCH пользователя (роль/блокировка), запрет
|
||||
самоизменения (409); заблокированный пользователь получает 401 на защищённых
|
||||
эндпоинтах; ручная рассылка приглашений ставит задачу (мок продюсера);
|
||||
`PUT /admin/settings` с недоступным уровнем AI → 400; частичный PUT настроек.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
import api.admin as admin_module
|
||||
from core.config import get_settings
|
||||
from core.security import create_access_token, hash_password
|
||||
from models.conference import Conference
|
||||
from models.team import Team
|
||||
from models.user import User
|
||||
from services import ai_levels
|
||||
from services.conference_ids import generate_number, generate_slug
|
||||
|
||||
FUTURE = datetime.now(UTC) + timedelta(days=3)
|
||||
|
||||
|
||||
async def _make_user(session: AsyncSession, *, role: str = "user") -> User:
|
||||
user = User(
|
||||
email=f"{uuid.uuid4()}@example.com",
|
||||
name_user="Admin API Tester",
|
||||
password_hash=hash_password("password123"),
|
||||
email_verified=True,
|
||||
role=role,
|
||||
)
|
||||
session.add(user)
|
||||
await session.flush()
|
||||
return user
|
||||
|
||||
|
||||
def _auth_headers(user: User) -> dict[str, str]:
|
||||
token = create_access_token(user.id, user.role)
|
||||
return {"Authorization": f"Bearer {token}"}
|
||||
|
||||
|
||||
async def _make_conference(
|
||||
session: AsyncSession, *, owner_id: uuid.UUID | None = None, **overrides: object
|
||||
) -> Conference:
|
||||
defaults: dict[str, object] = {
|
||||
"number": generate_number(),
|
||||
"slug": generate_slug(),
|
||||
"owner_id": owner_id,
|
||||
"status": "scheduled",
|
||||
"scheduled_at": FUTURE,
|
||||
}
|
||||
defaults.update(overrides)
|
||||
conference = Conference(**defaults)
|
||||
session.add(conference)
|
||||
await session.flush()
|
||||
return conference
|
||||
|
||||
|
||||
# --- 403 не-админу -----------------------------------------------------------------
|
||||
|
||||
|
||||
async def test_all_admin_endpoints_forbidden_for_non_admin(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
user = await _make_user(db_session)
|
||||
conference = await _make_conference(db_session, owner_id=user.id)
|
||||
other_user = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
headers = _auth_headers(user)
|
||||
|
||||
requests = [
|
||||
("GET", "/api/v1/admin/conferences", None),
|
||||
("PATCH", f"/api/v1/admin/conferences/{conference.id}", {"title": "x"}),
|
||||
("DELETE", f"/api/v1/admin/conferences/{conference.id}", None),
|
||||
("POST", f"/api/v1/admin/conferences/{conference.id}/invitations", {}),
|
||||
("GET", "/api/v1/admin/users", None),
|
||||
("GET", f"/api/v1/admin/users/{other_user.id}", None),
|
||||
("PATCH", f"/api/v1/admin/users/{other_user.id}", {"role": "admin"}),
|
||||
("GET", "/api/v1/admin/settings", None),
|
||||
("PUT", "/api/v1/admin/settings", {}),
|
||||
]
|
||||
for method, path, body in requests:
|
||||
response = await client.request(method, path, json=body, headers=headers)
|
||||
assert response.status_code == 403, f"{method} {path} -> {response.status_code}"
|
||||
|
||||
|
||||
async def test_admin_endpoints_require_authentication(client: httpx.AsyncClient) -> None:
|
||||
response = await client.get("/api/v1/admin/conferences")
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
# --- Конференции ---------------------------------------------------------------------
|
||||
|
||||
|
||||
async def test_list_conferences_returns_all(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
conference = await _make_conference(db_session, owner_id=owner.id, title="Sync")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get("/api/v1/admin/conferences", headers=_auth_headers(admin))
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
ids = [item["id"] for item in body["items"]]
|
||||
assert str(conference.id) in ids
|
||||
assert body["total"] >= 1
|
||||
|
||||
item = next(item for item in body["items"] if item["id"] == str(conference.id))
|
||||
assert item["owner_name"] == owner.name_user
|
||||
assert item["owner_email"] == owner.email
|
||||
|
||||
|
||||
async def test_list_conferences_owner_fields_are_null_without_owner(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
conference = await _make_conference(db_session, owner_id=None, title="Ownerless")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get("/api/v1/admin/conferences", headers=_auth_headers(admin))
|
||||
assert response.status_code == 200, response.text
|
||||
item = next(item for item in response.json()["items"] if item["id"] == str(conference.id))
|
||||
assert item["owner_name"] is None
|
||||
assert item["owner_email"] is None
|
||||
|
||||
|
||||
async def test_list_conferences_filters_by_status_and_query(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
await _make_conference(db_session, owner_id=owner.id, title="Findable Sync", status="scheduled")
|
||||
await _make_conference(db_session, owner_id=owner.id, title="Other", status="ended")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get(
|
||||
"/api/v1/admin/conferences",
|
||||
params={"status": "scheduled", "q": "Findable"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
titles = [item["title"] for item in response.json()["items"]]
|
||||
assert titles == ["Findable Sync"]
|
||||
|
||||
|
||||
async def test_patch_conference_by_admin_returns_200(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
conference = await _make_conference(db_session, owner_id=owner.id, title="Original")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/conferences/{conference.id}",
|
||||
json={"title": "Renamed by admin"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
assert body["title"] == "Renamed by admin"
|
||||
assert body["owner_name"] == owner.name_user
|
||||
assert body["owner_email"] == owner.email
|
||||
|
||||
|
||||
async def test_patch_unknown_conference_returns_404(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/conferences/{uuid.uuid4()}",
|
||||
json={"title": "x"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
async def test_delete_conference_by_admin_returns_204(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
conference = await _make_conference(db_session, owner_id=owner.id, status="scheduled")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.delete(
|
||||
f"/api/v1/admin/conferences/{conference.id}", headers=_auth_headers(admin)
|
||||
)
|
||||
assert response.status_code == 204
|
||||
|
||||
|
||||
async def test_delete_active_conference_by_admin_returns_409(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
conference = await _make_conference(
|
||||
db_session, owner_id=owner.id, status="active", scheduled_at=None
|
||||
)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.delete(
|
||||
f"/api/v1/admin/conferences/{conference.id}", headers=_auth_headers(admin)
|
||||
)
|
||||
assert response.status_code == 409
|
||||
|
||||
|
||||
async def test_send_invitations_enqueues_task(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
owner = await _make_user(db_session)
|
||||
conference = await _make_conference(db_session, owner_id=owner.id)
|
||||
await db_session.commit()
|
||||
|
||||
mock_enqueue = MagicMock()
|
||||
monkeypatch.setattr(admin_module, "enqueue_invitations", mock_enqueue)
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/admin/conferences/{conference.id}/invitations",
|
||||
json={"emails": ["custom@example.com"]},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 202, response.text
|
||||
mock_enqueue.assert_called_once_with(conference.id, emails=["custom@example.com"])
|
||||
|
||||
|
||||
async def test_send_invitations_unknown_conference_returns_404(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
monkeypatch.setattr(admin_module, "enqueue_invitations", MagicMock())
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/admin/conferences/{uuid.uuid4()}/invitations",
|
||||
json={},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# --- Создание пользователя администратором ---------------------------------------------
|
||||
|
||||
|
||||
async def test_create_user_returns_201_and_login_works(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
email = f"{uuid.uuid4()}@example.com"
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/admin/users",
|
||||
json={"name_user": "Новый пользователь", "email": email, "password": "password123"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 201, response.text
|
||||
body = response.json()
|
||||
assert body["email"] == email
|
||||
assert body["name_user"] == "Новый пользователь"
|
||||
assert body["role"] == "user"
|
||||
assert body["email_verified"] is True
|
||||
|
||||
login = await client.post(
|
||||
"/api/v1/auth/token", data={"username": email, "password": "password123"}
|
||||
)
|
||||
assert login.status_code == 200, login.text
|
||||
assert "access_token" in login.json()
|
||||
|
||||
|
||||
async def test_create_user_with_team_id(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
team = Team(name=f"Team {uuid.uuid4()}")
|
||||
db_session.add(team)
|
||||
await db_session.flush()
|
||||
await db_session.commit()
|
||||
email = f"{uuid.uuid4()}@example.com"
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/admin/users",
|
||||
json={
|
||||
"name_user": "С командой",
|
||||
"email": email,
|
||||
"password": "password123",
|
||||
"team_id": str(team.id),
|
||||
},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 201, response.text
|
||||
assert response.json()["team_id"] == str(team.id)
|
||||
|
||||
|
||||
async def test_create_user_unknown_team_returns_404(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/admin/users",
|
||||
json={
|
||||
"name_user": "Без команды",
|
||||
"email": f"{uuid.uuid4()}@example.com",
|
||||
"password": "password123",
|
||||
"team_id": str(uuid.uuid4()),
|
||||
},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert response.json()["detail"] == "team_not_found"
|
||||
|
||||
|
||||
async def test_create_user_duplicate_email_returns_409(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
existing = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/admin/users",
|
||||
json={
|
||||
"name_user": "Дубль",
|
||||
"email": existing.email,
|
||||
"password": "password123",
|
||||
},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 409
|
||||
assert response.json()["detail"] == "email_already_registered"
|
||||
|
||||
|
||||
async def test_create_user_forbidden_for_non_admin(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
user = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/admin/users",
|
||||
json={
|
||||
"name_user": "Not allowed",
|
||||
"email": f"{uuid.uuid4()}@example.com",
|
||||
"password": "password123",
|
||||
},
|
||||
headers=_auth_headers(user),
|
||||
)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
# --- Пользователи ----------------------------------------------------------------------
|
||||
|
||||
|
||||
async def test_list_users_returns_all(client: httpx.AsyncClient, db_session: AsyncSession) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
other = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get("/api/v1/admin/users", headers=_auth_headers(admin))
|
||||
assert response.status_code == 200
|
||||
items = response.json()["items"]
|
||||
ids = [item["id"] for item in items]
|
||||
assert str(admin.id) in ids
|
||||
assert str(other.id) in ids
|
||||
assert all("email_verified" in item for item in items)
|
||||
|
||||
|
||||
async def test_patch_user_role_and_block(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/users/{target.id}",
|
||||
json={"role": "admin", "is_blocked": True},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
assert body["role"] == "admin"
|
||||
assert body["is_blocked"] is True
|
||||
assert body["email_verified"] is True
|
||||
|
||||
|
||||
async def test_get_user_returns_profile_card(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
"""Карточка профиля из таблицы пользователей — те же поля, что `/users/me`."""
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get(f"/api/v1/admin/users/{target.id}", headers=_auth_headers(admin))
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
assert body["id"] == str(target.id)
|
||||
assert body["name_user"] == target.name_user
|
||||
assert body["avatar_url"] is None
|
||||
assert body["team_name"] is None
|
||||
|
||||
|
||||
async def test_get_unknown_user_returns_404(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get(f"/api/v1/admin/users/{uuid.uuid4()}", headers=_auth_headers(admin))
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
async def test_patch_user_updates_name(client: httpx.AsyncClient, db_session: AsyncSession) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/users/{target.id}",
|
||||
json={"name_user": "Renamed By Admin"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json()["name_user"] == "Renamed By Admin"
|
||||
|
||||
|
||||
async def test_upload_user_avatar_by_admin(
|
||||
client: httpx.AsyncClient,
|
||||
db_session: AsyncSession,
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setenv("MEDIA_ROOT", str(tmp_path))
|
||||
get_settings.cache_clear()
|
||||
try:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/admin/users/{target.id}/avatar",
|
||||
headers=_auth_headers(admin),
|
||||
files={"file": ("avatar.png", b"\x89PNG\r\n\x1a\n" + b"\x00" * 32, "image/png")},
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json()["avatar_url"] is not None
|
||||
finally:
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
async def test_upload_user_avatar_forbidden_for_non_admin(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
user = await _make_user(db_session)
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.post(
|
||||
f"/api/v1/admin/users/{target.id}/avatar",
|
||||
headers=_auth_headers(user),
|
||||
files={"file": ("avatar.png", b"\x89PNG\r\n\x1a\n" + b"\x00" * 32, "image/png")},
|
||||
)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
async def test_patch_self_returns_409(client: httpx.AsyncClient, db_session: AsyncSession) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/users/{admin.id}",
|
||||
json={"is_blocked": True},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 409
|
||||
|
||||
|
||||
async def test_blocked_user_gets_401_on_protected_endpoint(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
target = await _make_user(db_session)
|
||||
await db_session.commit()
|
||||
target_headers = _auth_headers(target)
|
||||
|
||||
block_response = await client.patch(
|
||||
f"/api/v1/admin/users/{target.id}",
|
||||
json={"is_blocked": True},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert block_response.status_code == 200
|
||||
|
||||
response = await client.get("/api/v1/users/me", headers=target_headers)
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
async def test_patch_unknown_user_returns_404(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.patch(
|
||||
f"/api/v1/admin/users/{uuid.uuid4()}",
|
||||
json={"is_blocked": True},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# --- Настройки --------------------------------------------------------------------------
|
||||
|
||||
|
||||
async def test_get_settings_includes_ai_levels(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Плумбинг `detect_ai_levels` через API — не тест самого детекта (см.
|
||||
`test_ai_levels.py`): железо теста-«пресета 3» смоделировано env-переменными
|
||||
(RAM хватает на `min`, но не на `medium`; GPU нет — `max` недоступен), файлы
|
||||
моделей считаются скачанными (изолируем тест от реального диска)."""
|
||||
monkeypatch.setattr(ai_levels, "_model_downloaded", lambda _path: True)
|
||||
monkeypatch.setattr(admin_module, "transcription_queue_served", lambda: False)
|
||||
monkeypatch.setenv("HW_RAM_MB", "16384")
|
||||
monkeypatch.delenv("HW_GPU_NAME", raising=False)
|
||||
get_settings.cache_clear()
|
||||
try:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.get("/api/v1/admin/settings", headers=_auth_headers(admin))
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
levels = {item["level"]: item["available"] for item in body["ai_levels"]}
|
||||
assert levels["min"] is True
|
||||
assert levels["medium"] is False
|
||||
assert levels["max"] is False
|
||||
finally:
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
async def test_get_settings_transcription_queue_served_reflects_worker_presence(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""`transcription_queue_served`
|
||||
в ответе `GET /admin/settings` для обоих исходов детекта воркера (замокан
|
||||
на уровне сервисной функции — сам детект Celery inspect покрыт
|
||||
`test_task_producers.py`)."""
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
monkeypatch.setattr(admin_module, "transcription_queue_served", lambda: True)
|
||||
served = await client.get("/api/v1/admin/settings", headers=_auth_headers(admin))
|
||||
assert served.status_code == 200, served.text
|
||||
assert served.json()["transcription_queue_served"] is True
|
||||
|
||||
monkeypatch.setattr(admin_module, "transcription_queue_served", lambda: False)
|
||||
not_served = await client.get("/api/v1/admin/settings", headers=_auth_headers(admin))
|
||||
assert not_served.status_code == 200, not_served.text
|
||||
assert not_served.json()["transcription_queue_served"] is False
|
||||
|
||||
|
||||
async def test_put_settings_partial_update(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setattr(admin_module, "transcription_queue_served", lambda: False)
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.put(
|
||||
"/api/v1/admin/settings",
|
||||
json={"chat_enabled": False, "display_timezone": "Asia/Yekaterinburg"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 200, response.text
|
||||
body = response.json()
|
||||
assert body["chat_enabled"] is False
|
||||
assert body["display_timezone"] == "Asia/Yekaterinburg"
|
||||
assert body["ai_level"] == "min"
|
||||
assert body["transcription_queue_served"] is False
|
||||
|
||||
|
||||
async def test_put_settings_unavailable_ai_level_returns_400(
|
||||
client: httpx.AsyncClient, db_session: AsyncSession
|
||||
) -> None:
|
||||
admin = await _make_user(db_session, role="admin")
|
||||
await db_session.commit()
|
||||
|
||||
response = await client.put(
|
||||
"/api/v1/admin/settings",
|
||||
json={"ai_level": "medium"},
|
||||
headers=_auth_headers(admin),
|
||||
)
|
||||
assert response.status_code == 400
|
||||
Reference in New Issue
Block a user