Skip to content

Commit e72cbed

Browse files
authored
Merge pull request #3 from ashishxcode/test/range-date-coverage
test: cover date-range logic and run go test in CI
2 parents 689836f + 6233053 commit e72cbed

3 files changed

Lines changed: 147 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ jobs:
1616
- run: gofmt -l cmd internal | tee /dev/stderr | (! read)
1717
- run: go vet ./...
1818
- run: go build ./...
19+
- run: go test -race ./...

internal/collect/git_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package collect
2+
3+
import "testing"
4+
5+
func TestAnchorMidnight(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
in string
9+
want string
10+
}{
11+
{"bare ISO date gets midnight", "2026-05-24", "2026-05-24 00:00:00"},
12+
{"month rollover date", "2026-02-01", "2026-02-01 00:00:00"},
13+
{"relative string untouched", "7 days ago", "7 days ago"},
14+
{"yesterday keyword untouched", "yesterday", "yesterday"},
15+
{"empty untouched", "", ""},
16+
{"date with time untouched", "2026-05-24 12:00:00", "2026-05-24 12:00:00"},
17+
}
18+
for _, tt := range tests {
19+
t.Run(tt.name, func(t *testing.T) {
20+
if got := anchorMidnight(tt.in); got != tt.want {
21+
t.Errorf("anchorMidnight(%q) = %q, want %q", tt.in, got, tt.want)
22+
}
23+
})
24+
}
25+
}

internal/model/range_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package model
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestFromDates(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
from, to string
12+
wantSince string
13+
wantUntil string
14+
wantLabel string
15+
wantErr bool
16+
}{
17+
{
18+
name: "single day makes until exclusive next day",
19+
from: "2026-05-24", to: "2026-05-24",
20+
wantSince: "2026-05-24", wantUntil: "2026-05-25", wantLabel: "2026-05-24",
21+
},
22+
{
23+
name: "multi-day range",
24+
from: "2026-05-01", to: "2026-05-03",
25+
wantSince: "2026-05-01", wantUntil: "2026-05-04", wantLabel: "2026-05-01 → 2026-05-03",
26+
},
27+
{
28+
name: "until rolls over month boundary",
29+
from: "2026-01-31", to: "2026-01-31",
30+
wantSince: "2026-01-31", wantUntil: "2026-02-01", wantLabel: "2026-01-31",
31+
},
32+
{name: "bad from", from: "nope", to: "2026-05-24", wantErr: true},
33+
{name: "bad to", from: "2026-05-24", to: "nope", wantErr: true},
34+
}
35+
for _, tt := range tests {
36+
t.Run(tt.name, func(t *testing.T) {
37+
r, err := FromDates(tt.from, tt.to)
38+
if tt.wantErr {
39+
if err == nil {
40+
t.Fatalf("expected error, got %+v", r)
41+
}
42+
return
43+
}
44+
if err != nil {
45+
t.Fatalf("unexpected error: %v", err)
46+
}
47+
if r.Since != tt.wantSince || r.Until != tt.wantUntil || r.Label != tt.wantLabel {
48+
t.Errorf("got {Since:%q Until:%q Label:%q}, want {Since:%q Until:%q Label:%q}",
49+
r.Since, r.Until, r.Label, tt.wantSince, tt.wantUntil, tt.wantLabel)
50+
}
51+
})
52+
}
53+
}
54+
55+
func TestFromDatesEmptyToDefaultsToday(t *testing.T) {
56+
r, err := FromDates("2026-05-01", "")
57+
if err != nil {
58+
t.Fatalf("unexpected error: %v", err)
59+
}
60+
wantUntil := time.Now().AddDate(0, 0, 1).Format(isoDate)
61+
if r.Until != wantUntil {
62+
t.Errorf("Until = %q, want %q (today + 1, exclusive)", r.Until, wantUntil)
63+
}
64+
}
65+
66+
func TestFromMonth(t *testing.T) {
67+
r, err := FromMonth("2026-02")
68+
if err != nil {
69+
t.Fatalf("unexpected error: %v", err)
70+
}
71+
if r.Since != "2026-02-01" || r.Until != "2026-03-01" {
72+
t.Errorf("got {Since:%q Until:%q}, want {2026-02-01 2026-03-01}", r.Since, r.Until)
73+
}
74+
if r.Label != "February 2026" {
75+
t.Errorf("Label = %q, want %q", r.Label, "February 2026")
76+
}
77+
if _, err := FromMonth("bad"); err == nil {
78+
t.Error("expected error for bad month")
79+
}
80+
}
81+
82+
// TestPresetBoundaries guards the regression behind the date-skew bug: each
83+
// preset must produce a half-open [Since, Until) window aligned to whole days,
84+
// independent of the current time of day.
85+
func TestPresetBoundaries(t *testing.T) {
86+
now := time.Now()
87+
today := now.Format(isoDate)
88+
yesterday := now.AddDate(0, 0, -1).Format(isoDate)
89+
tomorrow := now.AddDate(0, 0, 1).Format(isoDate)
90+
91+
tests := []struct {
92+
choice string
93+
wantSince string
94+
wantUntil string
95+
}{
96+
{"Today", today, tomorrow},
97+
{"Yesterday", yesterday, today},
98+
{"Last 7 days", now.AddDate(0, 0, -6).Format(isoDate), tomorrow},
99+
{"Last 30 days", now.AddDate(0, 0, -29).Format(isoDate), tomorrow},
100+
}
101+
for _, tt := range tests {
102+
t.Run(tt.choice, func(t *testing.T) {
103+
r := Preset(tt.choice)
104+
if r.Since != tt.wantSince {
105+
t.Errorf("Since = %q, want %q", r.Since, tt.wantSince)
106+
}
107+
if r.Until != tt.wantUntil {
108+
t.Errorf("Until = %q, want %q", r.Until, tt.wantUntil)
109+
}
110+
})
111+
}
112+
}
113+
114+
func TestPresetUnknownFallsBackToWeek(t *testing.T) {
115+
r := Preset("not a preset")
116+
want := Preset("Last 7 days")
117+
if r.Since != want.Since || r.Until != want.Until {
118+
t.Errorf("unknown preset = {%q,%q}, want last-7-days {%q,%q}",
119+
r.Since, r.Until, want.Since, want.Until)
120+
}
121+
}

0 commit comments

Comments
 (0)