96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
package notify
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aoagents/agent-orchestrator/backend/internal/domain"
|
|
)
|
|
|
|
type fakeStore struct {
|
|
rows []domain.NotificationRecord
|
|
duplicate bool
|
|
err error
|
|
}
|
|
|
|
func (f *fakeStore) CreateNotification(_ context.Context, rec domain.NotificationRecord) (domain.NotificationRecord, bool, error) {
|
|
if f.err != nil {
|
|
return domain.NotificationRecord{}, false, f.err
|
|
}
|
|
if f.duplicate {
|
|
return domain.NotificationRecord{}, false, nil
|
|
}
|
|
f.rows = append(f.rows, rec)
|
|
return rec, true, nil
|
|
}
|
|
|
|
func TestManagerNotifyPersistsThenPublishes(t *testing.T) {
|
|
st := &fakeStore{}
|
|
hub := NewHub()
|
|
ch, unsub := hub.Subscribe("")
|
|
defer unsub()
|
|
now := time.Date(2026, 6, 11, 10, 0, 0, 0, time.UTC)
|
|
mgr := New(Deps{Store: st, Publisher: hub, Clock: func() time.Time { return now }, NewID: func() string { return "ntf_1" }})
|
|
|
|
if err := mgr.Notify(context.Background(), Intent{Type: domain.NotificationNeedsInput, SessionID: "mer-1", ProjectID: "mer", SessionDisplayName: "checkout-flow"}); err != nil {
|
|
t.Fatalf("Notify: %v", err)
|
|
}
|
|
if len(st.rows) != 1 {
|
|
t.Fatalf("stored rows = %d, want 1", len(st.rows))
|
|
}
|
|
if got := st.rows[0]; got.ID != "ntf_1" || got.CreatedAt != now || got.Status != domain.NotificationUnread || got.Title != "checkout-flow needs input" {
|
|
t.Fatalf("stored notification = %+v", got)
|
|
}
|
|
select {
|
|
case got := <-ch:
|
|
if got.ID != "ntf_1" {
|
|
t.Fatalf("published = %+v", got)
|
|
}
|
|
default:
|
|
t.Fatal("expected published notification")
|
|
}
|
|
}
|
|
|
|
func TestManagerNotifyDuplicateDoesNotPublish(t *testing.T) {
|
|
st := &fakeStore{duplicate: true}
|
|
hub := NewHub()
|
|
ch, unsub := hub.Subscribe("")
|
|
defer unsub()
|
|
mgr := New(Deps{Store: st, Publisher: hub, Clock: func() time.Time { return time.Now() }, NewID: func() string { return "ntf_1" }})
|
|
|
|
if err := mgr.Notify(context.Background(), Intent{Type: domain.NotificationNeedsInput, SessionID: "mer-1", ProjectID: "mer", CreatedAt: time.Now()}); err != nil {
|
|
t.Fatalf("Notify duplicate: %v", err)
|
|
}
|
|
select {
|
|
case got := <-ch:
|
|
t.Fatalf("duplicate published %+v", got)
|
|
default:
|
|
}
|
|
}
|
|
|
|
func TestManagerNotifyRejectsUnknownType(t *testing.T) {
|
|
mgr := New(Deps{Store: &fakeStore{}, Clock: func() time.Time { return time.Now() }})
|
|
err := mgr.Notify(context.Background(), Intent{Type: "surprise", SessionID: "mer-1", ProjectID: "mer"})
|
|
if !errors.Is(err, domain.ErrInvalidNotificationType) {
|
|
t.Fatalf("err = %v, want invalid type", err)
|
|
}
|
|
}
|
|
|
|
func TestHubProjectFilter(t *testing.T) {
|
|
hub := NewHub()
|
|
ch, unsub := hub.Subscribe("mer")
|
|
defer unsub()
|
|
_ = hub.Publish(context.Background(), domain.NotificationRecord{ID: "skip", ProjectID: "ao"})
|
|
_ = hub.Publish(context.Background(), domain.NotificationRecord{ID: "keep", ProjectID: "mer"})
|
|
select {
|
|
case got := <-ch:
|
|
if got.ID != "keep" {
|
|
t.Fatalf("published = %+v", got)
|
|
}
|
|
default:
|
|
t.Fatal("expected filtered notification")
|
|
}
|
|
}
|