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 }