Skip to content

Commit

Permalink
chore: refactor twillio to be acessed at the usecase level
Browse files Browse the repository at this point in the history
  • Loading branch information
maxwellgithinji committed Sep 16, 2021
1 parent 18480c2 commit 53b7e4a
Show file tree
Hide file tree
Showing 15 changed files with 2,046 additions and 899 deletions.
6 changes: 1 addition & 5 deletions pkg/engagement/infrastructure/infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/surveys"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/twilio"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/uploads"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/whatsapp"
"github.com/savannahghi/engagementcore/pkg/engagement/repository"
"github.com/savannahghi/serverutils"
)
Expand All @@ -34,7 +33,6 @@ type Interactor struct {
*surveys.ServiceSurveyImpl
*twilio.ServiceTwilioImpl
*uploads.ServiceUploadImpl
*whatsapp.ServiceWhatsappImpl
}

// NewInteractor initializes a new infrastructure interactor
Expand All @@ -61,13 +59,12 @@ func NewInteractor() Interactor {
log.Fatal(err)
}

whatsapp := whatsapp.NewService()
sms := sms.NewService(db, pubsub)
twilio := twilio.NewService(*sms, db)

uploads := uploads.NewUploadsService()

otp := otp.NewService(*whatsapp, *mail, *sms, twilio)
otp := otp.NewService(*mail, *sms, twilio)

surveys := surveys.NewService(db)

