diff --git a/pkg/engagement/infrastructure/services/messaging/mock/pubsub_mock.go b/pkg/engagement/infrastructure/services/messaging/mock/pubsub_mock.go index bb2a7b4a..f3a779d1 100644 --- a/pkg/engagement/infrastructure/services/messaging/mock/pubsub_mock.go +++ b/pkg/engagement/infrastructure/services/messaging/mock/pubsub_mock.go @@ -4,6 +4,7 @@ import ( "context" "github.com/savannahghi/feedlib" + "github.com/savannahghi/firebasetools" ) // FakeServiceMessaging is a mock implementation of the "messaging" service @@ -23,6 +24,11 @@ type FakeServiceMessaging struct { SubscriptionIDsFn func() map[string]string ReverseSubscriptionIDsFn func() map[string]string + PushFn func( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error } // Notify Sends a message to a topic @@ -37,17 +43,26 @@ func (f *FakeServiceMessaging) Notify( return f.NotifyFn(ctx, topicID, uid, flavour, payload, metadata) } -// TopicIDs ... +// TopicIDs gets topic IDs func (f *FakeServiceMessaging) TopicIDs() []string { return f.TopicIDsFn() } -// SubscriptionIDs ... +// SubscriptionIDs gets subscription IDs func (f *FakeServiceMessaging) SubscriptionIDs() map[string]string { return f.SubscriptionIDsFn() } -// ReverseSubscriptionIDs ... +// ReverseSubscriptionIDs get Reverse Subscription IDs func (f *FakeServiceMessaging) ReverseSubscriptionIDs() map[string]string { return f.ReverseSubscriptionIDsFn() } + +// Push sends push notifications +func (f *FakeServiceMessaging) Push( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, +) error { + return f.PushFn(ctx, sender, payload) +} diff --git a/pkg/engagement/infrastructure/services/messaging/pubsub_test.go b/pkg/engagement/infrastructure/services/messaging/pubsub_integration_test.go similarity index 75% rename from pkg/engagement/infrastructure/services/messaging/pubsub_test.go rename to pkg/engagement/infrastructure/services/messaging/pubsub_integration_test.go index 69c477d4..d327c558 100644 --- a/pkg/engagement/infrastructure/services/messaging/pubsub_test.go +++ b/pkg/engagement/infrastructure/services/messaging/pubsub_integration_test.go @@ -2,6 +2,7 @@ package messaging_test import ( "context" + "reflect" "testing" "time" @@ -148,6 +149,64 @@ func TestPubSubNotificationService_Notify(t *testing.T) { } } +func TestPubSubNotificationService_SubscriptionIDs(t *testing.T) { + ctx := context.Background() + projectID := serverutils.MustGetEnvVar(serverutils.GoogleCloudProjectIDEnvVarName) + srv, err := messaging.NewPubSubNotificationService(ctx, projectID) + if err != nil { + t.Errorf("can't initialize pubsub notification service: %s", err) + return + } + + if srv == nil { + t.Errorf("nil pubsub notification service") + return + } + + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := srv.SubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.ReverseSubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestPubSubNotificationService_ReverseSubscriptionIDs(t *testing.T) { + ctx := context.Background() + projectID := serverutils.MustGetEnvVar(serverutils.GoogleCloudProjectIDEnvVarName) + srv, err := messaging.NewPubSubNotificationService(ctx, projectID) + if err != nil { + t.Errorf("can't initialize pubsub notification service: %s", err) + return + } + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := srv.ReverseSubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.ReverseSubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + func TestRemotePushService_Push(t *testing.T) { ctx := context.Background() projectID := serverutils.MustGetEnvVar(serverutils.GoogleCloudProjectIDEnvVarName) diff --git a/pkg/engagement/infrastructure/services/messaging/pubsub_unit_test.go b/pkg/engagement/infrastructure/services/messaging/pubsub_unit_test.go new file mode 100644 index 00000000..6c57b3ba --- /dev/null +++ b/pkg/engagement/infrastructure/services/messaging/pubsub_unit_test.go @@ -0,0 +1,275 @@ +package messaging_test + +import ( + "context" + "fmt" + "reflect" + "testing" + "time" + + "github.com/google/uuid" + "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/messaging" + messagingMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/messaging/mock" + "github.com/savannahghi/feedlib" + "github.com/savannahghi/firebasetools" + "github.com/segmentio/ksuid" +) + +var ( + fakemessagingService messagingMock.FakeServiceMessaging +) + +func getSendNotificationPayload() *firebasetools.SendNotificationPayload { + + img := "https://www.wxpr.org/sites/wxpr/files/styles/medium/public/202007/chipmunk-5401165_1920.jpg" + key := uuid.New().String() + fakeToken := uuid.New().String() + pckg := "video" + + return &firebasetools.SendNotificationPayload{ + RegistrationTokens: []string{fakeToken}, + Data: map[string]string{ + "some": "data", + }, + Notification: &firebasetools.FirebaseSimpleNotificationInput{ + Title: "Test Notification", + Body: "From Integration Tests", + ImageURL: &img, + Data: map[string]interface{}{ + "more": "data", + }, + }, + Android: &firebasetools.FirebaseAndroidConfigInput{ + Priority: "high", + CollapseKey: &key, + RestrictedPackageName: &pckg, + }, + } +} + +func TestUnit_Notify(t *testing.T) { + ctx := context.Background() + topicID := ksuid.New().String() + uid := ksuid.New().String() + flavour := feedlib.FlavourConsumer + el := &feedlib.Message{ + ID: ksuid.New().String(), + SequenceNumber: 1, + Text: ksuid.New().String(), + ReplyTo: ksuid.New().String(), + PostedByUID: ksuid.New().String(), + PostedByName: ksuid.New().String(), + Timestamp: time.Now(), + } + metadata := map[string]interface{}{ + "test": "metadata", + } + + var s messaging.NotificationService = &fakemessagingService + + type args struct { + ctx context.Context + topicID string + uid string + flavour feedlib.Flavour + el feedlib.Element + metadata map[string]interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: correct params passed", + args: args{ + ctx: ctx, + topicID: topicID, + uid: uid, + flavour: flavour, + el: el, + metadata: metadata, + }, + wantErr: false, + }, + { + name: "invalid: missing args", + args: args{ + ctx: ctx, + }, + wantErr: true, + }, + } + for _, tt := range tests { + if tt.name == "valid: correct params passed" { + fakemessagingService.NotifyFn = func( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + el feedlib.Element, + metadata map[string]interface{}, + ) error { + return nil + } + } + if tt.name == "invalid: missing args" { + fakemessagingService.NotifyFn = func( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + el feedlib.Element, + metadata map[string]interface{}, + ) error { + return fmt.Errorf("test error") + } + } + t.Run(tt.name, func(t *testing.T) { + if err := s.Notify(tt.args.ctx, tt.args.topicID, tt.args.uid, tt.args.flavour, tt.args.el, tt.args.metadata); (err != nil) != tt.wantErr { + t.Errorf("PubSubNotificationService.Notify() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUnit_TopicIDs(t *testing.T) { + + var s messaging.NotificationService = &fakemessagingService + + tests := []struct { + name string + want []string + }{ + { + name: "default case", + want: []string{"testIDs"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.TopicIDsFn = func() []string { + return []string{"testIDs"} + } + } + if got := s.TopicIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.TopicIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_SubscriptionIDs(t *testing.T) { + + var s messaging.NotificationService = &fakemessagingService + + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: map[string]string{"test": "id"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.SubscriptionIDsFn = func() map[string]string { + return map[string]string{"test": "id"} + } + } + if got := s.SubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.SubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_ReverseSubscriptionIDs(t *testing.T) { + var s messaging.NotificationService = &fakemessagingService + + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: map[string]string{"test": "id"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.ReverseSubscriptionIDsFn = func() map[string]string { + return map[string]string{"test": "id"} + } + } + if got := s.ReverseSubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.ReverseSubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_Push(t *testing.T) { + ctx := context.Background() + sender := firebasetools.TestUserEmail + notificationPayload := getSendNotificationPayload() + + var s messaging.NotificationService = &fakemessagingService + + type args struct { + ctx context.Context + sender string + notificationPayload firebasetools.SendNotificationPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: correct params passed", + args: args{ + ctx: ctx, + sender: sender, + notificationPayload: *notificationPayload, + }, + wantErr: false, + }, + { + name: "invalid: missing args passed", + args: args{ + ctx: ctx, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "valid: correct params passed" { + fakemessagingService.PushFn = func( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error { + return nil + } + } + if tt.name == "invalid: missing args passed" { + fakemessagingService.PushFn = func( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error { + return fmt.Errorf("test error") + } + } + if err := s.Push(tt.args.ctx, tt.args.sender, tt.args.notificationPayload); (err != nil) != tt.wantErr { + t.Errorf("PubSubNotificationService.Push() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/engagement/usecases/fcm/fcm_unit_test.go b/pkg/engagement/usecases/fcm/fcm_unit_test.go index fe00a369..5940057d 100644 --- a/pkg/engagement/usecases/fcm/fcm_unit_test.go +++ b/pkg/engagement/usecases/fcm/fcm_unit_test.go @@ -8,8 +8,8 @@ import ( "time" "github.com/savannahghi/engagementcore/pkg/engagement/application/common/dto" - "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/fcm" fcmMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/fcm/mock" + "github.com/savannahghi/engagementcore/pkg/engagement/usecases/fcm" "github.com/savannahghi/firebasetools" "github.com/savannahghi/interserviceclient" ) @@ -28,7 +28,7 @@ func TestUnit_SendNotification(t *testing.T) { ios := firebasetools.FirebaseAPNSConfigInput{} web := firebasetools.FirebaseWebpushConfigInput{} - var f fcm.ServiceFCM = &fakeFCMService + var f fcm.UsecaseFCM = &fakeFCMService type args struct { ctx context.Context @@ -116,7 +116,7 @@ func TestUnit_Notifications(t *testing.T) { notification := []*dto.SavedNotification{} - var f fcm.ServiceFCM = &fakeFCMService + var f fcm.UsecaseFCM = &fakeFCMService type args struct { ctx context.Context @@ -198,7 +198,7 @@ func TestUnit_SendFCMByPhoneOrEmail(t *testing.T) { ios := firebasetools.FirebaseAPNSConfigInput{} web := firebasetools.FirebaseWebpushConfigInput{} - var f fcm.ServiceFCM = &fakeFCMService + var f fcm.UsecaseFCM = &fakeFCMService type args struct { ctx context.Context diff --git a/pkg/engagement/usecases/messaging/messaging.go b/pkg/engagement/usecases/messaging/messaging.go new file mode 100644 index 00000000..fafd86e6 --- /dev/null +++ b/pkg/engagement/usecases/messaging/messaging.go @@ -0,0 +1,90 @@ +package messaging + +import ( + "context" + + "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure" + "github.com/savannahghi/feedlib" + "github.com/savannahghi/firebasetools" +) + +// UsecaseNotification defines pupsub notification service usecases interface +type UsecaseNotification interface { + // Send a message to a topic + Notify( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + payload feedlib.Element, + metadata map[string]interface{}, + ) error + + // Ask the notification service about the topics that it knows about + TopicIDs() []string + + SubscriptionIDs() map[string]string + + ReverseSubscriptionIDs() map[string]string + + Push( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error +} + +// ImplNotification is the pubsub notification service implementation +type ImplNotification struct { + infrastructure infrastructure.Interactor +} + +// NewNotification initializes a pubsub notification service instance +func NewNotification(infrastructure infrastructure.Interactor) *ImplNotification { + return &ImplNotification{ + infrastructure: infrastructure, + } +} + +// Notify Send a message to a topic +func (n *ImplNotification) Notify( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + payload feedlib.Element, + metadata map[string]interface{}, +) error { + i := n.infrastructure.NotificationService + return i.Notify(ctx, topicID, uid, flavour, payload, metadata) +} + +//TopicIDs Ask the notification service about the topics that it knows about +func (n *ImplNotification) TopicIDs() []string { + i := n.infrastructure.NotificationService + return i.TopicIDs() +} + +//SubscriptionIDs gets subscription IDs for the notification service +func (n *ImplNotification) SubscriptionIDs() map[string]string { + i := n.infrastructure.NotificationService + return i.SubscriptionIDs() +} + +// ReverseSubscriptionIDs gets reverse subscription IDs for the notification service +func (n *ImplNotification) ReverseSubscriptionIDs() map[string]string { + i := n.infrastructure.NotificationService + return i.ReverseSubscriptionIDs() +} + +// Push instructs a remote FCM service to send a push notification. +// +// This is done over Google Cloud Pub-Sub. +func (n *ImplNotification) Push( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, +) error { + i := n.infrastructure.NotificationService + return i.Push(ctx, sender, payload) +} diff --git a/pkg/engagement/usecases/messaging/messaging_integration_test.go b/pkg/engagement/usecases/messaging/messaging_integration_test.go new file mode 100644 index 00000000..34e7bc39 --- /dev/null +++ b/pkg/engagement/usecases/messaging/messaging_integration_test.go @@ -0,0 +1,198 @@ +package messaging_test + +import ( + "context" + "reflect" + "testing" + "time" + + "github.com/rs/xid" + "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure" + "github.com/savannahghi/engagementcore/pkg/engagement/usecases/messaging" + "github.com/savannahghi/feedlib" + "github.com/savannahghi/firebasetools" + "github.com/segmentio/ksuid" +) + +func InitializeTestNewMessaging(ctx context.Context) (*messaging.ImplNotification, infrastructure.Interactor, error) { + infra := infrastructure.NewInteractor() + messaging := messaging.NewNotification(infra) + return messaging, infra, nil +} + +func getNotificationPayload(t *testing.T) firebasetools.SendNotificationPayload { + imgURL := "https://example.com/img.png" + return firebasetools.SendNotificationPayload{ + RegistrationTokens: []string{xid.New().String(), xid.New().String()}, + Data: map[string]string{ + xid.New().String(): xid.New().String(), + xid.New().String(): xid.New().String(), + }, + Notification: &firebasetools.FirebaseSimpleNotificationInput{ + Title: xid.New().String(), + Body: xid.New().String(), + ImageURL: &imgURL, + Data: map[string]interface{}{ + xid.New().String(): xid.New().String(), + xid.New().String(): xid.New().String(), + }, + }, + } +} + +func TestNewPubSubNotificationService(t *testing.T) { + ctx := context.Background() + f, i, err := InitializeTestNewMessaging(ctx) + if err != nil { + t.Errorf("failed to initialize new Messaging: %v", err) + } + + type args struct { + infrastructure infrastructure.Interactor + } + tests := []struct { + name string + args args + want *messaging.ImplNotification + }{ + { + name: "default case", + args: args{ + infrastructure: i, + }, + want: f, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := messaging.NewNotification(tt.args.infrastructure); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewMessaging() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestPubSubNotificationService_Notify(t *testing.T) { + ctx := context.Background() + _, i, err := InitializeTestNewMessaging(ctx) + if err != nil { + t.Errorf("failed to initialize new Messaging: %v", err) + } + + s := messaging.NewNotification(i) + if s == nil { + t.Errorf("nil pubsub notification service") + return + } + + type args struct { + channel string + uid string + flavour feedlib.Flavour + el feedlib.Element + metadata map[string]interface{} + } + tests := []struct { + name string + pubsub messaging.UsecaseNotification + args args + wantErr bool + }{ + { + pubsub: s, + args: args{ + channel: "message.post", + el: &feedlib.Message{ + ID: ksuid.New().String(), + SequenceNumber: 1, + Text: ksuid.New().String(), + ReplyTo: ksuid.New().String(), + PostedByUID: ksuid.New().String(), + PostedByName: ksuid.New().String(), + Timestamp: time.Now(), + }, + uid: ksuid.New().String(), + flavour: feedlib.FlavourConsumer, + metadata: map[string]interface{}{}, + }, + wantErr: false, + }, + { + name: "invalid message, missing posted by info", + pubsub: s, + args: args{ + channel: "message.post", + el: &feedlib.Message{ + ID: ksuid.New().String(), + Text: ksuid.New().String(), + ReplyTo: ksuid.New().String(), + Timestamp: time.Now(), + }, + uid: ksuid.New().String(), + flavour: feedlib.FlavourPro, + metadata: map[string]interface{}{}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.pubsub.Notify( + context.Background(), + tt.args.channel, + tt.args.uid, + tt.args.flavour, + tt.args.el, + tt.args.metadata, + ); (err != nil) != tt.wantErr { + t.Errorf( + "PubSubNotificationService.Notify() error = %v, wantErr %v", + err, + tt.wantErr, + ) + } + }) + } +} + +func TestRemotePushService_Push(t *testing.T) { + ctx := context.Background() + _, i, err := InitializeTestNewMessaging(ctx) + if err != nil { + t.Errorf("failed to initialize new Messaging: %v", err) + } + + s := messaging.NewNotification(i) + if s == nil { + t.Errorf("nil remote Messaging push service") + return + } + + type args struct { + ctx context.Context + sender string + notificationPayload firebasetools.SendNotificationPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid send - won't actually push but won't error", + args: args{ + ctx: ctx, + sender: "test", + notificationPayload: getNotificationPayload(t), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := s.Push(tt.args.ctx, tt.args.sender, tt.args.notificationPayload); (err != nil) != tt.wantErr { + t.Errorf("RemotePushService.Push() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/engagement/usecases/messaging/messaging_unit_test.go b/pkg/engagement/usecases/messaging/messaging_unit_test.go new file mode 100644 index 00000000..0e0e98a0 --- /dev/null +++ b/pkg/engagement/usecases/messaging/messaging_unit_test.go @@ -0,0 +1,275 @@ +package messaging_test + +import ( + "context" + "fmt" + "reflect" + "testing" + "time" + + "github.com/google/uuid" + messagingMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/messaging/mock" + "github.com/savannahghi/engagementcore/pkg/engagement/usecases/messaging" + "github.com/savannahghi/feedlib" + "github.com/savannahghi/firebasetools" + "github.com/segmentio/ksuid" +) + +var ( + fakemessagingService messagingMock.FakeServiceMessaging +) + +func getSendNotificationPayload() *firebasetools.SendNotificationPayload { + + img := "https://www.wxpr.org/sites/wxpr/files/styles/medium/public/202007/chipmunk-5401165_1920.jpg" + key := uuid.New().String() + fakeToken := uuid.New().String() + pckg := "video" + + return &firebasetools.SendNotificationPayload{ + RegistrationTokens: []string{fakeToken}, + Data: map[string]string{ + "some": "data", + }, + Notification: &firebasetools.FirebaseSimpleNotificationInput{ + Title: "Test Notification", + Body: "From Integration Tests", + ImageURL: &img, + Data: map[string]interface{}{ + "more": "data", + }, + }, + Android: &firebasetools.FirebaseAndroidConfigInput{ + Priority: "high", + CollapseKey: &key, + RestrictedPackageName: &pckg, + }, + } +} + +func TestUnit_Notify(t *testing.T) { + ctx := context.Background() + topicID := ksuid.New().String() + uid := ksuid.New().String() + flavour := feedlib.FlavourConsumer + el := &feedlib.Message{ + ID: ksuid.New().String(), + SequenceNumber: 1, + Text: ksuid.New().String(), + ReplyTo: ksuid.New().String(), + PostedByUID: ksuid.New().String(), + PostedByName: ksuid.New().String(), + Timestamp: time.Now(), + } + metadata := map[string]interface{}{ + "test": "metadata", + } + + var s messaging.UsecaseNotification = &fakemessagingService + + type args struct { + ctx context.Context + topicID string + uid string + flavour feedlib.Flavour + el feedlib.Element + metadata map[string]interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: correct params passed", + args: args{ + ctx: ctx, + topicID: topicID, + uid: uid, + flavour: flavour, + el: el, + metadata: metadata, + }, + wantErr: false, + }, + { + name: "invalid: missing args", + args: args{ + ctx: ctx, + }, + wantErr: true, + }, + } + for _, tt := range tests { + if tt.name == "valid: correct params passed" { + fakemessagingService.NotifyFn = func( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + el feedlib.Element, + metadata map[string]interface{}, + ) error { + return nil + } + } + if tt.name == "invalid: missing args" { + fakemessagingService.NotifyFn = func( + ctx context.Context, + topicID string, + uid string, + flavour feedlib.Flavour, + el feedlib.Element, + metadata map[string]interface{}, + ) error { + return fmt.Errorf("test error") + } + } + t.Run(tt.name, func(t *testing.T) { + if err := s.Notify(tt.args.ctx, tt.args.topicID, tt.args.uid, tt.args.flavour, tt.args.el, tt.args.metadata); (err != nil) != tt.wantErr { + t.Errorf("PubSubNotificationService.Notify() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUnit_TopicIDs(t *testing.T) { + + var s messaging.UsecaseNotification = &fakemessagingService + + tests := []struct { + name string + want []string + }{ + { + name: "default case", + want: []string{"testIDs"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.TopicIDsFn = func() []string { + return []string{"testIDs"} + } + } + if got := s.TopicIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.TopicIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_SubscriptionIDs(t *testing.T) { + + var s messaging.UsecaseNotification = &fakemessagingService + + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: map[string]string{"test": "id"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.SubscriptionIDsFn = func() map[string]string { + return map[string]string{"test": "id"} + } + } + if got := s.SubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.SubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_ReverseSubscriptionIDs(t *testing.T) { + var s messaging.UsecaseNotification = &fakemessagingService + + tests := []struct { + name string + want map[string]string + }{ + { + name: "default case", + want: map[string]string{"test": "id"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "default case" { + fakemessagingService.ReverseSubscriptionIDsFn = func() map[string]string { + return map[string]string{"test": "id"} + } + } + if got := s.ReverseSubscriptionIDs(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PubSubNotificationService.ReverseSubscriptionIDs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnit_Push(t *testing.T) { + ctx := context.Background() + sender := firebasetools.TestUserEmail + notificationPayload := getSendNotificationPayload() + + var s messaging.UsecaseNotification = &fakemessagingService + + type args struct { + ctx context.Context + sender string + notificationPayload firebasetools.SendNotificationPayload + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: correct params passed", + args: args{ + ctx: ctx, + sender: sender, + notificationPayload: *notificationPayload, + }, + wantErr: false, + }, + { + name: "invalid: missing args passed", + args: args{ + ctx: ctx, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "valid: correct params passed" { + fakemessagingService.PushFn = func( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error { + return nil + } + } + if tt.name == "invalid: missing args passed" { + fakemessagingService.PushFn = func( + ctx context.Context, + sender string, + payload firebasetools.SendNotificationPayload, + ) error { + return fmt.Errorf("test error") + } + } + if err := s.Push(tt.args.ctx, tt.args.sender, tt.args.notificationPayload); (err != nil) != tt.wantErr { + t.Errorf("PubSubNotificationService.Push() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/engagement/usecases/usecases.go b/pkg/engagement/usecases/usecases.go index 27f2b489..e83f1dad 100644 --- a/pkg/engagement/usecases/usecases.go +++ b/pkg/engagement/usecases/usecases.go @@ -6,6 +6,7 @@ import ( "github.com/savannahghi/engagementcore/pkg/engagement/usecases/feed" "github.com/savannahghi/engagementcore/pkg/engagement/usecases/library" "github.com/savannahghi/engagementcore/pkg/engagement/usecases/mail" + "github.com/savannahghi/engagementcore/pkg/engagement/usecases/messaging" ) // Interactor is an implementation of the usecases interface @@ -15,6 +16,7 @@ type Interactor struct { *fcm.ImplFCM *library.ImplLibrary *mail.ImplMail + *messaging.ImplNotification } // NewUsecasesInteractor initializes a new usecases interactor @@ -25,6 +27,7 @@ func NewUsecasesInteractor(infrastructure infrastructure.Interactor) Interactor fcm := fcm.NewFCM(infrastructure) library := library.NewLibrary(infrastructure) mail := mail.NewMail(infrastructure) + messaging := messaging.NewNotification(infrastructure) return Interactor{ feed, @@ -32,5 +35,6 @@ func NewUsecasesInteractor(infrastructure infrastructure.Interactor) Interactor fcm, library, mail, + messaging, } }