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/consent-service/internal/handlers/communication_handlers_test.go
Benjamin Admin bfdaf63ba9 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

408 lines
12 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
// TestGetCommunicationStatus_NoServices tests status with no services configured
func TestGetCommunicationStatus_NoServices_ReturnsDisabled(t *testing.T) {
gin.SetMode(gin.TestMode)
// Create handler with no services
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.GET("/api/v1/communication/status", handler.GetCommunicationStatus)
req, _ := http.NewRequest("GET", "/api/v1/communication/status", nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Fatalf("Failed to parse response: %v", err)
}
// Check matrix is disabled
matrix, ok := response["matrix"].(map[string]interface{})
if !ok {
t.Fatal("Expected matrix in response")
}
if matrix["enabled"] != false {
t.Error("Expected matrix.enabled to be false")
}
// Check jitsi is disabled
jitsi, ok := response["jitsi"].(map[string]interface{})
if !ok {
t.Fatal("Expected jitsi in response")
}
if jitsi["enabled"] != false {
t.Error("Expected jitsi.enabled to be false")
}
// Check timestamp exists
if _, ok := response["timestamp"]; !ok {
t.Error("Expected timestamp in response")
}
}
// TestCreateRoom_NoMatrixService tests room creation without Matrix
func TestCreateRoom_NoMatrixService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/rooms", handler.CreateRoom)
body := `{"type": "class_info", "class_name": "5b"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/rooms", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
var response map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Fatalf("Failed to parse response: %v", err)
}
if response["error"] != "Matrix service not configured" {
t.Errorf("Unexpected error message: %s", response["error"])
}
}
// TestCreateRoom_InvalidBody tests room creation with invalid body
func TestCreateRoom_InvalidBody_Returns400(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/rooms", handler.CreateRoom)
req, _ := http.NewRequest("POST", "/api/v1/communication/rooms", bytes.NewBufferString("{invalid"))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Service unavailable check happens first, so we get 503
// This is expected behavior - service check before body validation
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestInviteUser_NoMatrixService tests invite without Matrix
func TestInviteUser_NoMatrixService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/rooms/invite", handler.InviteUser)
body := `{"room_id": "!abc:server", "user_id": "@user:server"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/rooms/invite", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestSendMessage_NoMatrixService tests message sending without Matrix
func TestSendMessage_NoMatrixService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/messages", handler.SendMessage)
body := `{"room_id": "!abc:server", "message": "Hello"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/messages", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestSendNotification_NoMatrixService tests notification without Matrix
func TestSendNotification_NoMatrixService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/notifications", handler.SendNotification)
body := `{"room_id": "!abc:server", "type": "absence", "student_name": "Max"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/notifications", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestCreateMeeting_NoJitsiService tests meeting creation without Jitsi
func TestCreateMeeting_NoJitsiService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/meetings", handler.CreateMeeting)
body := `{"type": "quick", "display_name": "Teacher"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/meetings", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
var response map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Fatalf("Failed to parse response: %v", err)
}
if response["error"] != "Jitsi service not configured" {
t.Errorf("Unexpected error message: %s", response["error"])
}
}
// TestGetEmbedURL_NoJitsiService tests embed URL without Jitsi
func TestGetEmbedURL_NoJitsiService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/meetings/embed", handler.GetEmbedURL)
body := `{"room_name": "test-room", "display_name": "User"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/meetings/embed", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestGetJitsiInfo_NoJitsiService tests Jitsi info without service
func TestGetJitsiInfo_NoJitsiService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.GET("/api/v1/communication/jitsi/info", handler.GetJitsiInfo)
req, _ := http.NewRequest("GET", "/api/v1/communication/jitsi/info", nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestRegisterMatrixUser_NoMatrixService tests user registration without Matrix
func TestRegisterMatrixUser_NoMatrixService_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/admin/matrix/users", handler.RegisterMatrixUser)
body := `{"username": "testuser", "display_name": "Test User"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/admin/matrix/users", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestGetAdminStats_NoServices tests admin stats without services
func TestGetAdminStats_NoServices_ReturnsDisabledStats(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.GET("/api/v1/communication/admin/stats", handler.GetAdminStats)
req, _ := http.NewRequest("GET", "/api/v1/communication/admin/stats", nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response CommunicationStats
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Fatalf("Failed to parse response: %v", err)
}
if response.Matrix.Enabled {
t.Error("Expected matrix.enabled to be false")
}
if response.Jitsi.Enabled {
t.Error("Expected jitsi.enabled to be false")
}
}
// TestErrToString tests the helper function
func TestErrToString_NilError_ReturnsEmpty(t *testing.T) {
result := errToString(nil)
if result != "" {
t.Errorf("Expected empty string, got %s", result)
}
}
// TestErrToString_WithError_ReturnsMessage tests error string conversion
func TestErrToString_WithError_ReturnsMessage(t *testing.T) {
err := &testError{"test error message"}
result := errToString(err)
if result != "test error message" {
t.Errorf("Expected 'test error message', got %s", result)
}
}
// testError is a simple error implementation for testing
type testError struct {
message string
}
func (e *testError) Error() string {
return e.message
}
// TestCreateRoomRequest_Types tests different room types validation
func TestCreateRoom_InvalidType_Returns400(t *testing.T) {
gin.SetMode(gin.TestMode)
// Since we don't have Matrix service, we get 503 first
// This test documents expected behavior when Matrix IS available
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/rooms", handler.CreateRoom)
body := `{"type": "invalid_type", "class_name": "5b"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/rooms", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Without Matrix service, we get 503 before type validation
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestCreateMeeting_InvalidType tests invalid meeting type
func TestCreateMeeting_InvalidType_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/meetings", handler.CreateMeeting)
body := `{"type": "invalid", "display_name": "User"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/meetings", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Without Jitsi service, we get 503 before type validation
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestSendNotification_InvalidType tests invalid notification type
func TestSendNotification_InvalidType_Returns503(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewCommunicationHandlers(nil, nil)
router := gin.New()
router.POST("/api/v1/communication/notifications", handler.SendNotification)
body := `{"room_id": "!abc:server", "type": "invalid", "student_name": "Max"}`
req, _ := http.NewRequest("POST", "/api/v1/communication/notifications", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Without Matrix service, we get 503 before type validation
if w.Code != http.StatusServiceUnavailable {
t.Errorf("Expected status 503, got %d", w.Code)
}
}
// TestNewCommunicationHandlers tests constructor
func TestNewCommunicationHandlers_WithNilServices_CreatesHandler(t *testing.T) {
handler := NewCommunicationHandlers(nil, nil)
if handler == nil {
t.Fatal("Expected handler to be created")
}
if handler.matrixService != nil {
t.Error("Expected matrixService to be nil")
}
if handler.jitsiService != nil {
t.Error("Expected jitsiService to be nil")
}
}