Skip to content

Commit 861de5e

Browse files
committed
Testing
1 parent bfe76dd commit 861de5e

File tree

3 files changed

+203
-11
lines changed

3 files changed

+203
-11
lines changed

pusher/notification_client.py

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
from .config import Config
22
from .http import POST, Request, request_method
3+
from .util import ensure_text
34

45
DEFAULT_HOST = "yolo.ngrok.io"
56
RESTRICTED_GCM_KEYS = ['to', 'registration_ids']
6-
API_PREFIX = '/customer_api'
7-
API_VERSION = '/v1'
7+
API_PREFIX = 'customer_api'
8+
API_VERSION = 'v1'
89
GCM_TTL = 241920
910
WEBHOOK_LEVELS = ['INFO', 'DEBUG', '']
1011

1112
class NotificationClient(Config):
1213

1314
def __init__(self, app_id, key, secret, ssl=True, host=None, port=None, timeout=5, cluster=None,
14-
json_encoder=None, json_decoder=None, backend=None, **backend_options):
15+
json_encoder=None, json_decoder=None, backend=None, **backend_options):
1516

1617
super(NotificationClient, self).__init__(
1718
app_id, key, secret, ssl,
1819
host, port, timeout, cluster,
19-
json_encoder, json_decoder, backend,
20-
**backend_options)
20+
json_encoder, json_decoder, backend,
21+
**backend_options)
2122

2223
if host:
2324
self._host = ensure_text(host, "host")
@@ -30,15 +31,19 @@ def notify(self, interests, notification):
3031
if not isinstance(interests, list) and not isinstance(interests, set):
3132
raise TypeError("Interests must be a list or a set")
3233

34+
if len(interests) is not 1:
35+
raise ValueError("Currently sending to more than one interest is unsupported")
36+
3337
if not isinstance(notification, dict):
3438
raise TypeError("Notification must be a dictionary")
3539

3640
params = {
37-
'interests': interests,
41+
'interests': interests,
3842
}
3943
params.update(notification)
4044
self.validate_notification(params)
41-
return Request(self, POST, "/customer_api/v1/apps/%s/notifications" % self.app_id, params)
45+
path = "/%s/%s/apps/%s/notifications" % (API_PREFIX, API_VERSION, self.app_id)
46+
return Request(self, POST, path, params)
4247

4348
def validate_notification(self, notification):
4449
gcm_payload = notification.get('gcm')
@@ -78,8 +83,8 @@ def validate_notification(self, notification):
7883
webhook_level = notification.get('webhook_level')
7984

8085
if webhook_level:
81-
if not webhook_url:
86+
if not webhook_url:
8287
raise ValueError("webhook_level cannot be used without a webhook_url")
8388

84-
if not webhook_level in WEBHOOK_LEVELS:
89+
if not webhook_level in WEBHOOK_LEVELS:
8590
raise ValueError("webhook_level must be either INFO or DEBUG. Blank will default to INFO")

pusher/pusher.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ def validate_webhook(self, key, signature, body):
269269
def notification_client(self):
270270
return self._notification_client
271271

272-
def notify(self, interests, notification):
273-
self._notification_client.notify(interests, notification)
272+
def notify(self, interest, notification):
273+
self._notification_client.notify(interest, notification)
274274

