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_recording_api.py
BreakPilot Dev 19855efacc
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
All services: admin-v2, studio-v2, website, ai-compliance-sdk,
consent-service, klausur-service, voice-service, and infrastructure.
Large PDFs and compiled binaries excluded via .gitignore.
2026-02-11 13:25:58 +01:00

295 lines
9.7 KiB
Python

"""
Tests for Recording API
Tests for Jibri webhook handling, recording management, and transcription endpoints.
"""
import pytest
from datetime import datetime, timedelta
from fastapi.testclient import TestClient
# Import the app (adjust import path as needed)
# In actual test environment, this would be the main FastAPI app
# from main import app
# For now, we create a minimal test setup
from fastapi import FastAPI
from recording_api import router as recording_router
app = FastAPI()
app.include_router(recording_router)
client = TestClient(app)
class TestJibriWebhook:
"""Tests for Jibri webhook endpoint."""
def test_webhook_recording_completed_valid(self):
"""Test webhook with valid recording_completed event."""
payload = {
"event": "recording_completed",
"recording_name": "test-room_20260115_120000",
"storage_path": "recordings/test-room_20260115_120000/video.mp4",
"audio_path": "recordings/test-room_20260115_120000/audio.wav",
"file_size_bytes": 52428800,
"timestamp": "2026-01-15T12:00:00Z"
}
response = client.post("/api/recordings/webhook", json=payload)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["status"] == "uploaded"
assert "recording_id" in data
assert data["meeting_id"] == "test-room"
def test_webhook_unknown_event_rejected(self):
"""Test that unknown event types are rejected."""
payload = {
"event": "unknown_event",
"recording_name": "test",
"storage_path": "test/video.mp4",
"file_size_bytes": 1000,
"timestamp": "2026-01-15T12:00:00Z"
}
response = client.post("/api/recordings/webhook", json=payload)
assert response.status_code == 400
assert "Unknown event type" in response.json()["error"]
def test_webhook_missing_required_fields(self):
"""Test that missing required fields cause validation error."""
payload = {
"event": "recording_completed"
# Missing other required fields
}
response = client.post("/api/recordings/webhook", json=payload)
assert response.status_code == 422 # Validation error
class TestRecordingManagement:
"""Tests for recording CRUD operations."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create a test recording before each test."""
# Clear store and create test recording
from recording_api import _recordings_store
_recordings_store.clear()
payload = {
"event": "recording_completed",
"recording_name": "fixture-room_20260115_100000",
"storage_path": "recordings/fixture-room/video.mp4",
"file_size_bytes": 10000000,
"timestamp": "2026-01-15T10:00:00Z"
}
response = client.post("/api/recordings/webhook", json=payload)
self.recording_id = response.json()["recording_id"]
def test_list_recordings_empty(self):
"""Test listing recordings when empty."""
from recording_api import _recordings_store
_recordings_store.clear()
response = client.get("/api/recordings")
assert response.status_code == 200
data = response.json()
assert data["total"] == 0
assert data["recordings"] == []
def test_list_recordings_with_data(self):
"""Test listing recordings returns created recordings."""
response = client.get("/api/recordings")
assert response.status_code == 200
data = response.json()
assert data["total"] == 1
assert len(data["recordings"]) == 1
def test_list_recordings_filter_by_status(self):
"""Test filtering recordings by status."""
response = client.get("/api/recordings?status=uploaded")
assert response.status_code == 200
data = response.json()
assert all(r["status"] == "uploaded" for r in data["recordings"])
def test_list_recordings_pagination(self):
"""Test pagination of recordings list."""
response = client.get("/api/recordings?page=1&page_size=10")
assert response.status_code == 200
data = response.json()
assert data["page"] == 1
assert data["page_size"] == 10
def test_get_recording_by_id(self):
"""Test getting a specific recording by ID."""
response = client.get(f"/api/recordings/{self.recording_id}")
assert response.status_code == 200
data = response.json()
assert data["id"] == self.recording_id
assert data["status"] == "uploaded"
def test_get_recording_not_found(self):
"""Test getting non-existent recording returns 404."""
response = client.get("/api/recordings/nonexistent-id")
assert response.status_code == 404
assert "not found" in response.json()["detail"].lower()
def test_delete_recording(self):
"""Test soft-deleting a recording."""
response = client.delete(
f"/api/recordings/{self.recording_id}?reason=DSGVO%20request"
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["status"] == "deleted"
def test_delete_recording_requires_reason(self):
"""Test that deletion requires a reason."""
response = client.delete(f"/api/recordings/{self.recording_id}")
assert response.status_code == 422 # Missing required query param
class TestTranscriptionEndpoints:
"""Tests for transcription management."""
@pytest.fixture(autouse=True)
def setup(self):
"""Create test recording and clear transcription store."""
from recording_api import _recordings_store, _transcriptions_store
_recordings_store.clear()
_transcriptions_store.clear()
payload = {
"event": "recording_completed",
"recording_name": "trans-test_20260115_110000",
"storage_path": "recordings/trans-test/video.mp4",
"file_size_bytes": 5000000,
"timestamp": "2026-01-15T11:00:00Z"
}
response = client.post("/api/recordings/webhook", json=payload)
self.recording_id = response.json()["recording_id"]
def test_start_transcription(self):
"""Test starting a transcription job."""
response = client.post(
f"/api/recordings/{self.recording_id}/transcribe",
json={"language": "de", "model": "large-v3"}
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "pending"
assert data["language"] == "de"
assert data["model"] == "large-v3"
def test_start_transcription_default_values(self):
"""Test transcription uses default values when not specified."""
response = client.post(
f"/api/recordings/{self.recording_id}/transcribe",
json={}
)
assert response.status_code == 200
data = response.json()
assert data["language"] == "de"
assert data["model"] == "large-v3"
def test_start_transcription_recording_not_found(self):
"""Test starting transcription for non-existent recording."""
response = client.post(
"/api/recordings/nonexistent/transcribe",
json={"language": "de"}
)
assert response.status_code == 404
def test_start_transcription_duplicate_rejected(self):
"""Test that duplicate transcription requests are rejected."""
# First request
client.post(
f"/api/recordings/{self.recording_id}/transcribe",
json={"language": "de"}
)
# Second request should fail
response = client.post(
f"/api/recordings/{self.recording_id}/transcribe",
json={"language": "de"}
)
assert response.status_code == 409
assert "already exists" in response.json()["detail"]
def test_get_transcription_status(self):
"""Test getting transcription status."""
# Start transcription first
client.post(
f"/api/recordings/{self.recording_id}/transcribe",
json={"language": "de"}
)
response = client.get(
f"/api/recordings/{self.recording_id}/transcription"
)
assert response.status_code == 200
data = response.json()
assert data["recording_id"] == self.recording_id
assert data["status"] == "pending"
def test_get_transcription_not_found(self):
"""Test getting transcription for recording without transcription."""
response = client.get(
f"/api/recordings/{self.recording_id}/transcription"
)
assert response.status_code == 404
class TestAuditLog:
"""Tests for audit log endpoints."""
def test_get_audit_log(self):
"""Test retrieving audit log entries."""
response = client.get("/api/recordings/audit/log")
assert response.status_code == 200
data = response.json()
assert "entries" in data
assert "total" in data
def test_get_audit_log_filter_by_action(self):
"""Test filtering audit log by action."""
response = client.get("/api/recordings/audit/log?action=created")
assert response.status_code == 200
class TestHealthCheck:
"""Tests for health check endpoint."""
def test_health_check(self):
"""Test health check returns healthy status."""
response = client.get("/api/recordings/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert "recordings_count" in data
assert "minio_endpoint" in data