@@ -8,10 +8,11 @@ import { Test, TestingModule } from '@nestjs/testing';
88import { SmsManager } from './sms.manager' ;
99import { SmsManagerConfig } from './sms.manger.config' ;
1010import { TwilioProvider } from './twilio.provider' ;
11+ import { TwilioErrorCodes } from './recovery-phone.errors' ;
1112
1213describe ( 'SmsManager' , ( ) => {
1314 const to = '+15005551111' ;
14- const from = '+15005550000' ;
15+ const from = [ '+15005550000' , '+15005550001' ] ;
1516 const mockTwilioSmsClient = {
1617 messages : {
1718 create : jest . fn ( ) ,
@@ -27,6 +28,7 @@ describe('SmsManager', () => {
2728 from,
2829 validNumberPrefixes : [ '+1' ] ,
2930 maxMessageLength : 160 ,
31+ maxRetries : 2 ,
3032 } ;
3133
3234 let manager : SmsManager ;
@@ -68,7 +70,7 @@ describe('SmsManager', () => {
6870 expect ( msg ) . toBeDefined ( ) ;
6971 expect ( mockTwilioSmsClient . messages . create ) . toBeCalledWith ( {
7072 to,
71- from,
73+ from : from [ 0 ] ,
7274 body,
7375 } ) ;
7476 expect ( msg ?. status ) . toEqual ( 'sent' ) ;
@@ -105,6 +107,62 @@ describe('SmsManager', () => {
105107 ) ;
106108 } ) ;
107109
110+ it ( 'Retries if send rate limit exceeded.' , async ( ) => {
111+ const mockError = new Error ( ) ;
112+ ( mockError as any ) . code = TwilioErrorCodes . SMS_SEND_RATE_LIMIT_EXCEEDED ;
113+ mockTwilioSmsClient . messages . create . mockRejectedValueOnce ( mockError ) ;
114+ mockTwilioSmsClient . messages . create . mockReturnValueOnce ( {
115+ sid : 'foo' ,
116+ status : 'sent' ,
117+ } ) ;
118+ const body = 'test success' ;
119+ const msg = await manager . sendSMS ( {
120+ to,
121+ body,
122+ } ) ;
123+
124+ expect ( msg ) . toBeDefined ( ) ;
125+ expect ( mockTwilioSmsClient . messages . create ) . toBeCalledWith ( {
126+ to,
127+ from : from [ 0 ] ,
128+ body,
129+ } ) ;
130+ expect ( mockTwilioSmsClient . messages . create ) . toBeCalledWith ( {
131+ to,
132+ from : from [ 0 ] ,
133+ body,
134+ } ) ;
135+ expect ( mockTwilioSmsClient . messages . create ) . toBeCalledTimes ( 2 ) ;
136+ expect ( msg ?. status ) . toEqual ( 'sent' ) ;
137+ expect ( mockLog . log ) . toBeCalledTimes ( 1 ) ;
138+ expect ( mockLog . log ) . toBeCalledWith ( 'SMS sent' , {
139+ sid : 'foo' ,
140+ status : 'sent' ,
141+ } ) ;
142+ expect ( mockMetrics . increment ) . toBeCalledTimes ( 1 ) ;
143+ expect ( mockMetrics . increment ) . toBeCalledWith ( 'sms.send.sent' ) ;
144+ } ) ;
145+
146+ it ( 'Retries but eventually fails if send rate limit exceeded.' , async ( ) => {
147+ const mockError = new Error ( ) ;
148+ ( mockError as any ) . code = TwilioErrorCodes . SMS_SEND_RATE_LIMIT_EXCEEDED ;
149+
150+ mockTwilioSmsClient . messages . create . mockRejectedValue ( mockError ) ;
151+ const body = 'test success' ;
152+ await expect (
153+ manager . sendSMS ( {
154+ to,
155+ body,
156+ } )
157+ ) . rejects . toThrow (
158+ 'Too many SMS are currently being sent. Try again later.'
159+ ) ;
160+
161+ expect ( mockLog . log ) . toBeCalledTimes ( 0 ) ;
162+ expect ( mockMetrics . increment ) . toBeCalledTimes ( 1 ) ;
163+ expect ( mockTwilioSmsClient . messages . create ) . toBeCalledTimes ( 3 ) ; // initial call + config.maxRetries.
164+ } ) ;
165+
108166 it ( 'Records failure' , async ( ) => {
109167 const boom = new Error ( 'Boom' ) ;
110168 mockTwilioSmsClient . messages . create . mockRejectedValue ( boom ) ;
@@ -120,4 +178,13 @@ describe('SmsManager', () => {
120178 expect ( mockLog . log ) . toBeCalledTimes ( 0 ) ;
121179 expect ( mockMetrics . increment ) . toBeCalledTimes ( 1 ) ;
122180 } ) ;
181+
182+ it ( 'Rotates numbers' , ( ) => {
183+ const number1 = manager . rotateFromNumber ( ) ;
184+ const number2 = manager . rotateFromNumber ( ) ;
185+
186+ expect ( number1 ) . toBeDefined ( ) ;
187+ expect ( number2 ) . toBeDefined ( ) ;
188+ expect ( number1 ) . not . toEqual ( number2 ) ;
189+ } ) ;
123190} ) ;
0 commit comments