1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
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)
}
})
}
}
|