182 lines
5.2 KiB
Go
182 lines
5.2 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
|
|
"git.threesix.ai/jordan/slack5-1770541397/pkg/logging"
|
|
"git.threesix.ai/jordan/slack5-1770541397/services/preferences-api/internal/domain"
|
|
"git.threesix.ai/jordan/slack5-1770541397/services/preferences-api/internal/port"
|
|
)
|
|
|
|
// mockPreferencesRepository implements port.PreferencesRepository for testing.
|
|
type mockPreferencesRepository struct {
|
|
mu sync.RWMutex
|
|
store map[domain.UserID]*domain.UserPreferences
|
|
}
|
|
|
|
var _ port.PreferencesRepository = (*mockPreferencesRepository)(nil)
|
|
|
|
func newMockPreferencesRepository() *mockPreferencesRepository {
|
|
return &mockPreferencesRepository{
|
|
store: make(map[domain.UserID]*domain.UserPreferences),
|
|
}
|
|
}
|
|
|
|
func (m *mockPreferencesRepository) Get(ctx context.Context, userID domain.UserID) (*domain.UserPreferences, error) {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
prefs, ok := m.store[userID]
|
|
if !ok {
|
|
return nil, domain.ErrPreferencesNotFound
|
|
}
|
|
copy := *prefs
|
|
return ©, nil
|
|
}
|
|
|
|
func (m *mockPreferencesRepository) Upsert(ctx context.Context, prefs *domain.UserPreferences) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
copy := *prefs
|
|
m.store[prefs.UserID] = ©
|
|
return nil
|
|
}
|
|
|
|
func TestPreferencesService_GetPreferences(t *testing.T) {
|
|
repo := newMockPreferencesRepository()
|
|
svc := NewPreferencesService(repo, logging.Nop())
|
|
|
|
t.Run("returns defaults when no preferences exist", func(t *testing.T) {
|
|
prefs, err := svc.GetPreferences(context.Background(), "user-123")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.UserID != "user-123" {
|
|
t.Errorf("expected user_id 'user-123', got '%s'", prefs.UserID)
|
|
}
|
|
if prefs.Preferences.Theme != "system" {
|
|
t.Errorf("expected default theme 'system', got '%s'", prefs.Preferences.Theme)
|
|
}
|
|
if prefs.Preferences.Language != "en" {
|
|
t.Errorf("expected default language 'en', got '%s'", prefs.Preferences.Language)
|
|
}
|
|
if !prefs.Preferences.Notifications.Email {
|
|
t.Error("expected default notifications.email to be true")
|
|
}
|
|
if !prefs.Preferences.Notifications.Push {
|
|
t.Error("expected default notifications.push to be true")
|
|
}
|
|
if prefs.Preferences.Notifications.SMS {
|
|
t.Error("expected default notifications.sms to be false")
|
|
}
|
|
})
|
|
|
|
t.Run("returns stored preferences", func(t *testing.T) {
|
|
// Store preferences first
|
|
_, err := svc.SetPreferences(context.Background(), "user-456", domain.Preferences{
|
|
Theme: "dark",
|
|
Language: "fr",
|
|
Notifications: domain.NotificationPreferences{
|
|
Email: false,
|
|
Push: true,
|
|
SMS: true,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error setting preferences: %v", err)
|
|
}
|
|
|
|
prefs, err := svc.GetPreferences(context.Background(), "user-456")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.Preferences.Theme != "dark" {
|
|
t.Errorf("expected theme 'dark', got '%s'", prefs.Preferences.Theme)
|
|
}
|
|
if prefs.Preferences.Language != "fr" {
|
|
t.Errorf("expected language 'fr', got '%s'", prefs.Preferences.Language)
|
|
}
|
|
if prefs.Preferences.Notifications.Email {
|
|
t.Error("expected notifications.email to be false")
|
|
}
|
|
if prefs.Preferences.Notifications.SMS != true {
|
|
t.Error("expected notifications.sms to be true")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestPreferencesService_SetPreferences(t *testing.T) {
|
|
repo := newMockPreferencesRepository()
|
|
svc := NewPreferencesService(repo, logging.Nop())
|
|
|
|
t.Run("sets valid preferences", func(t *testing.T) {
|
|
prefs, err := svc.SetPreferences(context.Background(), "user-789", domain.Preferences{
|
|
Theme: "light",
|
|
Language: "en",
|
|
Notifications: domain.NotificationPreferences{
|
|
Email: true,
|
|
Push: false,
|
|
SMS: false,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.UserID != "user-789" {
|
|
t.Errorf("expected user_id 'user-789', got '%s'", prefs.UserID)
|
|
}
|
|
if prefs.Preferences.Theme != "light" {
|
|
t.Errorf("expected theme 'light', got '%s'", prefs.Preferences.Theme)
|
|
}
|
|
if prefs.UpdatedAt.IsZero() {
|
|
t.Error("expected non-zero updated_at")
|
|
}
|
|
})
|
|
|
|
t.Run("rejects invalid theme", func(t *testing.T) {
|
|
_, err := svc.SetPreferences(context.Background(), "user-789", domain.Preferences{
|
|
Theme: "neon",
|
|
Language: "en",
|
|
})
|
|
if err != domain.ErrInvalidTheme {
|
|
t.Errorf("expected ErrInvalidTheme, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects language exceeding max length", func(t *testing.T) {
|
|
_, err := svc.SetPreferences(context.Background(), "user-789", domain.Preferences{
|
|
Theme: "dark",
|
|
Language: "abcdefghijk", // 11 chars
|
|
})
|
|
if err != domain.ErrInvalidLanguage {
|
|
t.Errorf("expected ErrInvalidLanguage, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("allows empty theme", func(t *testing.T) {
|
|
prefs, err := svc.SetPreferences(context.Background(), "user-000", domain.Preferences{
|
|
Theme: "",
|
|
Language: "en",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if prefs.Preferences.Theme != "" {
|
|
t.Errorf("expected empty theme, got '%s'", prefs.Preferences.Theme)
|
|
}
|
|
})
|
|
|
|
t.Run("allows max length language", func(t *testing.T) {
|
|
_, err := svc.SetPreferences(context.Background(), "user-000", domain.Preferences{
|
|
Theme: "dark",
|
|
Language: "abcdefghij", // exactly 10 chars
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|