test: expect proper midweek handling

This commit is contained in:
2026-05-13 20:44:14 +00:00
parent ca5f5f95e2
commit c617012401

View File

@@ -12,7 +12,7 @@ import (
"github.com/wotra/wotra/internal/store" "github.com/wotra/wotra/internal/store"
) )
// weekTestAnchor is a fixed Tuesday (2026-W20) used as "now" across week service tests. // weekTestAnchor is a fixed Wednesday (2026-W20) used as "now" across week service tests.
var weekTestAnchor = time.Date(2026, 5, 13, 10, 0, 0, 0, time.UTC) var weekTestAnchor = time.Date(2026, 5, 13, 10, 0, 0, 0, time.UTC)
func newFullServices(t *testing.T) (*service.EntryService, *service.DayService, *service.WeekService, *service.SettingsService, *clock.FixedClock) { func newFullServices(t *testing.T) (*service.EntryService, *service.DayService, *service.WeekService, *service.SettingsService, *clock.FixedClock) {
@@ -166,31 +166,88 @@ func TestReopenWeek(t *testing.T) {
} }
func TestCloseWeekMidWeek(t *testing.T) { func TestCloseWeekMidWeek(t *testing.T) {
// weekTestAnchor = 2026-05-13 (Tuesday, 2026-W20). // weekTestAnchor = 2026-05-13 (Wednesday, 2026-W20).
// Mon 2026-05-11 and Tue 2026-05-13 are past workdays; Wed-Fri are future. // MonWed are tracked with real intervals and closed. Thu is pre-marked as
// holiday, Fri as vacation. CloseWeek is called mid-week: the service skips
// future workdays (Thu, Fri), so only Mon+Tue+Wed intervals count.
ctx := context.Background() ctx := context.Background()
_, daySvc, weekSvc, _, clk := newFullServices(t) entrySvc, daySvc, weekSvc, _, _ := newFullServices(t)
tz, _ := time.LoadLocation("UTC") const weekKey = "2026-W20"
now := clk.Now().In(tz) mon := time.Date(2026, 5, 11, 0, 0, 0, 0, time.UTC)
isoYear, isoWeek := now.ISOWeek() tue := time.Date(2026, 5, 12, 0, 0, 0, 0, time.UTC)
weekKey := fmt.Sprintf("%d-W%02d", isoYear, isoWeek) wed := time.Date(2026, 5, 13, 0, 0, 0, 0, time.UTC)
thu := time.Date(2026, 5, 14, 0, 0, 0, 0, time.UTC)
fri := time.Date(2026, 5, 15, 0, 0, 0, 0, time.UTC)
monday := now.AddDate(0, 0, -int(now.Weekday()-time.Monday)) // at returns the unix-ms for a given day at hh:mm UTC.
today := now.Format("2006-01-02") at := func(base time.Time, h, m int) int64 {
for d := monday; d.Format("2006-01-02") <= today; d = d.AddDate(0, 0, 1) { return time.Date(base.Year(), base.Month(), base.Day(), h, m, 0, 0, time.UTC).UnixMilli()
wd := d.Weekday()
if wd == time.Saturday || wd == time.Sunday {
continue
}
dk := d.Format("2006-01-02")
if _, err := daySvc.MarkDay(ctx, dk, domain.DayKindHoliday); err != nil {
t.Fatalf("MarkDay %s: %v", dk, err)
}
} }
if _, err := weekSvc.CloseWeek(ctx, weekKey); err != nil { // Monday: 3 spans — 1.5h + 1h + 2h = 4.5h
t.Fatalf("CloseWeek mid-week: %v", err) for _, s := range [][2][2]int{{{9, 0}, {10, 30}}, {{11, 0}, {12, 0}}, {{13, 0}, {15, 0}}} {
if _, err := entrySvc.CreateInterval(ctx, service.CreateIntervalInput{
StartTime: at(mon, s[0][0], s[0][1]),
EndTime: at(mon, s[1][0], s[1][1]),
}); err != nil {
t.Fatalf("CreateInterval mon: %v", err)
}
}
if _, err := daySvc.CloseDay(ctx, mon.Format("2006-01-02")); err != nil {
t.Fatalf("CloseDay mon: %v", err)
}
// Tuesday: 1 span — 4h
if _, err := entrySvc.CreateInterval(ctx, service.CreateIntervalInput{
StartTime: at(tue, 9, 0),
EndTime: at(tue, 13, 0),
}); err != nil {
t.Fatalf("CreateInterval tue: %v", err)
}
if _, err := daySvc.CloseDay(ctx, tue.Format("2006-01-02")); err != nil {
t.Fatalf("CloseDay tue: %v", err)
}
// Wednesday: 2 spans — 2h + 2h = 4h
for _, s := range [][2][2]int{{{9, 0}, {11, 0}}, {{14, 0}, {16, 0}}} {
if _, err := entrySvc.CreateInterval(ctx, service.CreateIntervalInput{
StartTime: at(wed, s[0][0], s[0][1]),
EndTime: at(wed, s[1][0], s[1][1]),
}); err != nil {
t.Fatalf("CreateInterval wed: %v", err)
}
}
if _, err := daySvc.CloseDay(ctx, wed.Format("2006-01-02")); err != nil {
t.Fatalf("CloseDay wed: %v", err)
}
// Thursday and Friday are future — mark them ahead of time, so we can
// finish early.
if _, err := daySvc.MarkDay(ctx, thu.Format("2006-01-02"), domain.DayKindHoliday); err != nil {
t.Fatalf("MarkDay thu: %v", err)
}
if _, err := daySvc.MarkDay(ctx, fri.Format("2006-01-02"), domain.DayKindVacation); err != nil {
t.Fatalf("MarkDay fri: %v", err)
}
cw, err := weekSvc.CloseWeek(ctx, weekKey)
if err != nil {
t.Fatalf("CloseWeek: %v", err)
}
// Only Mon+Tue+Wed contribute: 4.5h + 4h + 4h + 8h + 8h = 28.5h
const wantWorked = 28*time.Hour + 30*time.Minute
if cw.WorkedMs != int64(wantWorked/time.Millisecond) {
t.Errorf("worked hours: want %s, got %s", wantWorked, time.Duration(cw.WorkedMs)*time.Millisecond)
}
const wantExpected = 40*time.Hour
if cw.ExpectedMs != int64(wantExpected/time.Millisecond) {
t.Errorf("expected_ms: want %s, got %s", wantExpected, time.Duration(cw.ExpectedMs)*time.Millisecond)
}
const wantDelta = wantWorked - wantExpected // 11.5h
if cw.DeltaMs != int64(wantDelta) {
t.Errorf("delta_ms: want %s, got %s", wantDelta, time.Duration(cw.DeltaMs)*time.Millisecond)
} }
} }