@@ -17,9 +17,7 @@ def test_sms_channel_reg(self):
1717
1818 with mock .patch .object (ua .Airship , "_request" ) as mock_request :
1919 response = requests .Response ()
20- response ._content = json .dumps ({"ok" : True , "status" : "pending" }).encode (
21- "utf-8"
22- )
20+ response ._content = json .dumps ({"ok" : True , "status" : "pending" }).encode ("utf-8" )
2321 response .status_code = 202
2422 mock_request .return_value = response
2523
@@ -38,9 +36,7 @@ def test_sms_channel_reg_with_optin(self):
3836
3937 with mock .patch .object (ua .Airship , "_request" ) as mock_request :
4038 response = requests .Response ()
41- response ._content = json .dumps (
42- {"ok" : True , "channel_id" : channel_id }
43- ).encode ("utf-8" )
39+ response ._content = json .dumps ({"ok" : True , "channel_id" : channel_id }).encode ("utf-8" )
4440 response .status_code = 201
4541 mock_request .return_value = response
4642
@@ -90,7 +86,7 @@ def test_sms_registration_payload_property(self):
9086 airship = ua .Airship (TEST_KEY , TEST_SECRET ),
9187 sender = "12345" ,
9288 msisdn = "15035556789" ,
93- opted_in = " 2018-02-13T11:58:59" ,
89+ opted_in = datetime ( 2018 , 2 , 13 , 11 , 58 , 59 ) ,
9490 locale_country = "us" ,
9591 locale_language = "en" ,
9692 timezone = "America/Los_Angeles" ,
@@ -146,6 +142,157 @@ def test_sms_lookup(self):
146142
147143 self .assertTrue (r .ok )
148144
145+ def test_sms_registration_payload_with_new_fields (self ):
146+ """Test SMS registration payload with new fields: opted_out, opt_in_mode, properties."""
147+ sms = ua .Sms (
148+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
149+ sender = "12345" ,
150+ msisdn = "15035556789" ,
151+ opted_in = datetime (2018 , 2 , 13 , 11 , 58 , 59 ),
152+ opted_out = datetime (2018 , 3 , 15 , 14 , 30 , 0 ),
153+ opt_in_mode = "double" ,
154+ properties = {"source" : "web_form" , "campaign" : "summer_2023" },
155+ locale_country = "us" ,
156+ locale_language = "en" ,
157+ timezone = "America/Los_Angeles" ,
158+ )
159+
160+ self .assertEqual (
161+ sms ._registration_payload ,
162+ {
163+ "sender" : "12345" ,
164+ "msisdn" : "15035556789" ,
165+ "locale_language" : "en" ,
166+ "locale_country" : "us" ,
167+ "timezone" : "America/Los_Angeles" ,
168+ "opted_in" : "2018-02-13T11:58:59" ,
169+ },
170+ )
171+
172+ def test_sms_update_payload (self ):
173+ """Test SMS update payload excludes opt_in_mode and properties."""
174+ sms = ua .Sms (
175+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
176+ sender = "12345" ,
177+ msisdn = "15035556789" ,
178+ opted_in = datetime (2018 , 2 , 13 , 11 , 58 , 59 ),
179+ opted_out = datetime (2018 , 3 , 15 , 14 , 30 , 0 ),
180+ opt_in_mode = "double" ,
181+ properties = {"source" : "web_form" },
182+ locale_country = "us" ,
183+ locale_language = "en" ,
184+ timezone = "America/Los_Angeles" ,
185+ )
186+
187+ self .assertEqual (
188+ sms ._update_payload ,
189+ {
190+ "sender" : "12345" ,
191+ "msisdn" : "15035556789" ,
192+ "locale_language" : "en" ,
193+ "locale_country" : "us" ,
194+ "timezone" : "America/Los_Angeles" ,
195+ "opted_in" : "2018-02-13T11:58:59" ,
196+ "opted_out" : "2018-03-15T14:30:00" ,
197+ },
198+ )
199+
200+ def test_sms_create_and_send_audience_with_new_fields (self ):
201+ """Test SMS create and send audience includes new fields."""
202+ sms = ua .Sms (
203+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
204+ sender = "12345" ,
205+ msisdn = "15035556789" ,
206+ opted_in = datetime (2018 , 2 , 13 , 11 , 58 , 59 ),
207+ opted_out = datetime (2018 , 3 , 15 , 14 , 30 , 0 ),
208+ template_fields = {"name" : "John Doe" , "preference" : "text" },
209+ )
210+
211+ audience = sms .create_and_send_audience
212+ self .assertEqual (audience ["ua_sender" ], "12345" )
213+ self .assertEqual (audience ["ua_msisdn" ], "15035556789" )
214+ self .assertEqual (audience ["ua_opted_in" ], datetime (2018 , 2 , 13 , 11 , 58 , 59 ))
215+ self .assertEqual (audience ["ua_opted_out" ], datetime (2018 , 3 , 15 , 14 , 30 , 0 ))
216+ self .assertEqual (audience ["name" ], "John Doe" )
217+ self .assertEqual (audience ["preference" ], "text" )
218+
219+ def test_sms_create_and_send_audience_without_opted_in_raises (self ):
220+ """Test SMS create and send audience raises error without opted_in."""
221+ sms = ua .Sms (
222+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
223+ sender = "12345" ,
224+ msisdn = "15035556789" ,
225+ )
226+
227+ with self .assertRaises (ValueError ) as context :
228+ sms .create_and_send_audience
229+
230+ self .assertIn ("must include opt-in datestamps" , str (context .exception ))
231+
232+ def test_sms_opt_in_mode_validation (self ):
233+ """Test SMS opt_in_mode validation."""
234+ # Valid values
235+ sms = ua .Sms (
236+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
237+ sender = "12345" ,
238+ msisdn = "15035556789" ,
239+ opt_in_mode = "classic" ,
240+ )
241+ self .assertEqual (sms .opt_in_mode , "classic" )
242+
243+ sms .opt_in_mode = "double"
244+ self .assertEqual (sms .opt_in_mode , "double" )
245+
246+ sms .opt_in_mode = None
247+ self .assertIsNone (sms .opt_in_mode )
248+
249+ # Invalid value
250+ with self .assertRaises (ValueError ) as context :
251+ sms .opt_in_mode = "invalid"
252+ self .assertIn ("must be one of: 'classic' or 'double'" , str (context .exception ))
253+
254+ def test_sms_properties_validation (self ):
255+ """Test SMS properties validation."""
256+ # Valid dict
257+ sms = ua .Sms (
258+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
259+ sender = "12345" ,
260+ msisdn = "15035556789" ,
261+ properties = {"key" : "value" },
262+ )
263+ self .assertEqual (sms .properties , {"key" : "value" })
264+
265+ # None value
266+ sms .properties = None
267+ self .assertIsNone (sms .properties )
268+
269+ # Invalid type
270+ with self .assertRaises (TypeError ) as context :
271+ sms .properties = "not_a_dict"
272+ self .assertIn ("must be a dict" , str (context .exception ))
273+
274+ def test_sms_opted_out_datetime_handling (self ):
275+ """Test SMS opted_out datetime handling."""
276+ sms = ua .Sms (
277+ airship = ua .Airship (TEST_KEY , TEST_SECRET ),
278+ sender = "12345" ,
279+ msisdn = "15035556789" ,
280+ )
281+
282+ # Set opted_out
283+ opted_out_dt = datetime (2018 , 3 , 15 , 14 , 30 , 0 )
284+ sms .opted_out = opted_out_dt
285+ self .assertEqual (sms .opted_out , opted_out_dt )
286+
287+ # Clear opted_out
288+ sms .opted_out = None
289+ self .assertIsNone (sms .opted_out )
290+
291+ # Test in update payload (opted_out is only included in updates, not registration)
292+ sms .opted_out = opted_out_dt
293+ update_payload = sms ._update_payload
294+ self .assertEqual (update_payload ["opted_out" ], "2018-03-15T14:30:00" )
295+
149296
150297class TestSmsKeywordInteraction (unittest .TestCase ):
151298 def setUp (self ):
0 commit comments