test: add comprehensive tests for new UX features and fix ISO date timezone bug

Add 33 new test functions covering annotations, undo system, history
formatting, relative date display, and weekday parsing pipeline. Fix ISO
date parsing to use ParseInLocation instead of Parse to respect the
parser's timezone context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 16:42:49 +01:00
parent 07d1a78dfc
commit 04fa9222d8
6 changed files with 1117 additions and 1 deletions
+121
View File
@@ -226,6 +226,127 @@ func TestParseDateWithTime(t *testing.T) {
}
}
func TestSplitDateTime(t *testing.T) {
base := time.Date(2026, 1, 5, 12, 0, 0, 0, time.UTC)
parser := NewDateParser(base, time.Monday)
tests := []struct {
name string
input string
wantDate string
wantTime string
wantHas bool
}{
{"plain weekday", "mon", "mon", "", false},
{"plain date", "2026-01-15", "2026-01-15", "", false},
{"weekday+HHMM", "mon:0800", "mon", "0800", true},
{"weekday+HH:MM", "mon:15:35", "mon", "15:35", true},
{"date+HHMM", "21jan:1430", "21jan", "1430", true},
{"just time HH:MM", "15:35", "", "15:35", true},
{"tomorrow+time", "tomorrow:0800", "tomorrow", "0800", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dateStr, timeStr, hasTime := parser.splitDateTime(tt.input)
if hasTime != tt.wantHas {
t.Errorf("hasTime = %v, want %v", hasTime, tt.wantHas)
}
if hasTime {
if dateStr != tt.wantDate {
t.Errorf("dateStr = %q, want %q", dateStr, tt.wantDate)
}
if timeStr != tt.wantTime {
t.Errorf("timeStr = %q, want %q", timeStr, tt.wantTime)
}
}
})
}
}
func TestParseISODate(t *testing.T) {
// Use a non-UTC timezone to verify ISO dates respect the parser's location
loc := time.FixedZone("UTC+10", 10*60*60)
base := time.Date(2026, 1, 5, 12, 0, 0, 0, loc)
parser := NewDateParser(base, time.Monday)
result, err := parser.ParseDate("2026-02-20")
if err != nil {
t.Fatalf("Failed to parse ISO date: %v", err)
}
expected := time.Date(2026, 2, 20, 0, 0, 0, 0, loc)
if !result.Equal(expected) {
t.Errorf("Expected %v, got %v", expected, result)
}
if result.Location() != loc {
t.Errorf("Expected location %v, got %v", loc, result.Location())
}
}
func TestParseDateInvalid(t *testing.T) {
base := time.Date(2026, 1, 5, 12, 0, 0, 0, time.UTC)
parser := NewDateParser(base, time.Monday)
invalids := []string{
"notadate",
"xyz123",
"",
"32jan",
"feb30",
}
for _, input := range invalids {
t.Run(input, func(t *testing.T) {
_, err := parser.ParseDate(input)
if err == nil && input != "" {
// Some of these might parse as durations or keywords
// but truly invalid ones should error
t.Logf("ParseDate(%q) did not error (may be valid as keyword/duration)", input)
}
})
}
}
func TestNextWeekday_Exhaustive(t *testing.T) {
// Test all 7 starting days × 7 target days
// Mon Jan 5 2026
monday := time.Date(2026, 1, 5, 12, 0, 0, 0, time.UTC)
allDays := []time.Weekday{
time.Sunday, time.Monday, time.Tuesday, time.Wednesday,
time.Thursday, time.Friday, time.Saturday,
}
for fromOffset := 0; fromOffset < 7; fromOffset++ {
from := monday.AddDate(0, 0, fromOffset)
parser := NewDateParser(from, time.Monday)
for _, target := range allDays {
t.Run(from.Weekday().String()+"_to_"+target.String(), func(t *testing.T) {
result := parser.nextWeekday(target)
// Must land on the correct weekday
if result.Weekday() != target {
t.Errorf("weekday = %v, want %v", result.Weekday(), target)
}
// Must be 1-7 days in the future
fromMidnight := time.Date(from.Year(), from.Month(), from.Day(), 0, 0, 0, 0, from.Location())
days := int(result.Sub(fromMidnight).Hours() / 24)
if days < 1 || days > 7 {
t.Errorf("days ahead = %d, want 1-7 (from %v to %v)", days, from, result)
}
// Same weekday should always be 7 days ahead
if from.Weekday() == target && days != 7 {
t.Errorf("same weekday should be 7 days, got %d", days)
}
})
}
}
}
func TestExpandedDurationFormats(t *testing.T) {
tests := []struct {
name string