212 lines
5.1 KiB
Go
212 lines
5.1 KiB
Go
package domain
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestNewDefaultPreferences(t *testing.T) {
|
|
p := NewDefaultPreferences("user-123")
|
|
|
|
if p.UserID != "user-123" {
|
|
t.Errorf("expected UserID 'user-123', got '%s'", p.UserID)
|
|
}
|
|
if p.Theme != "system" {
|
|
t.Errorf("expected theme 'system', got '%s'", p.Theme)
|
|
}
|
|
if p.Language != "en" {
|
|
t.Errorf("expected language 'en', got '%s'", p.Language)
|
|
}
|
|
if !p.Notifications.Email {
|
|
t.Error("expected email=true")
|
|
}
|
|
if !p.Notifications.Push {
|
|
t.Error("expected push=true")
|
|
}
|
|
if p.Notifications.Digest != "weekly" {
|
|
t.Errorf("expected digest 'weekly', got '%s'", p.Notifications.Digest)
|
|
}
|
|
if p.UpdatedAt.IsZero() {
|
|
t.Error("expected non-zero UpdatedAt")
|
|
}
|
|
}
|
|
|
|
func TestPreferences_Validate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
modify func(p *Preferences)
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "valid defaults",
|
|
modify: func(p *Preferences) {},
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "valid light theme",
|
|
modify: func(p *Preferences) { p.Theme = "light" },
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "valid dark theme",
|
|
modify: func(p *Preferences) { p.Theme = "dark" },
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "invalid theme",
|
|
modify: func(p *Preferences) { p.Theme = "blue" },
|
|
wantErr: ErrInvalidTheme,
|
|
},
|
|
{
|
|
name: "empty theme",
|
|
modify: func(p *Preferences) { p.Theme = "" },
|
|
wantErr: ErrInvalidTheme,
|
|
},
|
|
{
|
|
name: "valid language es",
|
|
modify: func(p *Preferences) { p.Language = "es" },
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "invalid language - too long",
|
|
modify: func(p *Preferences) { p.Language = "eng" },
|
|
wantErr: ErrInvalidLanguage,
|
|
},
|
|
{
|
|
name: "invalid language - uppercase",
|
|
modify: func(p *Preferences) { p.Language = "EN" },
|
|
wantErr: ErrInvalidLanguage,
|
|
},
|
|
{
|
|
name: "invalid language - empty",
|
|
modify: func(p *Preferences) { p.Language = "" },
|
|
wantErr: ErrInvalidLanguage,
|
|
},
|
|
{
|
|
name: "valid digest daily",
|
|
modify: func(p *Preferences) { p.Notifications.Digest = "daily" },
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "valid digest never",
|
|
modify: func(p *Preferences) { p.Notifications.Digest = "never" },
|
|
wantErr: nil,
|
|
},
|
|
{
|
|
name: "invalid digest",
|
|
modify: func(p *Preferences) { p.Notifications.Digest = "monthly" },
|
|
wantErr: ErrInvalidDigest,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
tt.modify(p)
|
|
err := p.Validate()
|
|
if err != tt.wantErr {
|
|
t.Errorf("expected error %v, got %v", tt.wantErr, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPreferences_MergeFrom(t *testing.T) {
|
|
strPtr := func(s string) *string { return &s }
|
|
boolPtr := func(b bool) *bool { return &b }
|
|
|
|
t.Run("nil update does nothing", func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
p.MergeFrom(nil)
|
|
if p.Theme != "system" {
|
|
t.Errorf("expected theme 'system', got '%s'", p.Theme)
|
|
}
|
|
})
|
|
|
|
t.Run("partial update - theme only", func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
p.MergeFrom(&PreferencesUpdate{
|
|
Theme: strPtr("dark"),
|
|
})
|
|
if p.Theme != "dark" {
|
|
t.Errorf("expected theme 'dark', got '%s'", p.Theme)
|
|
}
|
|
if p.Language != "en" {
|
|
t.Errorf("expected language 'en' unchanged, got '%s'", p.Language)
|
|
}
|
|
})
|
|
|
|
t.Run("partial update - language only", func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
p.MergeFrom(&PreferencesUpdate{
|
|
Language: strPtr("fr"),
|
|
})
|
|
if p.Language != "fr" {
|
|
t.Errorf("expected language 'fr', got '%s'", p.Language)
|
|
}
|
|
if p.Theme != "system" {
|
|
t.Errorf("expected theme 'system' unchanged, got '%s'", p.Theme)
|
|
}
|
|
})
|
|
|
|
t.Run("notifications sub-field merge", func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
p.MergeFrom(&PreferencesUpdate{
|
|
Notifications: &NotificationSettingsUpdate{
|
|
Email: boolPtr(false),
|
|
},
|
|
})
|
|
if p.Notifications.Email != false {
|
|
t.Error("expected email=false")
|
|
}
|
|
if p.Notifications.Push != true {
|
|
t.Error("expected push=true unchanged")
|
|
}
|
|
if p.Notifications.Digest != "weekly" {
|
|
t.Errorf("expected digest 'weekly' unchanged, got '%s'", p.Notifications.Digest)
|
|
}
|
|
})
|
|
|
|
t.Run("full update", func(t *testing.T) {
|
|
p := NewDefaultPreferences("user-1")
|
|
p.MergeFrom(&PreferencesUpdate{
|
|
Theme: strPtr("light"),
|
|
Language: strPtr("es"),
|
|
Notifications: &NotificationSettingsUpdate{
|
|
Email: boolPtr(false),
|
|
Push: boolPtr(false),
|
|
Digest: strPtr("daily"),
|
|
},
|
|
})
|
|
if p.Theme != "light" {
|
|
t.Errorf("expected theme 'light', got '%s'", p.Theme)
|
|
}
|
|
if p.Language != "es" {
|
|
t.Errorf("expected language 'es', got '%s'", p.Language)
|
|
}
|
|
if p.Notifications.Email != false {
|
|
t.Error("expected email=false")
|
|
}
|
|
if p.Notifications.Push != false {
|
|
t.Error("expected push=false")
|
|
}
|
|
if p.Notifications.Digest != "daily" {
|
|
t.Errorf("expected digest 'daily', got '%s'", p.Notifications.Digest)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestUserID(t *testing.T) {
|
|
id := UserID("test-123")
|
|
if id.String() != "test-123" {
|
|
t.Errorf("expected 'test-123', got '%s'", id.String())
|
|
}
|
|
if id.IsZero() {
|
|
t.Error("expected non-zero")
|
|
}
|
|
|
|
var empty UserID
|
|
if !empty.IsZero() {
|
|
t.Error("expected zero")
|
|
}
|
|
}
|