mirror of
https://github.com/warmbly/warmbly.git
synced 2026-10-15 08:02:42 +00:00
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
119 lines
4.3 KiB
Go
119 lines
4.3 KiB
Go
package notification
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/warmbly/warmbly/internal/models"
|
|
"github.com/warmbly/warmbly/internal/repository"
|
|
)
|
|
|
|
type messageNotificationRepo struct {
|
|
repository.NotificationRepository
|
|
allowed bool
|
|
err error
|
|
checks, created int
|
|
channels models.ChannelPrefs
|
|
skipped []uuid.UUID
|
|
retry []uuid.UUID
|
|
}
|
|
|
|
func (r *messageNotificationRepo) CanNotifyAboutMessage(context.Context, uuid.UUID, models.NotificationCategory) (bool, error) {
|
|
r.checks++
|
|
return r.allowed, r.err
|
|
}
|
|
|
|
func (r *messageNotificationRepo) GetPreferences(context.Context, uuid.UUID) (*models.NotificationPreferences, error) {
|
|
prefs := models.DefaultNotificationPreferences()
|
|
prefs.InboundReply = models.CategoryPref{Enabled: true, Channels: r.channels}
|
|
return &prefs, nil
|
|
}
|
|
|
|
func (r *messageNotificationRepo) Create(_ context.Context, n *models.Notification) (*models.Notification, error) {
|
|
r.created++
|
|
return n, nil
|
|
}
|
|
|
|
func (r *messageNotificationRepo) SkipEmails(_ context.Context, ids []uuid.UUID) error {
|
|
r.skipped = append(r.skipped, ids...)
|
|
return nil
|
|
}
|
|
|
|
func (r *messageNotificationRepo) RequeueEmails(_ context.Context, ids []uuid.UUID, _ time.Duration, _ int) error {
|
|
r.retry = append(r.retry, ids...)
|
|
return nil
|
|
}
|
|
|
|
func TestEmailRechecksTheMessageAfterClaiming(t *testing.T) {
|
|
id, notificationID, actionID := uuid.New(), uuid.New(), uuid.New()
|
|
r := &messageNotificationRepo{}
|
|
s := &service{repo: r}
|
|
kept := s.keepEligibleEmailMessages(context.Background(), []models.Notification{
|
|
{ID: notificationID, Category: models.NotifInboundReply, UniboxEmailID: &id},
|
|
{ID: actionID, Category: models.NotifInboxActionRequired, UniboxEmailID: &id},
|
|
})
|
|
if len(kept) != 1 || kept[0].ID != actionID || len(r.skipped) != 1 || r.skipped[0] != notificationID {
|
|
t.Fatalf("kept=%v, skipped=%v", kept, r.skipped)
|
|
}
|
|
r.skipped = nil
|
|
r.err = errors.New("database unavailable")
|
|
kept = s.keepEligibleEmailMessages(context.Background(), []models.Notification{
|
|
{ID: notificationID, Category: models.NotifInboundReply, UniboxEmailID: &id},
|
|
})
|
|
if len(kept) != 0 || len(r.skipped) != 0 || len(r.retry) != 1 || r.retry[0] != notificationID {
|
|
t.Fatalf("eligibility lookup failure did not retry: kept=%v skipped=%v retry=%v", kept, r.skipped, r.retry)
|
|
}
|
|
}
|
|
|
|
func TestNotifyAboutMessageGatesEveryChannel(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
allowed bool
|
|
err error
|
|
channels models.ChannelPrefs
|
|
}{
|
|
{"in app", false, nil, models.ChannelPrefs{InApp: true}},
|
|
{"slack only", false, nil, models.ChannelPrefs{Slack: true}},
|
|
{"push only", false, nil, models.ChannelPrefs{Push: true}},
|
|
{"email only", false, nil, models.ChannelPrefs{Email: true}},
|
|
{"lookup failed", false, errors.New("database unavailable"), models.ChannelPrefs{InApp: true}},
|
|
{"human reply", true, nil, models.ChannelPrefs{InApp: true}},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
r := &messageNotificationRepo{allowed: tc.allowed, err: tc.err, channels: tc.channels}
|
|
s := &service{repo: r}
|
|
s.NotifyAboutMessage(context.Background(), uuid.New(), nil, uuid.New(), models.NotifInboundReply, "Reply", "", "", nil)
|
|
if r.checks != 1 {
|
|
t.Fatalf("eligibility checks = %d, want 1", r.checks)
|
|
}
|
|
if (r.created == 1) != tc.allowed {
|
|
t.Fatalf("created = %d, allowed = %v", r.created, tc.allowed)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPendingPushRechecksTheMessageButKeepsActionAlerts(t *testing.T) {
|
|
id := uuid.New()
|
|
r := &messageNotificationRepo{}
|
|
s := &service{repo: r}
|
|
for _, category := range []models.NotificationCategory{models.NotifInboundReply, models.NotifInboundOOO} {
|
|
if s.canPushMessage(context.Background(), category, pendingPush{MessageID: &id}) {
|
|
t.Errorf("%s accepted an automated message", category)
|
|
}
|
|
if s.canPushMessage(context.Background(), category, pendingPush{Body: "Report Domain: example.test Submitter: seznam.cz Report-ID: abc"}) {
|
|
t.Errorf("%s accepted a legacy report batch", category)
|
|
}
|
|
}
|
|
if !s.canPushMessage(context.Background(), models.NotifInboxActionRequired, pendingPush{MessageID: &id}) {
|
|
t.Fatal("action alert was suppressed")
|
|
}
|
|
r.allowed = true
|
|
if !s.canPushMessage(context.Background(), models.NotifInboundReply, pendingPush{MessageID: &id}) {
|
|
t.Fatal("genuine reply was suppressed")
|
|
}
|
|
}
|