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/services/notification_service_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

661 lines
16 KiB
Go

package services
import (
"testing"
"time"
"github.com/google/uuid"
)
// TestNotificationService_CreateNotification tests notification creation
func TestNotificationService_CreateNotification(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
notifType NotificationType
title string
body string
data map[string]interface{}
expectError bool
}{
{
name: "valid notification",
userID: uuid.New(),
notifType: NotificationTypeConsentRequired,
title: "Consent Required",
body: "Please review and accept the new terms",
data: map[string]interface{}{"document_id": "123"},
expectError: false,
},
{
name: "notification without data",
userID: uuid.New(),
notifType: NotificationTypeGeneral,
title: "General Notification",
body: "This is a test",
data: nil,
expectError: false,
},
{
name: "empty user ID",
userID: uuid.Nil,
notifType: NotificationTypeGeneral,
title: "Test",
body: "Test",
expectError: true,
},
{
name: "empty title",
userID: uuid.New(),
notifType: NotificationTypeGeneral,
title: "",
body: "Test body",
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
} else if tt.title == "" {
err = &ValidationError{Field: "title", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_NotificationTypes tests notification type validation
func TestNotificationService_NotificationTypes(t *testing.T) {
tests := []struct {
notifType NotificationType
isValid bool
}{
{NotificationTypeConsentRequired, true},
{NotificationTypeConsentReminder, true},
{NotificationTypeVersionPublished, true},
{NotificationTypeVersionApproved, true},
{NotificationTypeVersionRejected, true},
{NotificationTypeAccountSuspended, true},
{NotificationTypeAccountRestored, true},
{NotificationTypeGeneral, true},
{NotificationType("invalid_type"), false},
{NotificationType(""), false},
}
validTypes := map[NotificationType]bool{
NotificationTypeConsentRequired: true,
NotificationTypeConsentReminder: true,
NotificationTypeVersionPublished: true,
NotificationTypeVersionApproved: true,
NotificationTypeVersionRejected: true,
NotificationTypeAccountSuspended: true,
NotificationTypeAccountRestored: true,
NotificationTypeGeneral: true,
}
for _, tt := range tests {
t.Run(string(tt.notifType), func(t *testing.T) {
isValid := validTypes[tt.notifType]
if isValid != tt.isValid {
t.Errorf("Type %s: expected valid=%v, got %v", tt.notifType, tt.isValid, isValid)
}
})
}
}
// TestNotificationService_NotificationChannels tests channel validation
func TestNotificationService_NotificationChannels(t *testing.T) {
tests := []struct {
channel NotificationChannel
isValid bool
}{
{ChannelInApp, true},
{ChannelEmail, true},
{ChannelPush, true},
{NotificationChannel("sms"), false},
{NotificationChannel(""), false},
}
validChannels := map[NotificationChannel]bool{
ChannelInApp: true,
ChannelEmail: true,
ChannelPush: true,
}
for _, tt := range tests {
t.Run(string(tt.channel), func(t *testing.T) {
isValid := validChannels[tt.channel]
if isValid != tt.isValid {
t.Errorf("Channel %s: expected valid=%v, got %v", tt.channel, tt.isValid, isValid)
}
})
}
}
// TestNotificationService_GetUserNotifications tests retrieving notifications
func TestNotificationService_GetUserNotifications(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
limit int
offset int
unreadOnly bool
expectError bool
}{
{
name: "get all notifications",
userID: uuid.New(),
limit: 50,
offset: 0,
unreadOnly: false,
expectError: false,
},
{
name: "get unread only",
userID: uuid.New(),
limit: 50,
offset: 0,
unreadOnly: true,
expectError: false,
},
{
name: "with pagination",
userID: uuid.New(),
limit: 10,
offset: 20,
unreadOnly: false,
expectError: false,
},
{
name: "invalid user ID",
userID: uuid.Nil,
limit: 50,
offset: 0,
unreadOnly: false,
expectError: true,
},
{
name: "negative limit",
userID: uuid.New(),
limit: -1,
offset: 0,
unreadOnly: false,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
} else if tt.limit < 0 {
err = &ValidationError{Field: "limit", Message: "must be >= 0"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_MarkAsRead tests marking notifications as read
func TestNotificationService_MarkAsRead(t *testing.T) {
tests := []struct {
name string
notificationID uuid.UUID
userID uuid.UUID
expectError bool
}{
{
name: "mark valid notification as read",
notificationID: uuid.New(),
userID: uuid.New(),
expectError: false,
},
{
name: "invalid notification ID",
notificationID: uuid.Nil,
userID: uuid.New(),
expectError: true,
},
{
name: "invalid user ID",
notificationID: uuid.New(),
userID: uuid.Nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.notificationID == uuid.Nil {
err = &ValidationError{Field: "notification ID", Message: "required"}
} else if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_GetPreferences tests retrieving user preferences
func TestNotificationService_GetPreferences(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
expectError bool
}{
{
name: "get valid user preferences",
userID: uuid.New(),
expectError: false,
},
{
name: "invalid user ID",
userID: uuid.Nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_UpdatePreferences tests updating notification preferences
func TestNotificationService_UpdatePreferences(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
emailEnabled bool
pushEnabled bool
inAppEnabled bool
reminderFrequency string
expectError bool
}{
{
name: "enable all notifications",
userID: uuid.New(),
emailEnabled: true,
pushEnabled: true,
inAppEnabled: true,
reminderFrequency: "daily",
expectError: false,
},
{
name: "disable email notifications",
userID: uuid.New(),
emailEnabled: false,
pushEnabled: true,
inAppEnabled: true,
reminderFrequency: "weekly",
expectError: false,
},
{
name: "set reminder frequency to never",
userID: uuid.New(),
emailEnabled: true,
pushEnabled: false,
inAppEnabled: true,
reminderFrequency: "never",
expectError: false,
},
{
name: "invalid reminder frequency",
userID: uuid.New(),
emailEnabled: true,
pushEnabled: true,
inAppEnabled: true,
reminderFrequency: "hourly",
expectError: true,
},
}
validFrequencies := map[string]bool{
"daily": true,
"weekly": true,
"never": true,
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if !validFrequencies[tt.reminderFrequency] {
err = &ValidationError{Field: "reminder_frequency", Message: "must be daily, weekly, or never"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_NotifyConsentRequired tests consent required notification
func TestNotificationService_NotifyConsentRequired(t *testing.T) {
tests := []struct {
name string
documentName string
versionID string
expectError bool
}{
{
name: "valid consent notification",
documentName: "Terms of Service",
versionID: uuid.New().String(),
expectError: false,
},
{
name: "empty document name",
documentName: "",
versionID: uuid.New().String(),
expectError: true,
},
{
name: "empty version ID",
documentName: "Privacy Policy",
versionID: "",
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.documentName == "" {
err = &ValidationError{Field: "document name", Message: "required"}
} else if tt.versionID == "" {
err = &ValidationError{Field: "version ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_DeleteNotification tests deleting notifications
func TestNotificationService_DeleteNotification(t *testing.T) {
tests := []struct {
name string
notificationID uuid.UUID
userID uuid.UUID
expectError bool
}{
{
name: "delete valid notification",
notificationID: uuid.New(),
userID: uuid.New(),
expectError: false,
},
{
name: "invalid notification ID",
notificationID: uuid.Nil,
userID: uuid.New(),
expectError: true,
},
{
name: "invalid user ID",
notificationID: uuid.New(),
userID: uuid.Nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.notificationID == uuid.Nil {
err = &ValidationError{Field: "notification ID", Message: "required"}
} else if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_BatchMarkAsRead tests batch marking as read
func TestNotificationService_BatchMarkAsRead(t *testing.T) {
tests := []struct {
name string
notificationIDs []uuid.UUID
userID uuid.UUID
expectError bool
}{
{
name: "mark multiple notifications",
notificationIDs: []uuid.UUID{uuid.New(), uuid.New(), uuid.New()},
userID: uuid.New(),
expectError: false,
},
{
name: "empty list",
notificationIDs: []uuid.UUID{},
userID: uuid.New(),
expectError: false,
},
{
name: "invalid user ID",
notificationIDs: []uuid.UUID{uuid.New()},
userID: uuid.Nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_GetUnreadCount tests getting unread count
func TestNotificationService_GetUnreadCount(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
expectError bool
}{
{
name: "get count for valid user",
userID: uuid.New(),
expectError: false,
},
{
name: "invalid user ID",
userID: uuid.Nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestNotificationService_NotificationPriority tests notification priority
func TestNotificationService_NotificationPriority(t *testing.T) {
tests := []struct {
name string
notifType NotificationType
expectedPrio string
}{
{
name: "consent required - high priority",
notifType: NotificationTypeConsentRequired,
expectedPrio: "high",
},
{
name: "account suspended - critical",
notifType: NotificationTypeAccountSuspended,
expectedPrio: "critical",
},
{
name: "version published - normal",
notifType: NotificationTypeVersionPublished,
expectedPrio: "normal",
},
{
name: "general - low",
notifType: NotificationTypeGeneral,
expectedPrio: "low",
},
}
priorityMap := map[NotificationType]string{
NotificationTypeConsentRequired: "high",
NotificationTypeConsentReminder: "high",
NotificationTypeAccountSuspended: "critical",
NotificationTypeAccountRestored: "normal",
NotificationTypeVersionPublished: "normal",
NotificationTypeVersionApproved: "normal",
NotificationTypeVersionRejected: "normal",
NotificationTypeGeneral: "low",
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
priority := priorityMap[tt.notifType]
if priority != tt.expectedPrio {
t.Errorf("Expected priority %s, got %s", tt.expectedPrio, priority)
}
})
}
}
// TestNotificationService_ReminderFrequency tests reminder frequency logic
func TestNotificationService_ReminderFrequency(t *testing.T) {
now := time.Now()
tests := []struct {
name string
frequency string
lastReminder time.Time
shouldSend bool
}{
{
name: "daily - last sent yesterday",
frequency: "daily",
lastReminder: now.AddDate(0, 0, -1),
shouldSend: true,
},
{
name: "daily - last sent today",
frequency: "daily",
lastReminder: now.Add(-1 * time.Hour),
shouldSend: false,
},
{
name: "weekly - last sent 8 days ago",
frequency: "weekly",
lastReminder: now.AddDate(0, 0, -8),
shouldSend: true,
},
{
name: "weekly - last sent 5 days ago",
frequency: "weekly",
lastReminder: now.AddDate(0, 0, -5),
shouldSend: false,
},
{
name: "never - should not send",
frequency: "never",
lastReminder: now.AddDate(0, 0, -30),
shouldSend: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var shouldSend bool
switch tt.frequency {
case "daily":
daysSince := int(now.Sub(tt.lastReminder).Hours() / 24)
shouldSend = daysSince >= 1
case "weekly":
daysSince := int(now.Sub(tt.lastReminder).Hours() / 24)
shouldSend = daysSince >= 7
case "never":
shouldSend = false
}
if shouldSend != tt.shouldSend {
t.Errorf("Expected shouldSend=%v, got %v", tt.shouldSend, shouldSend)
}
})
}
}