bifroest/tests/test_chats.py
2026-10-27 08:34:17 +01:00

109 lines
5.4 KiB
Python

"""Chats verwalten: Titel, Umbenennen, Löschen."""
import re
import pytest
from sqlalchemy import func, select
from app.audit.models import AuditEvent
from app.chat.models import ChatSession, Message
from app.tasks.models import TaskRun
from app.tasks.worker import Worker
from helpers import connect_repo, create_workspace
@pytest.fixture
def setup(browser, people, git_repo):
anna = browser("anna")
workspace_id = create_workspace(anna, people["team_demo"])
connect_repo(anna, workspace_id, git_repo)
anna.post(f"/workspaces/{workspace_id}/members", {"username": "ben", "role": "member"})
anna.post(f"/workspaces/{workspace_id}/members", {"username": "clara", "role": "member"})
ben = browser("ben")
chat_id = int(ben.post(f"/workspaces/{workspace_id}/chats").headers["location"].rsplit("/", 1)[1])
return {"anna": anna, "ben": ben, "clara": browser("clara"), "workspace_id": workspace_id, "chat_id": chat_id}
def send(b, chat_id: int, text: str):
response = b.post(f"/chats/{chat_id}/messages", {"content": text}, headers={"HX-Request": "true"})
assert response.status_code == 200, response.text
def title(db, chat_id: int) -> str:
with db.session() as session:
return session.get(ChatSession, chat_id).title
def test_erste_frage_wird_titel(setup, db, settings):
send(setup["ben"], setup["chat_id"], "Wie ist der Timeout\nkonfiguriert? " + "x" * 80)
assert title(db, setup["chat_id"]).startswith("Wie ist der Timeout konfiguriert? x")
assert title(db, setup["chat_id"]).endswith("…") and len(title(db, setup["chat_id"])) == 61
Worker(db, settings).run_once()
send(setup["ben"], setup["chat_id"], "Zweite Frage")
assert not title(db, setup["chat_id"]).startswith("Zweite")
def test_umbenennen(setup, db):
assert setup["ben"].post(f"/chats/{setup['chat_id']}/rename", {"title": " Timeouts "}).status_code == 303
assert title(db, setup["chat_id"]) == "Timeouts"
assert "Timeouts" in setup["ben"].get(f"/workspaces/{setup['workspace_id']}").text
assert setup["ben"].post(f"/chats/{setup['chat_id']}/rename", {"title": " "}).status_code == 400
# Workspace-Admin darf, anderes Mitglied nicht
assert setup["anna"].post(f"/chats/{setup['chat_id']}/rename", {"title": "Von Anna"}).status_code == 303
assert setup["clara"].post(f"/chats/{setup['chat_id']}/rename", {"title": "Clara"}).status_code == 403
assert "Bearbeiten" not in setup["clara"].get(f"/chats/{setup['chat_id']}").text
assert title(db, setup["chat_id"]) == "Von Anna"
def test_loeschen(setup, db, settings, browser):
send(setup["ben"], setup["chat_id"], "Hallo")
# Solange die Antwort läuft, nicht löschbar
response = setup["ben"].post(f"/chats/{setup['chat_id']}/delete")
assert response.status_code == 400 and "erst abbrechen" in response.text
Worker(db, settings).run_once()
assert setup["clara"].post(f"/chats/{setup['chat_id']}/delete").status_code == 403
assert browser("dora").post(f"/chats/{setup['chat_id']}/delete").status_code == 404
response = setup["ben"].post(f"/chats/{setup['chat_id']}/delete")
assert response.status_code == 303 and response.headers["location"] == f"/workspaces/{setup['workspace_id']}"
with db.session() as session:
assert session.get(ChatSession, setup["chat_id"]) is None
assert session.scalar(select(func.count()).select_from(Message)) == 0
assert session.scalar(select(func.count()).select_from(TaskRun)) == 0
assert session.scalar(select(AuditEvent).where(AuditEvent.action == "chat.deleted")) is not None
assert setup["ben"].get(f"/chats/{setup['chat_id']}").status_code == 404
def test_workspace_admin_loescht_fremden_chat(setup, db):
assert setup["anna"].post(f"/chats/{setup['chat_id']}/delete").status_code == 303
def test_loeschen_aus_der_workspace_uebersicht(setup):
"""Knopf in der Chat-Liste nur für Autor und Workspace-Admins."""
action = f'action="/chats/{setup["chat_id"]}/delete"'
page = f"/workspaces/{setup['workspace_id']}"
assert action in setup["ben"].get(page).text
assert action in setup["anna"].get(page).text
assert action not in setup["clara"].get(page).text
def test_statische_dateien_mit_version(setup):
"""Nach einem Update lädt der Browser neue Skripte statt alter Kopien aus dem Cache."""
import re
page = setup["ben"].get(f"/workspaces/{setup['workspace_id']}").text
assert re.search(r'/static/js/app\.js\?v=[0-9a-f]+"', page)
def test_rueckmeldung_nach_workspace_vorgabe(setup, db, people):
from app.identity import Principal
from app.tools import service as tools
admin = Principal(user_id=people["anna"], username="anna", display_name="Anna", is_admin=True,
team_ids=frozenset({people["team_demo"]}))
with db.session() as session:
tools.classify_suggested(session, admin)
response = setup["anna"].post(f"/workspaces/{setup['workspace_id']}/tools/git_log", {"decision": ""})
assert response.headers["location"] == f"/workspaces/{setup['workspace_id']}/settings?tab=tools&tool=git_log"
page = setup["anna"].get(response.headers["location"]).text
assert re.search(r"Gespeichert: <code>git_log</code> ist jetzt erlaubt \(wie global\)", page)
setup["anna"].post(f"/workspaces/{setup['workspace_id']}/tools/git_log", {"decision": "deny"})
page = setup["anna"].get(f"/workspaces/{setup['workspace_id']}/settings?tab=tools&tool=git_log").text
assert "ist jetzt gesperrt (Vorgabe des Workspace)" in page