package models import ( "testing" "time" ) func TestComputeNextOccurrence(t *testing.T) { mustParse := func(t *testing.T, s string) time.Time { t.Helper() d, err := time.Parse("2006-01-02", s) if err != nil { t.Fatalf("bad fixture date %q: %v", s, err) } return d } tests := []struct { name string due string freq string interval int weekdays []int want string }{ {"daily interval 1", "2026-07-13", "daily", 1, nil, "2026-07-14"}, {"daily interval 3", "2026-07-13", "daily", 3, nil, "2026-07-16"}, {"weekly no weekdays interval 1", "2026-07-13", "weekly", 1, nil, "2026-07-20"}, {"weekly no weekdays interval 2", "2026-07-13", "weekly", 2, nil, "2026-07-27"}, // 2026-07-13 is a Monday (weekday=1). {"weekly with weekdays same week", "2026-07-13", "weekly", 1, []int{1, 3, 5}, "2026-07-15"}, {"weekly with weekdays wraps to next week", "2026-07-17", "weekly", 1, []int{1, 3, 5}, "2026-07-20"}, // due=Fri(5), wraps to Mon {"weekly with weekdays interval 2 wraps", "2026-07-13", "weekly", 2, []int{1}, "2026-07-27"}, // due=Mon, only Mon active, skip a week {"monthly interval 1", "2026-06-13", "monthly", 1, nil, "2026-07-13"}, {"monthly rollover", "2026-01-31", "monthly", 1, nil, "2026-03-03"}, {"monthly rollover locks in on the drifted day", "2026-03-03", "monthly", 1, nil, "2026-04-03"}, {"yearly interval 1", "2026-07-13", "yearly", 1, nil, "2027-07-13"}, {"unknown freq returns due unchanged", "2026-07-13", "bogus", 1, nil, "2026-07-13"}, {"interval below 1 is treated as 1", "2026-07-13", "daily", 0, nil, "2026-07-14"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got := ComputeNextOccurrence(mustParse(t, tc.due), tc.freq, tc.interval, tc.weekdays) want := mustParse(t, tc.want) if !got.Equal(want) { t.Errorf("ComputeNextOccurrence(%s, %s, %d, %v) = %s, want %s", tc.due, tc.freq, tc.interval, tc.weekdays, got.Format("2006-01-02"), tc.want) } }) } }