package services import ( "testing" "github.com/breakpilot/school-service/internal/models" ) func TestUpsertSchoolCalendarConfigRequest_Validation(t *testing.T) { tests := []struct { name string req models.UpsertSchoolCalendarConfigRequest wantErr bool }{ {"valid NI", models.UpsertSchoolCalendarConfigRequest{Bundesland: "DE-NI"}, false}, {"empty bundesland", models.UpsertSchoolCalendarConfigRequest{Bundesland: ""}, true}, {"too long", models.UpsertSchoolCalendarConfigRequest{Bundesland: "DE-NIE"}, true}, {"too short", models.UpsertSchoolCalendarConfigRequest{Bundesland: "DE"}, 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 for %s", tt.name) } }) } } func TestCreateSchoolEventRequest_Validation(t *testing.T) { tests := []struct { name string req models.CreateSchoolEventRequest wantErr bool }{ {"valid fortbildung", models.CreateSchoolEventRequest{ Title: "SCHILF", EventType: "fortbildung", StartDate: "2026-10-01", EndDate: "2026-10-01", }, false}, {"missing title", models.CreateSchoolEventRequest{ EventType: "fortbildung", StartDate: "2026-10-01", EndDate: "2026-10-01", }, true}, {"invalid event type", models.CreateSchoolEventRequest{ Title: "X", EventType: "wedding", StartDate: "2026-10-01", EndDate: "2026-10-01", }, true}, {"missing dates", models.CreateSchoolEventRequest{ Title: "X", EventType: "schulfeier", }, 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 for %s", tt.name) } }) } } func TestNewCalendarService_Constructs(t *testing.T) { s := NewCalendarService(nil) if s == nil { t.Fatal("expected non-nil service") } } func TestDefaultSchoolYearDates_FallbackFormat(t *testing.T) { // No override → deterministic YYYY-MM-DD strings with end > start. start, end := defaultSchoolYearDates(nil) if len(start) != 10 || len(end) != 10 { t.Fatalf("expected YYYY-MM-DD strings, got %q %q", start, end) } if end <= start { t.Errorf("end %q must be after start %q", end, start) } } func TestDefaultSchoolYearDates_ExplicitOverride(t *testing.T) { s, e := "2030-09-01", "2031-06-30" req := &models.SchoolYearRolloverRequest{NewYearStart: &s, NewYearEnd: &e} gotS, gotE := defaultSchoolYearDates(req) if gotS != s || gotE != e { t.Errorf("override ignored: got %q/%q want %q/%q", gotS, gotE, s, e) } } func TestParseClassIDs_AcceptsValidAndRejectsGarbage(t *testing.T) { good := []string{"00000000-0000-0000-0000-000000000001", "00000000-0000-0000-0000-000000000002"} out, err := parseClassIDs(good) if err != nil || len(out) != 2 { t.Fatalf("expected 2 parsed UUIDs, got %v err=%v", out, err) } if _, err := parseClassIDs([]string{"not-a-uuid"}); err == nil { t.Errorf("expected error for invalid uuid") } // Empty strings are silently dropped (curl convenience). out, err = parseClassIDs([]string{"", "00000000-0000-0000-0000-000000000003", ""}) if err != nil || len(out) != 1 { t.Errorf("expected 1 parsed UUID, got %v err=%v", out, err) } }