This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/backend/tests/test_meeting_consent_api.py
Benjamin Admin 21a844cb8a fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00

358 lines
12 KiB
Python

"""
Tests for Meeting Consent API
Tests for DSGVO-compliant consent management for meeting recordings.
"""
import pytest
from fastapi.testclient import TestClient
from fastapi import FastAPI
# Import the router
from meeting_consent_api import router as consent_router
app = FastAPI()
app.include_router(consent_router)
client = TestClient(app)
class TestConsentRequest:
"""Tests for requesting recording consent."""
@pytest.fixture(autouse=True)
def setup(self):
"""Clear consent store before each test."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
def test_request_consent_success(self):
"""Test requesting consent for a meeting."""
response = client.post(
"/api/meeting-consent/request",
json={
"meeting_id": "test-meeting-123",
"consent_type": "opt_in",
"participant_count": 3
}
)
assert response.status_code == 200
data = response.json()
assert data["meeting_id"] == "test-meeting-123"
assert data["consent_type"] == "opt_in"
assert data["participant_count"] == 3
assert data["all_consented"] is False
assert data["can_record"] is False
assert data["status"] == "pending"
def test_request_consent_duplicate_rejected(self):
"""Test that duplicate consent requests are rejected."""
# First request
client.post(
"/api/meeting-consent/request",
json={"meeting_id": "dup-meeting", "consent_type": "opt_in"}
)
# Second request should fail
response = client.post(
"/api/meeting-consent/request",
json={"meeting_id": "dup-meeting", "consent_type": "opt_in"}
)
assert response.status_code == 409
assert "already exists" in response.json()["detail"]
def test_request_consent_default_values(self):
"""Test consent request uses default values."""
response = client.post(
"/api/meeting-consent/request",
json={"meeting_id": "default-meeting"}
)
assert response.status_code == 200
data = response.json()
assert data["consent_type"] == "opt_in"
class TestConsentStatus:
"""Tests for checking consent status."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create test consent before each test."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
client.post(
"/api/meeting-consent/request",
json={
"meeting_id": "status-test-meeting",
"consent_type": "opt_in",
"participant_count": 2
}
)
def test_get_consent_status_existing(self):
"""Test getting status for existing consent."""
response = client.get("/api/meeting-consent/status-test-meeting")
assert response.status_code == 200
data = response.json()
assert data["meeting_id"] == "status-test-meeting"
assert data["status"] == "pending"
def test_get_consent_status_not_requested(self):
"""Test getting status for meeting without consent request."""
response = client.get("/api/meeting-consent/nonexistent-meeting")
assert response.status_code == 200
data = response.json()
assert data["status"] == "not_requested"
assert data["can_record"] is False
class TestParticipantConsent:
"""Tests for recording individual participant consent."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create test consent with 2 participants."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
client.post(
"/api/meeting-consent/request",
json={
"meeting_id": "participant-test",
"consent_type": "opt_in",
"participant_count": 2
}
)
def test_record_participant_consent_positive(self):
"""Test recording positive consent from participant."""
response = client.post(
"/api/meeting-consent/participant-test/participant",
json={
"participant_id": "user-1",
"participant_name": "Alice",
"consented": True
}
)
assert response.status_code == 200
data = response.json()
assert data["consented_count"] == 1
assert data["all_consented"] is False
def test_record_participant_consent_negative(self):
"""Test recording negative consent from participant."""
response = client.post(
"/api/meeting-consent/participant-test/participant",
json={
"participant_id": "user-1",
"consented": False
}
)
assert response.status_code == 200
data = response.json()
assert data["consented"] is False
def test_all_participants_consented_auto_approves(self):
"""Test that recording is approved when all participants consent."""
# First participant
client.post(
"/api/meeting-consent/participant-test/participant",
json={"participant_id": "user-1", "consented": True}
)
# Second participant (should trigger approval)
response = client.post(
"/api/meeting-consent/participant-test/participant",
json={"participant_id": "user-2", "consented": True}
)
assert response.status_code == 200
data = response.json()
assert data["all_consented"] is True
assert data["can_record"] is True
def test_record_consent_meeting_not_found(self):
"""Test recording consent for non-existent meeting."""
response = client.post(
"/api/meeting-consent/nonexistent/participant",
json={"participant_id": "user-1", "consented": True}
)
assert response.status_code == 404
def test_update_existing_participant_consent(self):
"""Test updating consent for same participant."""
# Initial consent
client.post(
"/api/meeting-consent/participant-test/participant",
json={"participant_id": "user-1", "consented": True}
)
# Update to negative
response = client.post(
"/api/meeting-consent/participant-test/participant",
json={"participant_id": "user-1", "consented": False}
)
assert response.status_code == 200
data = response.json()
assert data["consented"] is False
class TestConsentWithdrawal:
"""Tests for withdrawing consent."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create approved consent."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
# Create and approve consent
client.post(
"/api/meeting-consent/request",
json={
"meeting_id": "withdraw-test",
"consent_type": "opt_in",
"participant_count": 1
}
)
client.post(
"/api/meeting-consent/withdraw-test/participant",
json={"participant_id": "user-1", "consented": True}
)
def test_withdraw_consent(self):
"""Test withdrawing consent for a meeting."""
response = client.post(
"/api/meeting-consent/withdraw-test/withdraw",
json={"reason": "Changed my mind"}
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "withdrawn"
def test_withdraw_consent_stops_recording_capability(self):
"""Test that withdrawal stops recording capability."""
# Withdraw
client.post(
"/api/meeting-consent/withdraw-test/withdraw",
json={}
)
# Check status
response = client.get("/api/meeting-consent/withdraw-test")
data = response.json()
assert data["status"] == "withdrawn" or data["status"] == "not_requested"
def test_withdraw_consent_not_found(self):
"""Test withdrawing consent for non-existent meeting."""
response = client.post(
"/api/meeting-consent/nonexistent/withdraw",
json={}
)
assert response.status_code == 404
class TestAnnouncedRecording:
"""Tests for announced recording mode."""
@pytest.fixture(autouse=True)
def setup(self):
"""Clear store before each test."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
def test_announce_recording(self):
"""Test announcing a recording."""
response = client.post(
"/api/meeting-consent/announce?meeting_id=announced-meeting&announced_by=Teacher"
)
assert response.status_code == 200
data = response.json()
assert data["consent_type"] == "announced"
assert data["can_record"] is True
assert data["announced_by"] == "Teacher"
def test_announce_recording_duplicate_rejected(self):
"""Test that duplicate announcements are rejected."""
# First announcement
client.post(
"/api/meeting-consent/announce?meeting_id=dup-announce&announced_by=Teacher"
)
# Second announcement
response = client.post(
"/api/meeting-consent/announce?meeting_id=dup-announce&announced_by=Teacher"
)
assert response.status_code == 409
class TestParticipantsList:
"""Tests for listing participant consents."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create test consent with participants."""
from meeting_consent_api import _consent_store, _participant_consents
_consent_store.clear()
_participant_consents.clear()
client.post(
"/api/meeting-consent/request",
json={"meeting_id": "list-test", "participant_count": 2}
)
client.post(
"/api/meeting-consent/list-test/participant",
json={"participant_id": "user-1-uuid-12345678", "consented": True}
)
client.post(
"/api/meeting-consent/list-test/participant",
json={"participant_id": "user-2-uuid-87654321", "consented": False}
)
def test_get_participants_list(self):
"""Test getting list of participant consents."""
response = client.get("/api/meeting-consent/list-test/participants")
assert response.status_code == 200
data = response.json()
assert len(data["participants"]) == 2
def test_participants_list_anonymized(self):
"""Test that participant IDs are anonymized."""
response = client.get("/api/meeting-consent/list-test/participants")
data = response.json()
# IDs should be truncated to last 8 chars
for p in data["participants"]:
assert len(p["participant_id"]) == 8
class TestHealthCheck:
"""Tests for health check endpoint."""
def test_health_check(self):
"""Test health check returns healthy status."""
response = client.get("/api/meeting-consent/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"