Complete training workflow and acceptance hardening

This commit is contained in:
andreysk0304 2026-09-26 18:12:27 +03:00 • committed by gglamer
commit 7237265833
243 changed files with 17014 additions and 1500 deletions

View file

@ -1,6 +1,7 @@
"""Групповая сводка считает людей, а не число их повторных попыток."""
from uuid import uuid4
from types import SimpleNamespace
import pytest
from fastapi import HTTPException
@ -9,6 +10,7 @@ from starlette.requests import Request
from app.api import auth
from app.api.http import groups as group_api
from app.api.auth import Principal
from app.db.models import AuditLog
from app.domain.roles import Role
from app.scoring.group import ScoredAttempt, summarize
@ -47,25 +49,53 @@ def test_unknown_codes_do_not_break_group_summary():
assert [item["code"] for item in result["errors"]] == ["E5"]
@pytest.mark.asyncio
async def test_group_insight_fails_closed_if_audit_cannot_be_saved(monkeypatch):
who = Principal(login="teacher", full_name="Преподаватель", role=Role.INSTRUCTOR)
monkeypatch.setattr(group_api, "require", lambda _request, *_roles: who)
async def fake_analytics(*_args, **_kwargs):
return SimpleNamespace(scored_attempts=1, model_dump=lambda **_kwargs: {})
async def fake_insight(_data):
return {"summary": "Повторить уточнение адреса", "priorities": []}
async def unavailable_audit(*_args, **_kwargs):
raise HTTPException(status_code=503, detail="audit_unavailable")
monkeypatch.setattr(group_api, "_analytics", fake_analytics)
monkeypatch.setattr(group_api, "generate_group_insight", fake_insight)
monkeypatch.setattr(group_api, "audit_required", unavailable_audit)
with pytest.raises(HTTPException) as exc:
await group_api.ai_insight(uuid4(), object(), object())
assert exc.value.status_code == 503
assert exc.value.detail == "audit_unavailable"
@pytest.mark.asyncio
async def test_group_creation_requires_staff_and_returns_new_group(monkeypatch):
class FakeDb:
def add(self, group):
group.id = uuid4()
def __init__(self):
self.added = []
self.commits = 0
def add(self, row):
self.added.append(row)
async def commit(self):
pass
async def no_audit(*args):
pass
monkeypatch.setattr(group_api, "audit", no_audit)
self.commits += 1
instructor = Principal(login="teacher", full_name="Преподаватель", role=Role.INSTRUCTOR)
request = Request({"type": "http", "session": {}})
auth._issue_session(request, instructor)
created = await group_api.create(group_api.GroupCreate(name=" Группа 1 "), request, FakeDb())
db = FakeDb()
created = await group_api.create(group_api.GroupCreate(name=" Группа 1 "), request, db)
assert created.name == "Группа 1"
assert created.id
assert db.commits == 1
audit_row = next(row for row in db.added if isinstance(row, AuditLog))
assert audit_row.action == "group.create" and audit_row.object_id == str(created.id)
trainee = Principal(login="trainee", full_name="Курсант", role=Role.TRAINEE)
forbidden = Request({"type": "http", "session": {}})