Skip to content

Commit 9b84d83

Browse files
Merge pull request #3 from pusher/interests
Interests
2 parents 4b0bf54 + 455d72c commit 9b84d83

File tree

2 files changed

+123
-62
lines changed

2 files changed

+123
-62
lines changed

pusher_push_notifications/__init__.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,32 @@
88

99
SDK_VERSION = '0.9.2'
1010
INTEREST_MAX_LENGTH = 164
11-
INTEREST_REGEX = re.compile('^(_-|=|@|,|\\.|:|[A-Z]|[a-z]|[0-9])*$')
11+
INTEREST_REGEX = re.compile('^(_|-|=|@|,|\\.|:|[A-Z]|[a-z]|[0-9])*$')
12+
MAX_NUMBER_OF_INTERESTS = 100
1213

1314

1415
class PusherValidationError(ValueError):
1516
"""Error thrown when the Push Notifications publish body is invalid"""
1617
pass
1718

19+
1820
class PusherAuthError(ValueError):
1921
"""Error thrown when the Push Notifications secret key is incorrect"""
2022
pass
2123

24+
2225
class PusherMissingInstanceError(KeyError):
2326
"""Error thrown when the instance id used does not exist"""
2427
pass
2528

29+
2630
class PusherServerError(Exception):
2731
"""Error thrown when the Push Notifications service has an internal server
2832
error
2933
"""
3034
pass
3135

36+
3237
def handle_http_error(response_body, status_code):
3338
"""Handle different http error codes from the Push Notifications service"""
3439
error_string = '{}: {}'.format(
@@ -96,6 +101,7 @@ def publish(self, interests, publish_body):
96101
TypeError: if publish_body is not a dict
97102
TypeError: if any interest is not a string
98103
ValueError: if len(interests) < 1
104+
ValueError: if len(interests) > 100
99105
ValueError: if any interest length is greater than the max
100106
ValueError: if any interest contains a forbidden character
101107
@@ -106,7 +112,11 @@ def publish(self, interests, publish_body):
106112
raise TypeError('publish_body must be a dictionary')
107113
if not interests:
108114
raise ValueError('Publishes must target at least one interest')
109-
115+
if len(interests) > MAX_NUMBER_OF_INTERESTS:
116+
raise ValueError('Number of interests ({}) exceeds maximum of {}'.format(
117+
len(interests),
118+
MAX_NUMBER_OF_INTERESTS
119+
))
110120
for interest in interests:
111121
if not isinstance(interest, six.string_types):
112122
raise TypeError(
@@ -125,7 +135,7 @@ def publish(self, interests, publish_body):
125135
interest,
126136
)
127137
+ 'Allowed characters are: ASCII upper/lower-case letters, '
128-
+ 'numbers or one of _=@,.:'
138+
+ 'numbers or one of _=@,.:-'
129139
)
130140

131141
publish_body['interests'] = interests

tests/test_push_notifications.py

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

55
import requests_mock
66

7+
78
from pusher_push_notifications import (
89
PushNotifications,
910
PusherAuthError,
@@ -130,22 +131,21 @@ def test_publish_should_make_correct_http_request(self):
130131
},
131132
)
132133

133-
134134
def test_publish_should_fail_if_interests_not_list(self):
135135
pn_client = PushNotifications(
136136
'INSTANCE_ID',
137137
'SECRET_KEY'
138138
)
139139
with self.assertRaises(TypeError):
140140
pn_client.publish(
141-
interests=False,
142-
publish_body={
143-
'apns': {
144-
'aps': {
145-
'alert': 'Hello World!',
146-
},
141+
interests=False,
142+
publish_body={
143+
'apns': {
144+
'aps': {
145+
'alert': 'Hello World!',
147146
},
148147
},
148+
},
149149
)
150150

151151
def test_publish_should_fail_if_body_not_dict(self):
@@ -155,8 +155,8 @@ def test_publish_should_fail_if_body_not_dict(self):
155155
)
156156
with self.assertRaises(TypeError):
157157
pn_client.publish(
158-
interests=['donuts'],
159-
publish_body=False,
158+
interests=['donuts'],
159+
publish_body=False,
160160
)
161161

162162
def test_publish_should_fail_if_no_interests_passed(self):
@@ -166,15 +166,66 @@ def test_publish_should_fail_if_no_interests_passed(self):
166166
)
167167
with self.assertRaises(ValueError):
168168
pn_client.publish(
169-
interests=[],
169+
interests=[],
170+
publish_body={
171+
'apns': {
172+
'aps': {
173+
'alert': 'Hello World!',
174+
},
175+
},
176+
},
177+
)
178+
179+
def test_publish_should_succeed_if_100_interests_passed(self):
180+
pn_client = PushNotifications(
181+
'INSTANCE_ID',
182+
'SECRET_KEY'
183+
)
184+
with requests_mock.Mocker() as http_mock:
185+
http_mock.register_uri(
186+
requests_mock.ANY,
187+
requests_mock.ANY,
188+
status_code=200,
189+
json={
190+
'publishId': '1234',
191+
},
192+
)
193+
pn_client.publish(
194+
interests=['interest-' + str(i) for i in range(0, 100)],
195+
publish_body={
196+
'apns': {
197+
'aps': {
198+
'alert': 'Hello World!',
199+
},
200+
},
201+
},
202+
)
203+
204+
def test_publish_should_fail_if_too_many_interests_passed(self):
205+
pn_client = PushNotifications(
206+
'INSTANCE_ID',
207+
'SECRET_KEY'
208+
)
209+
with requests_mock.Mocker() as http_mock:
210+
http_mock.register_uri(
211+
requests_mock.ANY,
212+
requests_mock.ANY,
213+
status_code=200,
214+
json={
215+
'publishId': '1234',
216+
},
217+
)
218+
with self.assertRaises(ValueError):
219+
pn_client.publish(
220+
interests=['interest-' + str(i) for i in range(0, 101)],
170221
publish_body={
171222
'apns': {
172223
'aps': {
173224
'alert': 'Hello World!',
174225
},
175226
},
176227
},
177-
)
228+
)
178229

