All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
138 lines
4.0 KiB
Go
138 lines
4.0 KiB
Go
package notifications
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"armature/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)
|
|
}
|
|
}
|