275275
def _data_to_string(self, data):
276276
if isinstance(data, six.string_types):
+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import unittest
4+
from pusher.notification_client import NotificationClient
5+
6+
class TestNotificationClient(unittest.TestCase):
7+
def setUp(self):
8+
self.client = NotificationClient(app_id='4', key='key', secret='secret')
9+
self.success_fixture = {
10+
'webhook_url': 'http://webhook.com',
11+
'webhook_level': 'DEBUG',
12+
'apns': {
13+
'alert': {
14+
'title': 'yolo',
15+
'body': 'woot'
16+
}
17+
},
18+
'gcm': {
19+
'notification': {
20+
'title': 'yipee',
21+
'icon': 'huh'
22+
}
23+
}
24+
}
25+
26+
def test_notify_success_case(self):
27+
request = self.client.notify.make_request(['yolo'], self.success_fixture)
28+
self.assertEqual(request.method, u'POST')
29+
self.assertEqual(request.base_url, u'https://yolo.ngrok.io:443')
30+
self.assertEqual(request.path, '/customer_api/v1/apps/4/notifications')
31+
self.assertEqual(request.params, {
32+
'interests': ['yolo'],
33+
'webhook_url': 'http://webhook.com',
34+
'webhook_level': 'DEBUG',
35+
'apns': {
36+
'alert': {
37+
'title': 'yolo',
38+
'body': 'woot'
39+
}
40+
},
41+
'gcm': {
42+
'notification': {
43+
'title': 'yipee',
44+
'icon': 'huh'
45+
}
46+
}
47+
})
48+
49+
def test_notify_supplied_ssl_and_host(self):
50+
configured_client = NotificationClient(app_id='6', key='woo', secret='shhh', ssl=False, host='foo.bar.io')
51+
request = configured_client.notify.make_request([u'blargh'], self.success_fixture)
52+
self.assertEqual(request.base_url, u'http://foo.bar.io:80')
53+
54+
def test_either_apns_or_gcm_must_be_present(self):
55+
self.assertRaises(ValueError, lambda:
56+
self.client.notify([u'yolo'], {})
57+
)
58+
59+
def test_only_one_interest_sent_to(self):
60+
self.assertRaises(ValueError, lambda: self.client.notify([u'yolo', u'woot'], self.success_fixture))
61+
62+
def test_gcm_restricted_keys_removed(self):
63+
request = self.client.notify.make_request(['yolo'], {
64+
'gcm': {
65+
'to': 'woot',
66+
'registration_ids': ['woot', 'bla'],
67+
'notification': {
68+
'title': 'yipee',
69+
'icon': 'huh'
70+
}
71+
}
72+
})
73+
self.assertEqual(request.params, {
74+
'interests': ['yolo'],
75+
'gcm': {
76+
'notification': {
77+
'title': 'yipee',
78+
'icon': 'huh'
79+
}
80+
}
81+
})
82+
83+
def test_gcm_validations(self):
84+
invalid_gcm_payloads = [
85+
{
86+
'gcm': {
87+
'time_to_live': -1,
88+
'notification': {
89+
'title': 'yipee',
90+
'icon': 'huh'
91+
}
92+
}
93+
},
94+
{
95+
'gcm': {
96+
'time_to_live': 241921,
97+
'notification': {
98+
'title': 'yipee',
99+
'icon': 'huh'
100+
}
101+
}
102+
},
103+
{
104+
'gcm': {
105+
'notification': {
106+
'title': 'yipee',
107+
}
108+
}
109+
},
110+
{
111+
'gcm': {
112+
'notification': {
113+
'icon': 'huh'
114+
}
115+
}
116+
},
117+
{
118+
'gcm': {
119+
'notification': {
120+
'title': '',
121+
'icon': 'huh'
122+
}
123+
}
124+
},
125+
{
126+
'gcm': {
127+
'notification': {
128+
'title': 'yipee',
129+
'icon': ''
130+
}
131+
}
132+
}
133+
]
134+
135+
for payload in invalid_gcm_payloads:
136+
self.assertRaises(ValueError, lambda:
137+
self.client.notify([u'yolo'], payload)
138+
)
139+
140+
valid_gcm_payload = \
141+
{
142+
'gcm': {
143+
'time_to_live': 42,
144+
'notification': {
145+
'title': 'yipee',
146+
'icon': 'huh'
147+
}
148+
}
149+
}
150+
self.client.notify.make_request([u'yolo'], valid_gcm_payload)
151+
152+
def test_webhook_level_validation(self):
153+
invalid_webhook_configs = [
154+
{
155+
'webhook_level': 'DEBUG',
156+
'apns': {
157+
'alert': {
158+
'title': 'yolo',
159+
'body': 'woot'
160+
}
161+
},
162+
'gcm': {
163+
'notification': {
164+
'title': 'yipee',
165+
'icon': 'huh'
166+
}
167+
}
168+
},
169+
{
170+
'webhook_level': 'FOOBAR',
171+
'webhook_url': 'http://webhook.com',
172+
'apns': {
173+
'alert': {
174+
'title': 'yolo',
175+
'body': 'woot'
176+
}
177+
},
178+
'gcm': {
179+
'notification': {
180+
'title': 'yipee',
181+
'icon': 'huh'
182+
}
183+
}
184+
}]
185+
186+
for config in invalid_webhook_configs:
187+
self.assertRaises(ValueError, lambda: self.client.notify.make_request([u'yolo'], config))

0 commit comments

Comments
 (0)