Correct daypart identity and display handling
This commit is contained in:
@@ -82,6 +82,40 @@ func TestDefaults(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaypartNamesMustHaveDistinctCanonicalIdentities(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
names []string
|
||||
wantErr string
|
||||
}{
|
||||
{name: "exact duplicate", names: []string{"morning", "morning"}, wantErr: "conflicts with"},
|
||||
{name: "case-only duplicate", names: []string{"morning", "MORNING"}, wantErr: "conflicts with"},
|
||||
{name: "punctuation-normalized duplicate", names: []string{"morning", "morning!"}, wantErr: "conflicts with"},
|
||||
{name: "distinct Unicode names", names: []string{"mañana", "manana"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := Defaults()
|
||||
cfg.Dayparts = make([]DaypartConfig, 0, len(tt.names))
|
||||
for _, name := range tt.names {
|
||||
cfg.Dayparts = append(cfg.Dayparts, DaypartConfig{Name: name, Start: "06:00", End: "12:00"})
|
||||
}
|
||||
|
||||
err := Validate(cfg)
|
||||
if tt.wantErr == "" {
|
||||
if err != nil {
|
||||
t.Fatalf("Validate() error = %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Fatalf("Validate() error = %v, want %q", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeatherAPIBaseURLValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
||||
)
|
||||
|
||||
@@ -74,10 +75,16 @@ func Validate(cfg Config) error {
|
||||
if len(cfg.Dayparts) == 0 {
|
||||
return fmt.Errorf("dayparts must contain at least one entry")
|
||||
}
|
||||
daypartNames := make(map[string]int, len(cfg.Dayparts))
|
||||
for i, daypart := range cfg.Dayparts {
|
||||
if strings.TrimSpace(daypart.Name) == "" {
|
||||
return fmt.Errorf("dayparts[%d].name is required", i)
|
||||
}
|
||||
key := forecast.CanonicalDaypartKey(daypart.Name)
|
||||
if previous, exists := daypartNames[key]; exists {
|
||||
return fmt.Errorf("dayparts[%d].name %q conflicts with dayparts[%d].name after canonicalization", i, daypart.Name, previous)
|
||||
}
|
||||
daypartNames[key] = i
|
||||
if _, err := timeutil.ParseClock(daypart.Start); err != nil {
|
||||
return fmt.Errorf("dayparts[%d].start is invalid: %w", i, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user