179230
def test_publish_should_fail_if_interest_not_a_string(self):
180231
pn_client = PushNotifications(
@@ -183,14 +234,14 @@ def test_publish_should_fail_if_interest_not_a_string(self):
183234
)
184235
with self.assertRaises(TypeError):
185236
pn_client.publish(
186-
interests=[False],
187-
publish_body={
188-
'apns': {
189-
'aps': {
190-
'alert': 'Hello World!',
191-
},
237+
interests=[False],
238+
publish_body={
239+
'apns': {
240+
'aps': {
241+
'alert': 'Hello World!',
192242
},
193243
},
244+
},
194245
)
195246

196247
def test_publish_should_fail_if_interest_too_long(self):
@@ -200,14 +251,14 @@ def test_publish_should_fail_if_interest_too_long(self):
200251
)
201252
with self.assertRaises(ValueError):
202253
pn_client.publish(
203-
interests=['A'*200],
204-
publish_body={
205-
'apns': {
206-
'aps': {
207-
'alert': 'Hello World!',
208-
},
254+
interests=['A'*200],
255+
publish_body={
256+
'apns': {
257+
'aps': {
258+
'alert': 'Hello World!',
209259
},
210260
},
261+
},
211262
)
212263

213264
def test_publish_should_fail_if_interest_contains_invalid_chars(self):
@@ -217,25 +268,25 @@ def test_publish_should_fail_if_interest_contains_invalid_chars(self):
217268
)
218269
with self.assertRaises(ValueError):
219270
pn_client.publish(
220-
interests=['bad|interest'],
221-
publish_body={
222-
'apns': {
223-
'aps': {
224-
'alert': 'Hello World!',
225-
},
271+
interests=['bad|interest'],
272+
publish_body={
273+
'apns': {
274+
'aps': {
275+
'alert': 'Hello World!',
226276
},
227277
},
278+
},
228279
)
229280
with self.assertRaises(ValueError):
230281
pn_client.publish(
231-
interests=['bad(interest)'],
232-
publish_body={
233-
'apns': {
234-
'aps': {
235-
'alert': 'Hello World!',
236-
},
282+
interests=['bad(interest)'],
283+
publish_body={
284+
'apns': {
285+
'aps': {
286+
'alert': 'Hello World!',
237287
},
238288
},
289+
},
239290
)
240291

241292
def test_publish_should_raise_on_http_4xx_error(self):
@@ -252,14 +303,14 @@ def test_publish_should_raise_on_http_4xx_error(self):
252303
)
253304
with self.assertRaises(PusherValidationError):
254305
pn_client.publish(
255-
interests=['donuts'],
256-
publish_body={
257-
'apns': {
258-
'aps': {
259-
'alert': 'Hello World!',
260-
},
306+
interests=['donuts'],
307+
publish_body={
308+
'apns': {
309+
'aps': {
310+
'alert': 'Hello World!',
261311
},
262312
},
313+
},
263314
)
264315

265316
def test_publish_should_raise_on_http_5xx_error(self):
@@ -276,14 +327,14 @@ def test_publish_should_raise_on_http_5xx_error(self):
276327
)
277328
with self.assertRaises(PusherServerError):
278329
pn_client.publish(
279-
interests=['donuts'],
280-
publish_body={
281-
'apns': {
282-
'aps': {
283-
'alert': 'Hello World!',
284-
},
330+
interests=['donuts'],
331+
publish_body={
332+
'apns': {
333+
'aps': {
334+
'alert': 'Hello World!',
285335
},
286336
},
337+
},
287338
)
288339

289340
def test_publish_should_raise_on_http_401_error(self):
@@ -300,14 +351,14 @@ def test_publish_should_raise_on_http_401_error(self):
300351
)
301352
with self.assertRaises(PusherAuthError):
302353
pn_client.publish(
303-
interests=['donuts'],
304-
publish_body={
305-
'apns': {
306-
'aps': {
307-
'alert': 'Hello World!',
308-
},
354+
interests=['donuts'],
355+
publish_body={
356+
'apns': {
357+
'aps': {
358+
'alert': 'Hello World!',
309359
},
310360
},
361+
},
311362
)
312363

313364
def test_publish_should_raise_on_http_404_error(self):
@@ -324,12 +375,12 @@ def test_publish_should_raise_on_http_404_error(self):
324375
)
325376
with self.assertRaises(PusherMissingInstanceError):
326377
pn_client.publish(
327-
interests=['donuts'],
328-
publish_body={
329-
'apns': {
330-
'aps': {
331-
'alert': 'Hello World!',
332-
},
378+
interests=['donuts'],
379+
publish_body={
380+
'apns': {
381+
'aps': {
382+
'alert': 'Hello World!',
333383
},
334384
},
385+
},
335386
)

0 commit comments

Comments
 (0)