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>
425 lines
9.2 KiB
Go
425 lines
9.2 KiB
Go
package services
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/breakpilot/consent-service/internal/models"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// TestGenerateOnboardingToken tests the QR code token generation
|
|
func TestGenerateOnboardingToken(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
studentID uuid.UUID
|
|
createdBy uuid.UUID
|
|
role string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "valid parent token",
|
|
studentID: uuid.New(),
|
|
createdBy: uuid.New(),
|
|
role: "parent",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "valid parent_representative token",
|
|
studentID: uuid.New(),
|
|
createdBy: uuid.New(),
|
|
role: "parent_representative",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "empty student ID",
|
|
studentID: uuid.Nil,
|
|
createdBy: uuid.New(),
|
|
role: "parent",
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
token := &models.ParentOnboardingToken{
|
|
StudentID: tt.studentID,
|
|
CreatedBy: tt.createdBy,
|
|
Role: tt.role,
|
|
ExpiresAt: time.Now().Add(7 * 24 * time.Hour),
|
|
}
|
|
|
|
// Validate token fields
|
|
if tt.studentID == uuid.Nil && !tt.expectError {
|
|
t.Errorf("expected error for empty student ID")
|
|
}
|
|
|
|
if token.Role != "parent" && token.Role != "parent_representative" {
|
|
if !tt.expectError {
|
|
t.Errorf("invalid role: %s", token.Role)
|
|
}
|
|
}
|
|
|
|
// Check expiration is in the future
|
|
if token.ExpiresAt.Before(time.Now()) {
|
|
t.Errorf("token expiration should be in the future")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestValidateSchoolData tests school data validation
|
|
func TestValidateSchoolData(t *testing.T) {
|
|
address1 := "Musterstraße 1, 20095 Hamburg"
|
|
address2 := "Musterstraße 1"
|
|
address3 := "Parkweg 5"
|
|
|
|
tests := []struct {
|
|
name string
|
|
school models.School
|
|
expectValid bool
|
|
}{
|
|
{
|
|
name: "valid school",
|
|
school: models.School{
|
|
Name: "Testschule Hamburg",
|
|
Address: &address1,
|
|
Type: "gymnasium",
|
|
},
|
|
expectValid: true,
|
|
},
|
|
{
|
|
name: "empty name",
|
|
school: models.School{
|
|
Name: "",
|
|
Address: &address2,
|
|
Type: "gymnasium",
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "valid grundschule",
|
|
school: models.School{
|
|
Name: "Grundschule Am Park",
|
|
Address: &address3,
|
|
Type: "grundschule",
|
|
},
|
|
expectValid: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isValid := validateSchool(tt.school)
|
|
if isValid != tt.expectValid {
|
|
t.Errorf("expected valid=%v, got valid=%v", tt.expectValid, isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// validateSchool is a helper function for validation
|
|
func validateSchool(school models.School) bool {
|
|
if school.Name == "" {
|
|
return false
|
|
}
|
|
if school.Type == "" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// TestValidateClassData tests class data validation
|
|
func TestValidateClassData(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
class models.Class
|
|
expectValid bool
|
|
}{
|
|
{
|
|
name: "valid class 5a",
|
|
class: models.Class{
|
|
Name: "5a",
|
|
Grade: 5,
|
|
SchoolID: uuid.New(),
|
|
SchoolYearID: uuid.New(),
|
|
},
|
|
expectValid: true,
|
|
},
|
|
{
|
|
name: "invalid grade level 0",
|
|
class: models.Class{
|
|
Name: "0a",
|
|
Grade: 0,
|
|
SchoolID: uuid.New(),
|
|
SchoolYearID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "invalid grade level 14",
|
|
class: models.Class{
|
|
Name: "14a",
|
|
Grade: 14,
|
|
SchoolID: uuid.New(),
|
|
SchoolYearID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "missing school ID",
|
|
class: models.Class{
|
|
Name: "5a",
|
|
Grade: 5,
|
|
SchoolID: uuid.Nil,
|
|
SchoolYearID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isValid := validateClass(tt.class)
|
|
if isValid != tt.expectValid {
|
|
t.Errorf("expected valid=%v, got valid=%v", tt.expectValid, isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// validateClass is a helper function for class validation
|
|
func validateClass(class models.Class) bool {
|
|
if class.Name == "" {
|
|
return false
|
|
}
|
|
if class.Grade < 1 || class.Grade > 13 {
|
|
return false
|
|
}
|
|
if class.SchoolID == uuid.Nil {
|
|
return false
|
|
}
|
|
if class.SchoolYearID == uuid.Nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// TestValidateStudentData tests student data validation
|
|
func TestValidateStudentData(t *testing.T) {
|
|
dob := time.Date(2014, 5, 15, 0, 0, 0, 0, time.UTC)
|
|
futureDob := time.Now().AddDate(1, 0, 0)
|
|
studentNum := "2024-001"
|
|
|
|
tests := []struct {
|
|
name string
|
|
student models.Student
|
|
expectValid bool
|
|
}{
|
|
{
|
|
name: "valid student",
|
|
student: models.Student{
|
|
FirstName: "Max",
|
|
LastName: "Mustermann",
|
|
DateOfBirth: &dob,
|
|
SchoolID: uuid.New(),
|
|
ClassID: uuid.New(),
|
|
StudentNumber: &studentNum,
|
|
},
|
|
expectValid: true,
|
|
},
|
|
{
|
|
name: "empty first name",
|
|
student: models.Student{
|
|
FirstName: "",
|
|
LastName: "Mustermann",
|
|
DateOfBirth: &dob,
|
|
SchoolID: uuid.New(),
|
|
ClassID: uuid.New(),
|
|
StudentNumber: &studentNum,
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "future birth date",
|
|
student: models.Student{
|
|
FirstName: "Max",
|
|
LastName: "Mustermann",
|
|
DateOfBirth: &futureDob,
|
|
SchoolID: uuid.New(),
|
|
ClassID: uuid.New(),
|
|
StudentNumber: &studentNum,
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "missing class ID",
|
|
student: models.Student{
|
|
FirstName: "Max",
|
|
LastName: "Mustermann",
|
|
DateOfBirth: &dob,
|
|
SchoolID: uuid.New(),
|
|
ClassID: uuid.Nil,
|
|
StudentNumber: &studentNum,
|
|
},
|
|
expectValid: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isValid := validateStudent(tt.student)
|
|
if isValid != tt.expectValid {
|
|
t.Errorf("expected valid=%v, got valid=%v", tt.expectValid, isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// validateStudent is a helper function for student validation
|
|
func validateStudent(student models.Student) bool {
|
|
if student.FirstName == "" || student.LastName == "" {
|
|
return false
|
|
}
|
|
if student.DateOfBirth != nil && student.DateOfBirth.After(time.Now()) {
|
|
return false
|
|
}
|
|
if student.ClassID == uuid.Nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// TestValidateTeacherData tests teacher data validation
|
|
func TestValidateTeacherData(t *testing.T) {
|
|
code := "SCH"
|
|
codeLong := "SCHMI"
|
|
|
|
tests := []struct {
|
|
name string
|
|
teacher models.Teacher
|
|
expectValid bool
|
|
}{
|
|
{
|
|
name: "valid teacher",
|
|
teacher: models.Teacher{
|
|
FirstName: "Anna",
|
|
LastName: "Schmidt",
|
|
UserID: uuid.New(),
|
|
TeacherCode: &code,
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: true,
|
|
},
|
|
{
|
|
name: "empty first name",
|
|
teacher: models.Teacher{
|
|
FirstName: "",
|
|
LastName: "Schmidt",
|
|
UserID: uuid.New(),
|
|
TeacherCode: &code,
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "teacher code too long",
|
|
teacher: models.Teacher{
|
|
FirstName: "Anna",
|
|
LastName: "Schmidt",
|
|
UserID: uuid.New(),
|
|
TeacherCode: &codeLong,
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isValid := validateTeacher(tt.teacher)
|
|
if isValid != tt.expectValid {
|
|
t.Errorf("expected valid=%v, got valid=%v", tt.expectValid, isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// validateTeacher is a helper function for teacher validation
|
|
func validateTeacher(teacher models.Teacher) bool {
|
|
if teacher.FirstName == "" || teacher.LastName == "" {
|
|
return false
|
|
}
|
|
if teacher.TeacherCode != nil && len(*teacher.TeacherCode) > 4 {
|
|
return false
|
|
}
|
|
if teacher.SchoolID == uuid.Nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// TestSchoolYearValidation tests school year date validation
|
|
func TestSchoolYearValidation(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
year models.SchoolYear
|
|
expectValid bool
|
|
}{
|
|
{
|
|
name: "valid school year 2024/2025",
|
|
year: models.SchoolYear{
|
|
Name: "2024/2025",
|
|
StartDate: time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC),
|
|
EndDate: time.Date(2025, 7, 31, 0, 0, 0, 0, time.UTC),
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: true,
|
|
},
|
|
{
|
|
name: "end before start",
|
|
year: models.SchoolYear{
|
|
Name: "2024/2025",
|
|
StartDate: time.Date(2025, 8, 1, 0, 0, 0, 0, time.UTC),
|
|
EndDate: time.Date(2024, 7, 31, 0, 0, 0, 0, time.UTC),
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
{
|
|
name: "same start and end",
|
|
year: models.SchoolYear{
|
|
Name: "2024/2025",
|
|
StartDate: time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC),
|
|
EndDate: time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC),
|
|
SchoolID: uuid.New(),
|
|
},
|
|
expectValid: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isValid := validateSchoolYear(tt.year)
|
|
if isValid != tt.expectValid {
|
|
t.Errorf("expected valid=%v, got valid=%v", tt.expectValid, isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// validateSchoolYear is a helper function for school year validation
|
|
func validateSchoolYear(year models.SchoolYear) bool {
|
|
if year.Name == "" {
|
|
return false
|
|
}
|
|
if year.SchoolID == uuid.Nil {
|
|
return false
|
|
}
|
|
if !year.EndDate.After(year.StartDate) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|