test: expect proper midweek handling
This commit is contained in:
@@ -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.
|
// Mon–Wed 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user