package services import ( "testing" "github.com/breakpilot/school-service/internal/models" ) // Additional validator tests covering the 9 constraint DTOs not exercised in // timetable_constraints_test.go. Each entry probes both the happy path and // the boundary that the binding tags are supposed to reject. const ( uidTeacher = "00000000-0000-0000-0000-0000000000a1" uidSubject = "00000000-0000-0000-0000-0000000000a2" uidClass = "00000000-0000-0000-0000-0000000000a3" uidRoom = "00000000-0000-0000-0000-0000000000a4" ) func TestCreateTeacherMaxHoursDayRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateTeacherMaxHoursDayRequest wantErr bool }{ {"valid", models.CreateTeacherMaxHoursDayRequest{TeacherID: uidTeacher, MaxHours: 6, IsHard: false, Weight: 50}, false}, {"missing teacher", models.CreateTeacherMaxHoursDayRequest{MaxHours: 6}, true}, {"hours below 1", models.CreateTeacherMaxHoursDayRequest{TeacherID: uidTeacher, MaxHours: 0}, true}, {"hours above 12", models.CreateTeacherMaxHoursDayRequest{TeacherID: uidTeacher, MaxHours: 13}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateTeacherMaxHoursWeekRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateTeacherMaxHoursWeekRequest wantErr bool }{ {"valid", models.CreateTeacherMaxHoursWeekRequest{TeacherID: uidTeacher, MaxHours: 28, IsHard: true, Weight: 100}, false}, {"hours below 1", models.CreateTeacherMaxHoursWeekRequest{TeacherID: uidTeacher, MaxHours: 0}, true}, {"hours above 40", models.CreateTeacherMaxHoursWeekRequest{TeacherID: uidTeacher, MaxHours: 41}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateTeacherExcludedSubjectRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateTeacherExcludedSubjectRequest wantErr bool }{ {"valid", models.CreateTeacherExcludedSubjectRequest{TeacherID: uidTeacher, SubjectID: uidSubject, IsHard: true, Weight: 100}, false}, {"missing subject", models.CreateTeacherExcludedSubjectRequest{TeacherID: uidTeacher}, true}, {"non-uuid subject", models.CreateTeacherExcludedSubjectRequest{TeacherID: uidTeacher, SubjectID: "nope"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateTeacherExcludedRoomRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateTeacherExcludedRoomRequest wantErr bool }{ {"valid", models.CreateTeacherExcludedRoomRequest{TeacherID: uidTeacher, RoomID: uidRoom, IsHard: true, Weight: 100}, false}, {"missing room", models.CreateTeacherExcludedRoomRequest{TeacherID: uidTeacher}, true}, {"non-uuid room", models.CreateTeacherExcludedRoomRequest{TeacherID: uidTeacher, RoomID: "nope"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateSubjectMinDayGapRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateSubjectMinDayGapRequest wantErr bool }{ {"valid", models.CreateSubjectMinDayGapRequest{SubjectID: uidSubject, MinGapDays: 1, IsHard: false, Weight: 70}, false}, {"below 1", models.CreateSubjectMinDayGapRequest{SubjectID: uidSubject, MinGapDays: 0}, true}, {"above 4", models.CreateSubjectMinDayGapRequest{SubjectID: uidSubject, MinGapDays: 5}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateSubjectContiguousWhenRepeatedRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateSubjectContiguousWhenRepeatedRequest wantErr bool }{ {"valid", models.CreateSubjectContiguousWhenRepeatedRequest{SubjectID: uidSubject, IsHard: true, Weight: 100}, false}, {"missing subject", models.CreateSubjectContiguousWhenRepeatedRequest{}, true}, {"weight above 100", models.CreateSubjectContiguousWhenRepeatedRequest{SubjectID: uidSubject, Weight: 200}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateSubjectDoubleLessonRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateSubjectDoubleLessonRequest wantErr bool }{ {"valid", models.CreateSubjectDoubleLessonRequest{SubjectID: uidSubject, IsHard: false, Weight: 60}, false}, {"missing subject", models.CreateSubjectDoubleLessonRequest{}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateClassNoGapsRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateClassNoGapsRequest wantErr bool }{ {"valid", models.CreateClassNoGapsRequest{ClassID: uidClass, IsHard: false, Weight: 80}, false}, {"missing class", models.CreateClassNoGapsRequest{}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } } func TestCreateRoomRequiresTypeRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateRoomRequiresTypeRequest wantErr bool }{ {"valid", models.CreateRoomRequiresTypeRequest{SubjectID: uidSubject, RoomType: "Sporthalle", IsHard: true, Weight: 100}, false}, {"missing room type", models.CreateRoomRequiresTypeRequest{SubjectID: uidSubject}, true}, {"non-uuid subject", models.CreateRoomRequiresTypeRequest{SubjectID: "x", RoomType: "y"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome") } }) } }