- Holiday service with German federal holidays, Easter calculation, DB loading - Deadline calculator adapted from youpc.org (duration calc + non-working day adjustment) - Deadline CRUD service (tenant-scoped: list, create, update, complete, delete) - Deadline rule service (list, filter by proceeding type, hierarchical rule trees) - HTTP handlers for all endpoints with tenant resolution via X-Tenant-ID header - Router wired with all new endpoints under /api/ - Tests for holiday and calculator services (8 passing)
122 lines
3.0 KiB
Go
122 lines
3.0 KiB
Go
package services
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCalculateEasterSunday(t *testing.T) {
|
|
tests := []struct {
|
|
year int
|
|
wantMonth int
|
|
wantDay int
|
|
}{
|
|
{2024, 3, 31},
|
|
{2025, 4, 20},
|
|
{2026, 4, 5},
|
|
{2027, 3, 28},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
m, d := CalculateEasterSunday(tt.year)
|
|
if m != tt.wantMonth || d != tt.wantDay {
|
|
t.Errorf("CalculateEasterSunday(%d) = %d-%02d, want %d-%02d",
|
|
tt.year, m, d, tt.wantMonth, tt.wantDay)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGermanFederalHolidays(t *testing.T) {
|
|
holidays := germanFederalHolidays(2026)
|
|
|
|
// Should have 11 federal holidays
|
|
if len(holidays) != 11 {
|
|
t.Fatalf("expected 11 federal holidays, got %d", len(holidays))
|
|
}
|
|
|
|
// Check Neujahr
|
|
if holidays[0].Name != "Neujahr" {
|
|
t.Errorf("first holiday should be Neujahr, got %s", holidays[0].Name)
|
|
}
|
|
if holidays[0].Date != time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) {
|
|
t.Errorf("Neujahr should be Jan 1, got %s", holidays[0].Date)
|
|
}
|
|
|
|
// Check Karfreitag 2026 (Easter = Apr 5, so Good Friday = Apr 3)
|
|
found := false
|
|
for _, h := range holidays {
|
|
if h.Name == "Karfreitag" {
|
|
found = true
|
|
expected := time.Date(2026, 4, 3, 0, 0, 0, 0, time.UTC)
|
|
if h.Date != expected {
|
|
t.Errorf("Karfreitag 2026 should be %s, got %s", expected, h.Date)
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("Karfreitag not found in holidays")
|
|
}
|
|
}
|
|
|
|
func TestHolidayServiceIsNonWorkingDay(t *testing.T) {
|
|
svc := NewHolidayService(nil) // no DB, uses hardcoded holidays
|
|
|
|
// Saturday
|
|
sat := time.Date(2026, 3, 28, 0, 0, 0, 0, time.UTC)
|
|
if !svc.IsNonWorkingDay(sat) {
|
|
t.Error("Saturday should be non-working day")
|
|
}
|
|
|
|
// Sunday
|
|
sun := time.Date(2026, 3, 29, 0, 0, 0, 0, time.UTC)
|
|
if !svc.IsNonWorkingDay(sun) {
|
|
t.Error("Sunday should be non-working day")
|
|
}
|
|
|
|
// Regular Monday
|
|
mon := time.Date(2026, 3, 23, 0, 0, 0, 0, time.UTC)
|
|
if svc.IsNonWorkingDay(mon) {
|
|
t.Error("regular Monday should be a working day")
|
|
}
|
|
|
|
// Christmas (Friday Dec 25, 2026)
|
|
xmas := time.Date(2026, 12, 25, 0, 0, 0, 0, time.UTC)
|
|
if !svc.IsNonWorkingDay(xmas) {
|
|
t.Error("Christmas should be non-working day")
|
|
}
|
|
|
|
// New Year
|
|
newyear := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
if !svc.IsNonWorkingDay(newyear) {
|
|
t.Error("New Year should be non-working day")
|
|
}
|
|
}
|
|
|
|
func TestAdjustForNonWorkingDays(t *testing.T) {
|
|
svc := NewHolidayService(nil)
|
|
|
|
// Saturday -> Monday
|
|
sat := time.Date(2026, 3, 28, 0, 0, 0, 0, time.UTC)
|
|
adj, orig, adjusted := svc.AdjustForNonWorkingDays(sat)
|
|
if !adjusted {
|
|
t.Error("Saturday should be adjusted")
|
|
}
|
|
if orig != sat {
|
|
t.Error("original should be unchanged")
|
|
}
|
|
expected := time.Date(2026, 3, 30, 0, 0, 0, 0, time.UTC)
|
|
if adj != expected {
|
|
t.Errorf("Saturday should adjust to Monday %s, got %s", expected, adj)
|
|
}
|
|
|
|
// Regular Wednesday -> no adjustment
|
|
wed := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC)
|
|
adj, _, adjusted = svc.AdjustForNonWorkingDays(wed)
|
|
if adjusted {
|
|
t.Error("Wednesday should not be adjusted")
|
|
}
|
|
if adj != wed {
|
|
t.Error("non-adjusted date should be unchanged")
|
|
}
|
|
}
|