1+ import {
2+ preMessageSave ,
3+ postMessageSave
4+ } from "../../../src/extensions/message-handlers/auto-optin" ;
5+ import { cacheableData , r } from "../../../src/server/models" ;
6+
7+ import {
8+ setupTest ,
9+ cleanupTest ,
10+ createStartedCampaign
11+ } from "../../test_helpers" ;
12+
13+ const CacheableMessage = require ( "../../../src/server/models/cacheable_queries/message" ) ;
14+ const saveMessage = CacheableMessage . default . save ;
15+
16+ const AutoOptin = require ( "../../../src/extensions/message-handlers/auto-optin" ) ;
17+
18+ const config = require ( "../../../src/server/api/lib/config" ) ;
19+
20+ describe ( "Auto Opt-In Tests" , ( ) => {
21+ let messageToSave ;
22+ let organization ;
23+
24+ beforeEach ( ( ) => {
25+ jest . resetAllMocks ( ) ;
26+
27+ global . DEFAULT_SERVICE = "fakeservice" ;
28+
29+ jest . spyOn ( cacheableData . optIn , "save" ) . mockResolvedValue ( null ) ;
30+ jest . spyOn ( cacheableData . campaignContact , "load" ) . mockResolvedValue ( {
31+ id : 1 ,
32+ assignment_id : 2
33+ } ) ;
34+ jest . spyOn ( AutoOptin , "available" ) . mockReturnValue ( true ) ;
35+ jest . spyOn ( config , "getConfig" ) . mockReturnValue ( "" ) ;
36+
37+ messageToSave = {
38+ is_from_contact : true ,
39+ contact_number : "+1234567890" ,
40+ capmaign_contact_id : 1 ,
41+ text : "START" ,
42+ campaign_contact_id : 42
43+ } ;
44+ // I think this is the structure,
45+ // even if wrong, doesnt affect test
46+ organization = 1 ;
47+ } )
48+
49+ afterEach ( ( ) => {
50+ global . DEFAULT_SERVICE = "fakeservice" ;
51+ } ) ;
52+
53+ describe ( "preMessageSave" , ( ) => {
54+ it ( "returns object on default settings" , async ( ) => {
55+ const result = preMessageSave ( {
56+ messageToSave,
57+ organization
58+ } ) ;
59+
60+ expect ( config . getConfig ) . toHaveBeenCalled ( ) ;
61+ expect ( result ) . toEqual ( {
62+ contactUpdates : {
63+ is_opted_in : true
64+ } ,
65+ handlerContext : {
66+ autoOptInReason : "start"
67+ } ,
68+ messageToSave
69+ } )
70+ } ) ;
71+
72+ it ( "does not return with a non matching message" , async ( ) => {
73+ messageToSave = {
74+ ...messageToSave ,
75+ text : "just another message"
76+ } ;
77+
78+ const result = preMessageSave ( {
79+ messageToSave,
80+ organization
81+ } ) ;
82+
83+ expect ( config . getConfig ) . toHaveBeenCalled ( ) ;
84+ expect ( result ) . toEqual ( undefined ) ;
85+ } ) ;
86+
87+ it ( "does not return, even when START is apart of the text" , async ( ) => {
88+ // This is inline with DEFAULT_AUTO_OPTIN_REGEX_LIST_BASE64.
89+ // If AUTO_OPTIN_REGEX_LIST_BASE64 is enabled, may change behavior.
90+ messageToSave = {
91+ ...messageToSave ,
92+ text : "START, but do not opt me in"
93+ } ;
94+
95+ const result = preMessageSave ( {
96+ messageToSave,
97+ organization
98+ } ) ;
99+
100+ expect ( config . getConfig ) . toHaveBeenCalled ( ) ;
101+ expect ( result ) . toEqual ( undefined ) ;
102+ } ) ;
103+
104+ it ( "returns an object after changing default regex" , async ( ) => {
105+ // this also tests autoOptInReason is "optin"
106+ jest . spyOn ( config , "getConfig" ) . mockReturnValue (
107+ "W3sicmVnZXgiOiAiXk9QVC1JTiQiLCAicmVhc29uIjogIm9wdGluIn1d"
108+ ) ; // [{"regex": "^OPT-IN$"", "reason": "optin"}]
109+
110+ messageToSave = {
111+ ...messageToSave ,
112+ text :"OPT-IN"
113+ } ;
114+
115+ const result = preMessageSave ( {
116+ messageToSave,
117+ organization
118+ } )
119+
120+ expect ( result ) . toEqual ( {
121+ contactUpdates : {
122+ is_opted_in : true
123+ } ,
124+ handlerContext : {
125+ autoOptInReason : "optin"
126+ } ,
127+ messageToSave
128+ } )
129+ } ) ;
130+
131+ it ( "tests autoOptInReason defaults to \"auto_optin\" when no reason is given in regex" , async ( ) => {
132+ jest . spyOn ( config , "getConfig" ) . mockReturnValue (
133+ "W3sicmVnZXgiOiAiXk9QVC1JTiQifV0="
134+ ) ; // [{"regex": "^OPT-IN$"}]
135+
136+ messageToSave = {
137+ ...messageToSave ,
138+ text : "OPT-IN"
139+ } ;
140+
141+ const result = preMessageSave ( {
142+ messageToSave,
143+ organization
144+ } ) ;
145+
146+ expect ( result ) . toEqual ( {
147+ contactUpdates : {
148+ is_opted_in : true
149+ } ,
150+ handlerContext : {
151+ autoOptInReason : "auto_optin"
152+ } ,
153+ messageToSave
154+ } )
155+ } ) ;
156+ } )
157+
158+ describe ( "postMessageSave" , ( ) => {
159+ let message ;
160+ let organization ;
161+ let handlerContext ;
162+ let campaign ;
163+
164+ beforeEach ( async ( ) => {
165+ jest . restoreAllMocks ( ) ;
166+
167+ global . DEFAULT_SERVICE = "fakeservice" ;
168+
169+ message = {
170+ is_from_contact : true ,
171+ campaign_contact_id : 42
172+ } ;
173+
174+ organization = {
175+ id : 2
176+ } ;
177+
178+ handlerContext = {
179+ autoOptInReason : "start"
180+ } ;
181+
182+ campaign = { }
183+
184+ jest . spyOn ( cacheableData . campaignContact , "load" ) . mockReturnValue ( null ) ;
185+ jest . spyOn ( cacheableData . optIn , "save" ) . mockReturnValue ( null ) ;
186+ } ) ;
187+
188+ afterEach ( async ( ) => {
189+ jest . restoreAllMocks ( ) ;
190+ global . DEFAULT_SERVICE = "fakeservice" ;
191+ } ) ;
192+
193+ it ( "saves to optIn table" , async ( ) => {
194+ await postMessageSave ( {
195+ message,
196+ organization,
197+ handlerContext,
198+ campaign
199+ } ) ;
200+
201+ expect ( cacheableData . campaignContact . load ) . toHaveBeenCalled ( ) ;
202+ expect ( cacheableData . optIn . save ) . toHaveBeenCalled ( ) ;
203+ } ) ;
204+
205+ it ( "does not save to optin table with no handlerContext.autoOptInReason" , async ( ) => {
206+ handlerContext = { } ;
207+
208+ await postMessageSave ( {
209+ message,
210+ organization,
211+ handlerContext,
212+ campaign
213+ } ) ;
214+
215+ expect ( cacheableData . campaignContact . load ) . toHaveBeenCalledTimes ( 0 ) ;
216+ expect ( cacheableData . optIn . save ) . toHaveBeenCalledTimes ( 0 ) ;
217+ } ) ;
218+
219+ it ( "does not save to optin table with when message is not from contact" , async ( ) => {
220+ message = { } ;
221+
222+ await postMessageSave ( {
223+ message,
224+ organization,
225+ handlerContext,
226+ campaign
227+ } ) ;
228+
229+ expect ( cacheableData . campaignContact . load ) . toHaveBeenCalledTimes ( 0 ) ;
230+ expect ( cacheableData . optIn . save ) . toHaveBeenCalledTimes ( 0 ) ;
231+ } ) ;
232+ } ) ;
233+ } ) ;
234+
235+ describe ( "Tests for Auto Opt-Out's members getting called from messageCache.save" , ( ) => {
236+ let contacts ;
237+ let organization ;
238+ let texter ;
239+
240+ let service ;
241+ let messageServiceSID ;
242+
243+ beforeEach ( async ( ) => {
244+ await cleanupTest ( ) ;
245+ await setupTest ( ) ;
246+ jest . restoreAllMocks ( ) ;
247+
248+ global . MESSAGE_HANDLERS = "auto-optin" ;
249+
250+ const startedCampaign = await createStartedCampaign ( ) ;
251+
252+ ( {
253+ testContacts : contacts ,
254+ testTexterUser : texter ,
255+ testOrganization : {
256+ data : { createOrganization : organization }
257+ }
258+ } = startedCampaign ) ;
259+
260+ service = "twilio" ;
261+ messageServiceSID = "some_messsage_service_id" ;
262+
263+ const messageToContact = {
264+ is_from_contact : false ,
265+ contact_number : contacts [ 0 ] . cell ,
266+ campaign_contact_id : contacts [ 0 ] . id ,
267+ send_status : "SENT" ,
268+ text : "Hi" ,
269+ service,
270+ texter,
271+ messageservice_sid : messageServiceSID
272+ } ;
273+
274+ await saveMessage ( {
275+ messageInstance : messageToContact ,
276+ contact : contacts [ 0 ] ,
277+ organization,
278+ texter
279+ } ) ;
280+ } , global . DATABASE_SETUP_TEARDOWN_TIMEOUT ) ;
281+
282+ afterEach ( async ( ) => {
283+ await cleanupTest ( ) ;
284+ } , global . DATABASE_SETUP_TEARDOWN_TIMEOUT ) ;
285+
286+ it ( "gets called" , async ( ) => {
287+ const message = {
288+ is_from_contact : true ,
289+ contact_number : contacts [ 0 ] . cell ,
290+ service,
291+ messageservice_sid : messageServiceSID ,
292+ text : "START" ,
293+ send_status : "DELIVERED" // ??
294+ } ;
295+
296+ jest . spyOn ( AutoOptin , "preMessageSave" ) . mockResolvedValue ( null ) ;
297+ jest . spyOn ( AutoOptin , "postMessageSave" ) . mockResolvedValue ( null ) ;
298+
299+ await saveMessage ( {
300+ messageInstance : message
301+ } ) ;
302+
303+ expect ( AutoOptin . preMessageSave ) . toHaveBeenCalledWith (
304+ expect . objectContaining ( {
305+ messageToSave : expect . objectContaining ( {
306+ text : "START" ,
307+ contact_number : contacts [ 0 ] . cell
308+ } )
309+ } )
310+ ) ;
311+
312+ expect ( AutoOptin . postMessageSave ) . toHaveBeenCalledWith (
313+ expect . objectContaining ( {
314+ message : expect . objectContaining ( {
315+ text : "START" ,
316+ contact_number : contacts [ 0 ] . cell
317+ } )
318+ } )
319+ ) ;
320+ } ) ;
321+ } ) ;
0 commit comments