This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/notifications/service_test.go
2026-03-01 12:40:15 +00:00

138 lines
4.0 KiB
Go

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)
}
}