Skip to content

Commit 001062d

Browse files
authored
[TOOLSLIBS-392] Attribute Audience Selectors (#168)
* adds date_attribute audience selector * adds date_attribute tests * missing black formatting * adds text_attribute selector * adds text_attribute tests * adds check for text type * adds number_attribute * adds number attribute * adds nubmer attribute tests * adds proper typing to date_attribute * adds to changelog * rm datetime check
1 parent 2dc79d9 commit 001062d

File tree

7 files changed

+389
-137
lines changed

7 files changed

+389
-137
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- Adds iOS platform options for: interruption_level, relevance_score, and target_content_id
44
- Adds amazon platform options for: notification_tag, notification_channel, icon, icon_color
5+
- Adds audience selectors for date_attribute, text_attribute, and number_attribute
56
- Adds attributes, device_attributes, named_user_id, commercial_opted_in, commercial_opted_out, transactional_opted_in, transactional_opted_out to channel look up and listing.
67
- Adds support for setting attributes on channel ids and named user ids
78
- Adds support for removing attributes from channel ids and named user ids

tests/push/test_audience.py

Lines changed: 159 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import unittest
23

34
import urbanairship as ua
@@ -26,11 +27,7 @@ def test_basic_selectors(self):
2627
"074e84a2-9ed9-4eee-9ca4-cc597bfdbef3",
2728
{"open_channel": "074e84a2-9ed9-4eee-9ca4-cc597bfdbef3"},
2829
),
29-
(
30-
ua.device_token,
31-
"f" * 64,
32-
{"device_token": "F" * 64},
33-
),
30+
(ua.device_token, "f" * 64, {"device_token": "F" * 64}),
3431
(ua.device_token, "0" * 64, {"device_token": "0" * 64}),
3532
(
3633
ua.apid,
@@ -118,3 +115,160 @@ def test_location_selector(self):
118115
self.assertRaises(ValueError, ua.location)
119116
self.assertRaises(ValueError, ua.location, alias=1, id=1)
120117
self.assertRaises(ValueError, ua.location, date=None, id="foobar")
118+
119+
120+
class TestAttributeSelectors(unittest.TestCase):
121+
def test_date_incorrect_operator_raises(self):
122+
with self.assertRaises(ValueError) as err_ctx:
123+
ua.date_attribute(attribute="test_attribute", operator="the_way_we_wont")
124+
125+
self.assertEqual(
126+
err_ctx.message,
127+
"operator must be one of: 'is_empty', 'before', 'after', 'range', 'equals'",
128+
)
129+
130+
def test_date_is_empty(self):
131+
selector = ua.date_attribute(attribute="test_attribute", operator="is_empty")
132+
133+
self.assertEqual(
134+
selector, {"attribute": "test_attribute", "operator": "is_empty"}
135+
)
136+
137+
# testing exception raising only on before. after and equals use same codepath
138+
def test_date_before_no_value_raises(self):
139+
with self.assertRaises(ValueError) as err_ctx:
140+
ua.date_attribute(
141+
attribute="test_attribute", operator="before", precision="years"
142+
)
143+
144+
self.assertEqual(
145+
err_ctx.message,
146+
"value must be included when using the 'before' operator",
147+
)
148+
149+
def test_date_before_no_precision_raises(self):
150+
with self.assertRaises(ValueError) as err_ctx:
151+
ua.date_attribute(
152+
attribute="test_attribute",
153+
operator="before",
154+
value="2021-11-03 12:00:00",
155+
)
156+
157+
self.assertEqual(
158+
err_ctx.message,
159+
"precision must be included when using the 'before' operator",
160+
)
161+
162+
def test_date_before(self):
163+
selector = ua.date_attribute(
164+
attribute="test_attribute",
165+
operator="before",
166+
value="2021-11-03 12:00:00",
167+
precision="years",
168+
)
169+
170+
self.assertEqual(
171+
selector,
172+
{
173+
"attribute": "test_attribute",
174+
"operator": "before",
175+
"value": "2021-11-03 12:00:00",
176+
"precision": "years",
177+
},
178+
)
179+
180+
def test_date_after(self):
181+
selector = ua.date_attribute(
182+
attribute="test_attribute",
183+
operator="after",
184+
value="2021-11-03 12:00:00",
185+
precision="years",
186+
)
187+
188+
self.assertEqual(
189+
selector,
190+
{
191+
"attribute": "test_attribute",
192+
"operator": "after",
193+
"value": "2021-11-03 12:00:00",
194+
"precision": "years",
195+
},
196+
)
197+
198+
def test_date_equals(self):
199+
selector = ua.date_attribute(
200+
attribute="test_attribute",
201+
operator="equals",
202+
value="2021-11-03 12:00:00",
203+
precision="years",
204+
)
205+
206+
self.assertEqual(
207+
selector,
208+
{
209+
"attribute": "test_attribute",
210+
"operator": "equals",
211+
"value": "2021-11-03 12:00:00",
212+
"precision": "years",
213+
},
214+
)
215+
216+
def test_text(self):
217+
selector = ua.text_attribute(
218+
attribute="test_attribute", operator="equals", value="test_value"
219+
)
220+
221+
self.assertEqual(
222+
selector,
223+
{
224+
"attribute": "test_attribute",
225+
"operator": "equals",
226+
"value": "test_value",
227+
},
228+
)
229+
230+
def test_text_incorrect_operator_raises(self):
231+
with self.assertRaises(ValueError) as err_ctx:
232+
ua.text_attribute(
233+
attribute="test_attribute", operator="am_180", value="test_value"
234+
)
235+
236+
self.assertEqual(
237+
err_ctx.message,
238+
"operator must be one of 'equals', 'contains', 'less', 'greater', 'is_empty'",
239+
)
240+
241+
def test_text_incorrect_value_type_raises(self):
242+
with self.assertRaises(ValueError) as err_ctx:
243+
ua.text_attribute(attribute="test_attribute", operator="am_180", value=2001)
244+
245+
self.assertEqual(err_ctx.message, "value must be a string")
246+
247+
def test_number(self):
248+
selector = ua.number_attribute(
249+
attribute="test_attribute", operator="equals", value=100
250+
)
251+
252+
self.assertEqual(
253+
selector,
254+
{"attribute": "test_attribute", "operator": "equals", "value": 100},
255+
)
256+
257+
def test_number_incorrect_operator_raises(self):
258+
with self.assertRaises(ValueError) as err_ctx:
259+
ua.number_attribute(
260+
attribute="test_attribute", operator="am_180", value="test_value"
261+
)
262+
263+
self.assertEqual(
264+
err_ctx.message,
265+
"operator must be one of 'equals', 'contains', 'less', 'greater', 'is_empty'",
266+
)
267+
268+
def test_number_incorrect_value_type_raises(self):
269+
with self.assertRaises(ValueError) as err_ctx:
270+
ua.number_attribute(
271+
attribute="test_attribute", operator="equals", value="ive_got_it"
272+
)
273+
274+
self.assertEqual(err_ctx.message, "value must be an integer")

tests/push/test_push.py

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import mock
66
import requests
7-
87
import urbanairship as ua
98
from tests import TEST_KEY, TEST_SECRET
109

@@ -350,10 +349,7 @@ def test_sms_overrides(self):
350349
p.audience = ua.all_
351350
p.notification = ua.notification(
352351
alert="top level alert",
353-
sms=ua.sms(
354-
alert="sms override alert",
355-
expiry="2018-04-01T12:00:00",
356-
),
352+
sms=ua.sms(alert="sms override alert", expiry="2018-04-01T12:00:00"),
357353
)
358354
p.device_types = ua.device_types("sms")
359355

@@ -459,10 +455,7 @@ def test_standard_ios_opts(self):
459455
p.audience = ua.all_
460456
p.notification = ua.notification(
461457
alert="Top level alert",
462-
ios=ua.ios(
463-
alert="iOS override alert",
464-
sound="cat.caf",
465-
),
458+
ios=ua.ios(alert="iOS override alert", sound="cat.caf"),
466459
)
467460
p.device_types = ua.device_types("ios")
468461

@@ -539,7 +532,7 @@ def test_ios_overrides(self):
539532
"collapse_id": "nugent sand",
540533
"interruption_level": "critical",
541534
"relevance_score": 0.75,
542-
"target_content_id": "big day coming"
535+
"target_content_id": "big day coming",
543536
}
544537
},
545538
"device_types": "ios",
@@ -1011,18 +1004,15 @@ def test_amazon_overrides(self):
10111004
"icon": "icon.img",
10121005
"icon_color": "#1234ff",
10131006
}
1014-
}
1015-
}
1007+
},
1008+
},
10161009
)
10171010

10181011
def test_standard_amazon_push(self):
10191012
p = ua.Push(None)
10201013
p.audience = ua.all_
10211014
p.notification = ua.notification(
1022-
alert="top level alert",
1023-
amazon=ua.amazon(
1024-
alert="amazon override alert"
1025-
)
1015+
alert="top level alert", amazon=ua.amazon(alert="amazon override alert")
10261016
)
10271017
p.device_types = ua.device_types("amazon")
10281018

@@ -1033,9 +1023,7 @@ def test_standard_amazon_push(self):
10331023
"device_types": ["amazon"],
10341024
"notification": {
10351025
"alert": "top level alert",
1036-
"amazon": {
1037-
"alert": "amazon override alert"
1038-
}
1039-
}
1040-
}
1041-
)
1026+
"amazon": {"alert": "amazon override alert"},
1027+
},
1028+
},
1029+
)

0 commit comments

Comments
 (0)