154 lines
4.3 KiB
Go
154 lines
4.3 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.threesix.ai/jordan/slate-v3-1770514618/pkg/logging"
|
|
"git.threesix.ai/jordan/slate-v3-1770514618/services/preferences-api/internal/adapter/memory"
|
|
"git.threesix.ai/jordan/slate-v3-1770514618/services/preferences-api/internal/domain"
|
|
)
|
|
|
|
func strPtr(s string) *string { return &s }
|
|
func boolPtr(b bool) *bool { return &b }
|
|
|
|
func TestPreferencesService_Get(t *testing.T) {
|
|
repo := memory.NewPreferencesRepository()
|
|
svc := NewPreferencesService(repo, logging.Nop())
|
|
ctx := context.Background()
|
|
|
|
t.Run("returns not found when no preferences exist", func(t *testing.T) {
|
|
_, err := svc.Get(ctx, "user-1")
|
|
if err != domain.ErrPreferencesNotFound {
|
|
t.Errorf("expected ErrPreferencesNotFound, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("returns preferences after upsert", func(t *testing.T) {
|
|
_, _ = svc.Upsert(ctx, "user-1", &domain.PreferencesUpdate{
|
|
Theme: strPtr("dark"),
|
|
})
|
|
prefs, err := svc.Get(ctx, "user-1")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.Theme != "dark" {
|
|
t.Errorf("expected theme 'dark', got '%s'", prefs.Theme)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestPreferencesService_Upsert(t *testing.T) {
|
|
repo := memory.NewPreferencesRepository()
|
|
svc := NewPreferencesService(repo, logging.Nop())
|
|
ctx := context.Background()
|
|
|
|
t.Run("creates new with defaults and merges", func(t *testing.T) {
|
|
prefs, err := svc.Upsert(ctx, "user-new", &domain.PreferencesUpdate{
|
|
Theme: strPtr("light"),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.Theme != "light" {
|
|
t.Errorf("expected theme 'light', got '%s'", prefs.Theme)
|
|
}
|
|
if prefs.Language != "en" {
|
|
t.Errorf("expected default language 'en', got '%s'", prefs.Language)
|
|
}
|
|
if !prefs.Notifications.Email {
|
|
t.Error("expected default email=true")
|
|
}
|
|
})
|
|
|
|
t.Run("updates existing with merge", func(t *testing.T) {
|
|
// First upsert
|
|
_, _ = svc.Upsert(ctx, "user-merge", &domain.PreferencesUpdate{
|
|
Theme: strPtr("dark"),
|
|
Language: strPtr("fr"),
|
|
})
|
|
|
|
// Second upsert - only change language
|
|
prefs, err := svc.Upsert(ctx, "user-merge", &domain.PreferencesUpdate{
|
|
Language: strPtr("es"),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.Theme != "dark" {
|
|
t.Errorf("expected theme 'dark' unchanged, got '%s'", prefs.Theme)
|
|
}
|
|
if prefs.Language != "es" {
|
|
t.Errorf("expected language 'es', got '%s'", prefs.Language)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects invalid theme", func(t *testing.T) {
|
|
_, err := svc.Upsert(ctx, "user-invalid", &domain.PreferencesUpdate{
|
|
Theme: strPtr("blue"),
|
|
})
|
|
if err != domain.ErrInvalidTheme {
|
|
t.Errorf("expected ErrInvalidTheme, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects invalid language", func(t *testing.T) {
|
|
_, err := svc.Upsert(ctx, "user-invalid2", &domain.PreferencesUpdate{
|
|
Language: strPtr("XYZ"),
|
|
})
|
|
if err != domain.ErrInvalidLanguage {
|
|
t.Errorf("expected ErrInvalidLanguage, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects invalid digest", func(t *testing.T) {
|
|
_, err := svc.Upsert(ctx, "user-invalid3", &domain.PreferencesUpdate{
|
|
Notifications: &domain.NotificationSettingsUpdate{
|
|
Digest: strPtr("monthly"),
|
|
},
|
|
})
|
|
if err != domain.ErrInvalidDigest {
|
|
t.Errorf("expected ErrInvalidDigest, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("sets UpdatedAt", func(t *testing.T) {
|
|
prefs, err := svc.Upsert(ctx, "user-time", &domain.PreferencesUpdate{
|
|
Theme: strPtr("dark"),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.UpdatedAt.IsZero() {
|
|
t.Error("expected non-zero UpdatedAt")
|
|
}
|
|
})
|
|
|
|
t.Run("notification sub-field merge preserves unset fields", func(t *testing.T) {
|
|
_, _ = svc.Upsert(ctx, "user-notif", &domain.PreferencesUpdate{
|
|
Notifications: &domain.NotificationSettingsUpdate{
|
|
Email: boolPtr(false),
|
|
Push: boolPtr(false),
|
|
Digest: strPtr("daily"),
|
|
},
|
|
})
|
|
prefs, err := svc.Upsert(ctx, "user-notif", &domain.PreferencesUpdate{
|
|
Notifications: &domain.NotificationSettingsUpdate{
|
|
Email: boolPtr(true),
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !prefs.Notifications.Email {
|
|
t.Error("expected email=true")
|
|
}
|
|
if prefs.Notifications.Push != false {
|
|
t.Error("expected push=false preserved")
|
|
}
|
|
if prefs.Notifications.Digest != "daily" {
|
|
t.Errorf("expected digest 'daily' preserved, got '%s'", prefs.Notifications.Digest)
|
|
}
|
|
})
|
|
}
|