Expand All @@ -83,6 +80,5 @@ func NewInteractor() Interactor {
surveys,
twilio,
uploads,
whatsapp,
}
}
14 changes: 5 additions & 9 deletions pkg/engagement/infrastructure/services/otp/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/mail"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/sms"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/twilio"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/whatsapp"
"github.com/savannahghi/enumutils"
"github.com/savannahghi/firebasetools"
"github.com/savannahghi/interserviceclient"
Expand Down Expand Up @@ -66,10 +65,9 @@ type ServiceOTP interface {

// ServiceOTPImpl is an OTP generation and validation service
type ServiceOTPImpl struct {
whatsapp whatsapp.ServiceWhatsapp
mail mail.ServiceMail
sms sms.ServiceSMS
twilio twilio.ServiceTwilio
mail mail.ServiceMail
sms sms.ServiceSMS
twilio twilio.ServiceTwilio

totpOpts totp.GenerateOpts
firestoreClient *firestore.Client
Expand All @@ -81,7 +79,6 @@ type ServiceOTPImpl struct {
// of dependencies, the same dependecies defined in the yaml should be defined in the service
// struct definition explicitly, No guess work.
func NewService(
whatsapp whatsapp.ServiceWhatsapp,
mail mail.ServiceMail,
sms sms.ServiceSMS,
twilio twilio.ServiceTwilio,
Expand Down Expand Up @@ -113,7 +110,6 @@ func NewService(
},
firestoreClient: firestoreClient,
rootCollectionSuffix: serverutils.MustGetEnvVar("ROOT_COLLECTION_SUFFIX"),
whatsapp: whatsapp,
mail: mail,
sms: sms,
twilio: twilio,
Expand Down Expand Up @@ -435,7 +431,7 @@ func (s ServiceOTPImpl) GenerateRetryOTP(

if retryStep == whatsappStep {

sent, err := s.whatsapp.PhoneNumberVerificationCode(
sent, err := s.twilio.PhoneNumberVerificationCode(
ctx,
otp.MSISDN,
otp.AuthorizationCode,
Expand Down Expand Up @@ -544,7 +540,7 @@ func (s ServiceOTPImpl) SendTemporaryPIN(ctx context.Context, input dto.Temporar
if input.Channel == whatsappStep {
msg := fmt.Sprintf(PINWhatsApp, input.FirstName, input.PIN)

sent, err := s.whatsapp.TemporaryPIN(ctx, *cleanNo, msg)
sent, err := s.twilio.TemporaryPIN(ctx, *cleanNo, msg)
if err != nil {
helpers.RecordSpanError(span, err)
return fmt.Errorf("unable to send otp via whatsapp: %w", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/otp"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/sms"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/twilio"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/whatsapp"
"github.com/savannahghi/firebasetools"
"github.com/savannahghi/interserviceclient"
"github.com/savannahghi/serverutils"
Expand All @@ -32,7 +31,6 @@ func newTestOtpSService(t *testing.T) (*otp.ServiceOTPImpl, error) {
ctx,
serverutils.MustGetEnvVar(serverutils.GoogleCloudProjectIDEnvVarName),
)
whatsapp := whatsapp.NewService()
mail := mail.NewService(fr)
sms := sms.NewService(fr, ps)
twilio := twilio.NewService(sms, fr)
Expand All @@ -44,7 +42,7 @@ func newTestOtpSService(t *testing.T) (*otp.ServiceOTPImpl, error) {
)
return nil, err
}
return otp.NewService(whatsapp, mail, sms, twilio), nil
return otp.NewService(mail, sms, twilio), nil
}

func TestNewRemoteOtpService(t *testing.T) {
Expand Down
30 changes: 13 additions & 17 deletions pkg/engagement/infrastructure/services/otp/service_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import (
smsMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/sms/mock"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/twilio"
twilioMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/twilio/mock"
"github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/whatsapp"
whatsappMock "github.com/savannahghi/engagementcore/pkg/engagement/infrastructure/services/whatsapp/mock"

"github.com/savannahghi/enumutils"
"github.com/savannahghi/interserviceclient"
"github.com/stretchr/testify/assert"
Expand All @@ -27,9 +26,6 @@ import (
var fakeMail mailMock.FakeServiceMail
var mailSvc mail.ServiceMail = &fakeMail

var fakeWhatsapp whatsappMock.FakeServiceWhatsapp
var whatsappSvc whatsapp.ServiceWhatsapp = &fakeWhatsapp

var fakeSMS smsMock.FakeServiceSMS
var smsSvs sms.ServiceSMS = &fakeSMS

Expand Down Expand Up @@ -101,7 +97,7 @@ func TestNormalizeMSISDN(t *testing.T) {

func TestService_GenerateAndSendOTP(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
appID := uuid.New().String()
type args struct {
ctx context.Context
Expand Down Expand Up @@ -185,7 +181,7 @@ func TestService_GenerateAndSendOTP(t *testing.T) {

func TestService_SendOTPToEmail(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
validEmail := ValidTestEmail
phoneNumber := interserviceclient.TestUserPhoneNumber
appID := uuid.New().String()
Expand Down Expand Up @@ -320,7 +316,7 @@ func TestService_SendOTPToEmail(t *testing.T) {

func TestService_GenerateRetryOtp(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
phoneNumber := interserviceclient.TestUserPhoneNumber
invalidPhoneNumber := "this is definitely not a number"

Expand Down Expand Up @@ -396,7 +392,7 @@ func TestService_GenerateRetryOtp(t *testing.T) {
return nil
}

fakeWhatsapp.PhoneNumberVerificationCodeFn = func(
fakeTwilio.PhoneNumberVerificationCodeFn = func(
ctx context.Context,
to string,
code string,
Expand All @@ -415,7 +411,7 @@ func TestService_GenerateRetryOtp(t *testing.T) {
return nil
}

fakeWhatsapp.PhoneNumberVerificationCodeFn = func(
fakeTwilio.PhoneNumberVerificationCodeFn = func(
ctx context.Context,
to string,
code string,
Expand Down Expand Up @@ -467,7 +463,7 @@ func TestService_GenerateRetryOtp(t *testing.T) {

func TestService_GenerateOTP(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)

type args struct {
ctx context.Context
Expand Down Expand Up @@ -516,7 +512,7 @@ func TestService_EmailVerificationOtp(t *testing.T) {
invalidEmail := "not an email address"
integrationTestEmail := otp.ITEmail

service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
type args struct {
ctx context.Context
email *string
Expand Down Expand Up @@ -814,7 +810,7 @@ func TestService_VerifyEmailOtp(t *testing.T) {

func Test_sendOtp(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
appID := uuid.New().String()
type args struct {
ctx context.Context
Expand Down Expand Up @@ -919,7 +915,7 @@ func Test_sendOtp(t *testing.T) {

func TestService_SendTemporaryPIN(t *testing.T) {
ctx := context.Background()
service := otp.NewService(whatsappSvc, mailSvc, smsSvs, twilioSvc)
service := otp.NewService(mailSvc, smsSvs, twilioSvc)
phone := interserviceclient.TestUserPhoneNumber

type args struct {
Expand Down Expand Up @@ -1013,17 +1009,17 @@ func TestService_SendTemporaryPIN(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.name == "sad: error when sending via whatsapp" {
fakeWhatsapp.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
fakeTwilio.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
return false, fmt.Errorf("unable to send whatsapp")
}
}
if tt.name == "sad: unable to send whatsapp" {
fakeWhatsapp.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
fakeTwilio.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
return false, nil
}
}
if tt.name == "happy: sent whatsapp" {
fakeWhatsapp.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
fakeTwilio.TemporaryPINFn = func(ctx context.Context, to, message string) (bool, error) {
return true, nil
}
}
Expand Down
71 changes: 58 additions & 13 deletions pkg/engagement/infrastructure/services/twilio/mock/twilio_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,82 @@ type FakeServiceTwilio struct {
ctx context.Context,
data dto.CallbackData,
) error
}

// MakeTwilioRequest ...
func (f *FakeServiceTwilio) MakeTwilioRequest(
method string,
urlPath string,
content url.Values,
target interface{},
) error {
return f.MakeTwilioRequestFn(method, urlPath, content, target)
PhoneNumberVerificationCodeFn func(
ctx context.Context,
to string,
code string,
marketingMessage string,
) (bool, error)

SaveTwilioCallbackResponseFn func(
ctx context.Context,
data dto.Message,
) error

TemporaryPINFn func(
ctx context.Context,
to string,
message string,
) (bool, error)
}

// Room ...
// Room is a mock of the Room method
func (f *FakeServiceTwilio) Room(ctx context.Context) (*dto.Room, error) {
return f.RoomFn(ctx)
}

// TwilioAccessToken ...
// TwilioAccessToken is a mock of the TwilioAccessToken method
func (f *FakeServiceTwilio) TwilioAccessToken(ctx context.Context) (*dto.AccessToken, error) {
return f.TwilioAccessTokenFn(ctx)
}

// SendSMS ...
// SendSMS is a mock of the SendSMS method
func (f *FakeServiceTwilio) SendSMS(ctx context.Context, to string, msg string) error {
return f.SendSMSFn(ctx, to, msg)
}

// SaveTwilioVideoCallbackStatus ..
// SaveTwilioVideoCallbackStatus is a mock of the SendSMS method
func (f *FakeServiceTwilio) SaveTwilioVideoCallbackStatus(
ctx context.Context,
data dto.CallbackData,
) error {
return f.SaveTwilioVideoCallbackStatusFn(ctx, data)
}

// PhoneNumberVerificationCode is a mock of the PhoneNumberVerificationCode method
func (f *FakeServiceTwilio) PhoneNumberVerificationCode(
ctx context.Context,
to string,
code string,
marketingMessage string,
) (bool, error) {
return f.PhoneNumberVerificationCodeFn(ctx, to, code, marketingMessage)
}

// SaveTwilioCallbackResponse is a mock of the SaveTwilioCallbackResponse method
func (f *FakeServiceTwilio) SaveTwilioCallbackResponse(
ctx context.Context,
data dto.Message,
) error {
return f.SaveTwilioCallbackResponseFn(ctx, data)
}

// MakeTwilioRequest is a mock of the MakeTwilioRequest method
func (f *FakeServiceTwilio) MakeTwilioRequest(
method string,
urlPath string,
content url.Values,
target interface{},
) error {
return f.MakeTwilioRequestFn(method, urlPath, content, target)
}

// TemporaryPIN is a mock of the TemporaryPIN method
func (f *FakeServiceTwilio) TemporaryPIN(
ctx context.Context,
to string,
message string,
) (bool, error) {
return f.TemporaryPINFn(ctx, to, message)
}
Loading

0 comments on commit 53b7e4a

Please sign in to comment.