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/consent_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

519 lines
12 KiB
Go

package services
import (
"testing"
"time"
"github.com/google/uuid"
)
// TestConsentService_CreateConsent tests creating a new consent
func TestConsentService_CreateConsent(t *testing.T) {
// This is a unit test with table-driven approach
tests := []struct {
name string
userID uuid.UUID
versionID uuid.UUID
consented bool
expectError bool
errorContains string
}{
{
name: "valid consent - accepted",
userID: uuid.New(),
versionID: uuid.New(),
consented: true,
expectError: false,
},
{
name: "valid consent - declined",
userID: uuid.New(),
versionID: uuid.New(),
consented: false,
expectError: false,
},
{
name: "empty user ID",
userID: uuid.Nil,
versionID: uuid.New(),
consented: true,
expectError: true,
errorContains: "user ID",
},
{
name: "empty version ID",
userID: uuid.New(),
versionID: uuid.Nil,
consented: true,
expectError: true,
errorContains: "version ID",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Validate inputs (in real implementation this would be in the service)
var hasError bool
if tt.userID == uuid.Nil {
hasError = true
} else if tt.versionID == uuid.Nil {
hasError = true
}
// Assert
if tt.expectError && !hasError {
t.Errorf("Expected error containing '%s', got nil", tt.errorContains)
}
if !tt.expectError && hasError {
t.Error("Expected no error, got error")
}
})
}
}
// TestConsentService_WithdrawConsent tests withdrawing consent
func TestConsentService_WithdrawConsent(t *testing.T) {
tests := []struct {
name string
consentID uuid.UUID
userID uuid.UUID
expectError bool
errorContains string
}{
{
name: "valid withdrawal",
consentID: uuid.New(),
userID: uuid.New(),
expectError: false,
},
{
name: "empty consent ID",
consentID: uuid.Nil,
userID: uuid.New(),
expectError: true,
errorContains: "consent ID",
},
{
name: "empty user ID",
consentID: uuid.New(),
userID: uuid.Nil,
expectError: true,
errorContains: "user ID",
},
{
name: "both empty",
consentID: uuid.Nil,
userID: uuid.Nil,
expectError: true,
errorContains: "ID",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Validate
var hasError bool
if tt.consentID == uuid.Nil || tt.userID == uuid.Nil {
hasError = true
}
// Assert
if tt.expectError && !hasError {
t.Errorf("Expected error containing '%s', got nil", tt.errorContains)
}
if !tt.expectError && hasError {
t.Error("Expected no error, got error")
}
})
}
}
// TestConsentService_CheckConsent tests checking consent status
func TestConsentService_CheckConsent(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
documentType string
language string
hasConsent bool
needsUpdate bool
expectedConsent bool
expectedNeedsUpd bool
}{
{
name: "user has current consent",
userID: uuid.New(),
documentType: "terms",
language: "de",
hasConsent: true,
needsUpdate: false,
expectedConsent: true,
expectedNeedsUpd: false,
},
{
name: "user has outdated consent",
userID: uuid.New(),
documentType: "privacy",
language: "de",
hasConsent: true,
needsUpdate: true,
expectedConsent: true,
expectedNeedsUpd: true,
},
{
name: "user has no consent",
userID: uuid.New(),
documentType: "cookies",
language: "de",
hasConsent: false,
needsUpdate: true,
expectedConsent: false,
expectedNeedsUpd: true,
},
{
name: "english language",
userID: uuid.New(),
documentType: "terms",
language: "en",
hasConsent: true,
needsUpdate: false,
expectedConsent: true,
expectedNeedsUpd: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Simulate consent check logic
hasConsent := tt.hasConsent
needsUpdate := tt.needsUpdate
// Assert
if hasConsent != tt.expectedConsent {
t.Errorf("Expected hasConsent=%v, got %v", tt.expectedConsent, hasConsent)
}
if needsUpdate != tt.expectedNeedsUpd {
t.Errorf("Expected needsUpdate=%v, got %v", tt.expectedNeedsUpd, needsUpdate)
}
})
}
}
// TestConsentService_GetConsentHistory tests retrieving consent history
func TestConsentService_GetConsentHistory(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
expectError bool
expectEmpty bool
}{
{
name: "valid user with consents",
userID: uuid.New(),
expectError: false,
expectEmpty: false,
},
{
name: "valid user without consents",
userID: uuid.New(),
expectError: false,
expectEmpty: true,
},
{
name: "invalid user ID",
userID: uuid.Nil,
expectError: true,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Validate
var err error
if tt.userID == uuid.Nil {
err = &ValidationError{Field: "user ID", Message: "required"}
}
// Assert error expectation
if tt.expectError && err == nil {
t.Error("Expected error, got nil")
}
if !tt.expectError && err != nil {
t.Errorf("Expected no error, got %v", err)
}
})
}
}
// TestConsentService_UpdateConsent tests updating existing consent
func TestConsentService_UpdateConsent(t *testing.T) {
tests := []struct {
name string
consentID uuid.UUID
userID uuid.UUID
newConsented bool
expectError bool
}{
{
name: "update to consented",
consentID: uuid.New(),
userID: uuid.New(),
newConsented: true,
expectError: false,
},
{
name: "update to not consented",
consentID: uuid.New(),
userID: uuid.New(),
newConsented: false,
expectError: false,
},
{
name: "invalid consent ID",
consentID: uuid.Nil,
userID: uuid.New(),
newConsented: true,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var err error
if tt.consentID == uuid.Nil {
err = &ValidationError{Field: "consent 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)
}
})
}
}
// TestConsentService_GetConsentStats tests getting consent statistics
func TestConsentService_GetConsentStats(t *testing.T) {
tests := []struct {
name string
documentType string
totalUsers int
consentedUsers int
expectedRate float64
}{
{
name: "100% consent rate",
documentType: "terms",
totalUsers: 100,
consentedUsers: 100,
expectedRate: 100.0,
},
{
name: "50% consent rate",
documentType: "privacy",
totalUsers: 100,
consentedUsers: 50,
expectedRate: 50.0,
},
{
name: "0% consent rate",
documentType: "cookies",
totalUsers: 100,
consentedUsers: 0,
expectedRate: 0.0,
},
{
name: "no users",
documentType: "terms",
totalUsers: 0,
consentedUsers: 0,
expectedRate: 0.0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Calculate consent rate
var consentRate float64
if tt.totalUsers > 0 {
consentRate = float64(tt.consentedUsers) / float64(tt.totalUsers) * 100
}
// Assert
if consentRate != tt.expectedRate {
t.Errorf("Expected consent rate %.2f%%, got %.2f%%", tt.expectedRate, consentRate)
}
})
}
}
// TestConsentService_BulkConsentCheck tests checking multiple consents at once
func TestConsentService_BulkConsentCheck(t *testing.T) {
tests := []struct {
name string
userID uuid.UUID
documentTypes []string
expectError bool
}{
{
name: "check multiple documents",
userID: uuid.New(),
documentTypes: []string{"terms", "privacy", "cookies"},
expectError: false,
},
{
name: "check single document",
userID: uuid.New(),
documentTypes: []string{"terms"},
expectError: false,
},
{
name: "empty document list",
userID: uuid.New(),
documentTypes: []string{},
expectError: false,
},
{
name: "invalid user ID",
userID: uuid.Nil,
documentTypes: []string{"terms"},
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)
}
})
}
}
// TestConsentService_ConsentVersionComparison tests version comparison logic
func TestConsentService_ConsentVersionComparison(t *testing.T) {
tests := []struct {
name string
currentVersion string
consentedVersion string
needsUpdate bool
}{
{
name: "same version",
currentVersion: "1.0.0",
consentedVersion: "1.0.0",
needsUpdate: false,
},
{
name: "minor version update",
currentVersion: "1.1.0",
consentedVersion: "1.0.0",
needsUpdate: true,
},
{
name: "major version update",
currentVersion: "2.0.0",
consentedVersion: "1.0.0",
needsUpdate: true,
},
{
name: "patch version update",
currentVersion: "1.0.1",
consentedVersion: "1.0.0",
needsUpdate: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Simple version comparison (in real implementation use proper semver)
needsUpdate := tt.currentVersion != tt.consentedVersion
if needsUpdate != tt.needsUpdate {
t.Errorf("Expected needsUpdate=%v, got %v", tt.needsUpdate, needsUpdate)
}
})
}
}
// TestConsentService_ConsentDeadlineCheck tests deadline validation
func TestConsentService_ConsentDeadlineCheck(t *testing.T) {
now := time.Now()
tests := []struct {
name string
deadline time.Time
isOverdue bool
daysLeft int
}{
{
name: "deadline in 30 days",
deadline: now.AddDate(0, 0, 30),
isOverdue: false,
daysLeft: 30,
},
{
name: "deadline in 7 days",
deadline: now.AddDate(0, 0, 7),
isOverdue: false,
daysLeft: 7,
},
{
name: "deadline today",
deadline: now,
isOverdue: false,
daysLeft: 0,
},
{
name: "deadline 1 day overdue",
deadline: now.AddDate(0, 0, -1),
isOverdue: true,
daysLeft: -1,
},
{
name: "deadline 30 days overdue",
deadline: now.AddDate(0, 0, -30),
isOverdue: true,
daysLeft: -30,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Calculate if overdue
isOverdue := tt.deadline.Before(now)
daysLeft := int(tt.deadline.Sub(now).Hours() / 24)
if isOverdue != tt.isOverdue {
t.Errorf("Expected isOverdue=%v, got %v", tt.isOverdue, isOverdue)
}
// Allow 1 day difference due to time precision
if abs(daysLeft-tt.daysLeft) > 1 {
t.Errorf("Expected daysLeft=%d, got %d", tt.daysLeft, daysLeft)
}
})
}
}
// Helper functions
// abs returns the absolute value of an integer
func abs(n int) int {
if n < 0 {
return -n
}
return n
}