Changeset 0.20.0 (#85)
This commit is contained in:
137
server/notifications/service_test.go
Normal file
137
server/notifications/service_test.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package notifications
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
)
|
||||
|
||||
// mockPrefStore implements store.NotificationPreferenceStore for testing.
|
||||
type mockPrefStore struct {
|
||||
prefs map[string]map[string]*models.NotificationPreference // userID → type → pref
|
||||
}
|
||||
|
||||
func newMockPrefStore() *mockPrefStore {
|
||||
return &mockPrefStore{prefs: make(map[string]map[string]*models.NotificationPreference)}
|
||||
}
|
||||
|
||||
func (m *mockPrefStore) Get(_ context.Context, userID, notifType string) (*models.NotificationPreference, error) {
|
||||
if userPrefs, ok := m.prefs[userID]; ok {
|
||||
if p, ok := userPrefs[notifType]; ok {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockPrefStore) ListForUser(_ context.Context, userID string) ([]models.NotificationPreference, error) {
|
||||
var result []models.NotificationPreference
|
||||
if userPrefs, ok := m.prefs[userID]; ok {
|
||||
for _, p := range userPrefs {
|
||||
result = append(result, *p)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m *mockPrefStore) Upsert(_ context.Context, pref *models.NotificationPreference) error {
|
||||
if m.prefs[pref.UserID] == nil {
|
||||
m.prefs[pref.UserID] = make(map[string]*models.NotificationPreference)
|
||||
}
|
||||
m.prefs[pref.UserID][pref.Type] = pref
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockPrefStore) Delete(_ context.Context, userID, notifType string) error {
|
||||
if userPrefs, ok := m.prefs[userID]; ok {
|
||||
delete(userPrefs, notifType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockPrefStore) set(userID, notifType string, inApp, email bool) {
|
||||
if m.prefs[userID] == nil {
|
||||
m.prefs[userID] = make(map[string]*models.NotificationPreference)
|
||||
}
|
||||
m.prefs[userID][notifType] = &models.NotificationPreference{
|
||||
UserID: userID,
|
||||
Type: notifType,
|
||||
InApp: inApp,
|
||||
Email: email,
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_SystemDefault(t *testing.T) {
|
||||
svc := &Service{prefStore: newMockPrefStore()}
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if !p.InApp || p.Email {
|
||||
t.Errorf("expected system default (in_app=true, email=false), got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_NoPrefStore(t *testing.T) {
|
||||
svc := &Service{prefStore: nil}
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if !p.InApp || p.Email {
|
||||
t.Errorf("expected system default when no pref store, got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_SpecificType(t *testing.T) {
|
||||
ps := newMockPrefStore()
|
||||
ps.set("user1", "kb.ready", true, true)
|
||||
svc := &Service{prefStore: ps}
|
||||
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if !p.InApp || !p.Email {
|
||||
t.Errorf("expected specific pref (in_app=true, email=true), got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_WildcardFallback(t *testing.T) {
|
||||
ps := newMockPrefStore()
|
||||
ps.set("user1", "*", false, true) // user turned off in-app, turned on email globally
|
||||
svc := &Service{prefStore: ps}
|
||||
|
||||
// No specific "kb.ready" pref → falls to wildcard
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if p.InApp || !p.Email {
|
||||
t.Errorf("expected wildcard pref (in_app=false, email=true), got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_SpecificOverridesWildcard(t *testing.T) {
|
||||
ps := newMockPrefStore()
|
||||
ps.set("user1", "*", false, true) // wildcard: no in-app, yes email
|
||||
ps.set("user1", "kb.ready", true, false) // specific: yes in-app, no email
|
||||
svc := &Service{prefStore: ps}
|
||||
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if !p.InApp || p.Email {
|
||||
t.Errorf("specific should override wildcard, got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_DifferentUsersIsolated(t *testing.T) {
|
||||
ps := newMockPrefStore()
|
||||
ps.set("user1", "kb.ready", false, true)
|
||||
svc := &Service{prefStore: ps}
|
||||
|
||||
// user2 has no prefs → system default
|
||||
p := svc.resolvePrefs(context.Background(), "user2", "kb.ready")
|
||||
if !p.InApp || p.Email {
|
||||
t.Errorf("user2 should get system default, got %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePrefs_DisableBoth(t *testing.T) {
|
||||
ps := newMockPrefStore()
|
||||
ps.set("user1", "kb.ready", false, false)
|
||||
svc := &Service{prefStore: ps}
|
||||
|
||||
p := svc.resolvePrefs(context.Background(), "user1", "kb.ready")
|
||||
if p.InApp || p.Email {
|
||||
t.Errorf("expected both disabled, got %+v", p)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user