diff --git a/absences_test.go b/absences_test.go index 5cce5b0..930d8a3 100644 --- a/absences_test.go +++ b/absences_test.go @@ -18,7 +18,7 @@ func TestAddAbsence(t *testing.T) { store, err := NewStore(db, zerolog.Nop()) require.NoError(t, err) - now := NextWednesday() + now := NextWednesday(nil) assert.NoError(t, store.AddAbsence(context.TODO(), now, "foobarbaz")) absentees, err := store.GetAbsentees(context.TODO(), now) assert.NoError(t, err) @@ -40,7 +40,7 @@ func TestGetSchedule(t *testing.T) { store, err := NewStore(db, zerolog.Nop()) require.NoError(t, err) - now := NextWednesday() + now := NextWednesday(nil) _ = store.AddAbsence(context.TODO(), now.Add(7*24*time.Hour), "foobar") diff --git a/cmd/themis-server/main.go b/cmd/themis-server/main.go index ecd28dc..679ed39 100644 --- a/cmd/themis-server/main.go +++ b/cmd/themis-server/main.go @@ -581,7 +581,7 @@ func main() { }, "schedule": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error { // get schedule from now to 4 wednesdays into the future - sched, err := store.GetSchedule(ctx, themis.NextWednesday(), themis.NextWednesday().Add(4*7*24*time.Hour)) + sched, err := store.GetSchedule(ctx, themis.NextWednesday(nil), themis.NextWednesday(nil).Add(4*7*24*time.Hour)) if err != nil { if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, @@ -643,7 +643,7 @@ func main() { "absent": func(ctx context.Context, s *discordgo.Session, i *discordgo.InteractionCreate) error { var rawDate string if len(i.ApplicationCommandData().Options) == 0 { - rawDate = themis.NextWednesday().Format(time.DateOnly) + rawDate = themis.NextWednesday(nil).Format(time.DateOnly) } else { rawDate = i.ApplicationCommandData().Options[0].StringValue() } @@ -739,7 +739,7 @@ func main() { defer span.End() log.Info().Msg("sending weekly reminder") - absentees, err := store.GetAbsentees(ctx, themis.NextWednesday()) + absentees, err := store.GetAbsentees(ctx, themis.NextWednesday(nil)) if err != nil { log.Error().Err(err).Msg("failed to get absentees for next session") return @@ -884,7 +884,7 @@ func registerHandlers(sess *discordgo.Session, handlers map[string]Handler) { userId := i.Member.User.ID log.Info().Ctx(ctx).Str("message_component", "schedule-response").Str("userid", userId).Msg("handling message component interaction") - if err := store.AddAbsence(ctx, themis.NextWednesday(), userId); err != nil { + if err := store.AddAbsence(ctx, themis.NextWednesday(nil), userId); err != nil { if err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ diff --git a/notify.go b/notify.go index 5fe3e4e..3494dea 100644 --- a/notify.go +++ b/notify.go @@ -26,7 +26,7 @@ func NewNotifier(c chan context.Context) *Notifier { } func (n *Notifier) Start(ctx context.Context) { - m := NextWednesday() + m := NextWednesday(nil) sat := m.AddDate(0, 0, -4) if sat.Before(time.Now()) { sat = sat.AddDate(0, 0, 7) diff --git a/time.go b/time.go index 5aa5a27..30d4547 100644 --- a/time.go +++ b/time.go @@ -2,12 +2,22 @@ package themis import "time" -var now func() time.Time +var defaultClock Clock = DefaultClock{} -func init() { - now = time.Now +type Clock interface { + Now() time.Time } -func NextWednesday() time.Time { - return now().AddDate(0, 0, int((10-now().Weekday())%7)) +type DefaultClock struct{} + +func (DefaultClock) Now() time.Time { + return time.Now() +} + +func NextWednesday(clock Clock) time.Time { + if clock == nil { + clock = defaultClock + } + now := clock.Now() + return now.AddDate(0, 0, int((10-now.Weekday())%7)) } diff --git a/time_test.go b/time_test.go index 6a16926..9d13147 100644 --- a/time_test.go +++ b/time_test.go @@ -4,8 +4,18 @@ import ( "reflect" "testing" "time" + + "github.com/stretchr/testify/require" ) +type TestClock struct { + now time.Time +} + +func (c TestClock) Now() time.Time { + return c.now +} + func TestNextWednesday(t *testing.T) { tests := []struct { name string @@ -14,31 +24,35 @@ func TestNextWednesday(t *testing.T) { }{ { name: "on wednesday", - seed: "2023-11-13T15:04:05Z07:00", - want: "2023-11-13T15:04:05Z07:00", + seed: "2023-11-15T15:04:05Z", + want: "2023-11-15T15:04:05Z", }, { name: "on sunday", - seed: "2023-11-12T15:04:05Z07:00", - want: "2023-11-13T15:04:05Z07:00", + seed: "2023-11-12T15:04:05Z", + want: "2023-11-15T15:04:05Z", }, { - name: "on tuesday", - seed: "2023-11-14T15:04:05Z07:00", - want: "2023-11-20T15:04:05Z07:00", + name: "on thursday", + seed: "2023-11-16T15:04:05Z", + want: "2023-11-22T15:04:05Z", }, { name: "on saturday", - seed: "2023-11-18T15:04:05Z07:00", - want: "2023-11-20T15:04:05Z07:00", + seed: "2023-11-18T15:04:05Z", + want: "2023-11-22T15:04:05Z", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - seedt, _ := time.Parse(time.RFC3339, tt.seed) - now = func() time.Time { return seedt } - wantt, _ := time.Parse(time.RFC3339, tt.want) - if got := NextWednesday(); !reflect.DeepEqual(got, wantt) { + seedt, err := time.Parse(time.RFC3339, tt.seed) + require.NoError(t, err) + + wantt, err := time.Parse(time.RFC3339, tt.want) + require.NoError(t, err) + + testClock := TestClock{now: seedt} + if got := NextWednesday(testClock); !reflect.DeepEqual(got, wantt) { t.Errorf("NextWednesday() = %v, want %v", got, wantt) } })