-
Notifications
You must be signed in to change notification settings - Fork 2k
/
test_email_notifications.py
484 lines (385 loc) · 19.7 KB
/
test_email_notifications.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
import time
import ckan.model as model
import ckan.lib.base
import ckan.lib.mailer
import ckan.tests as tests
import ckan.tests.mock_mail_server as mock_mail_server
import ckan.tests.pylons_controller as pylons_controller
import ckan.config.middleware
import paste
import paste.deploy
import pylons.test
class TestEmailNotifications(mock_mail_server.SmtpServerHarness,
pylons_controller.PylonsTestCase):
@classmethod
def setup_class(cls):
mock_mail_server.SmtpServerHarness.setup_class()
pylons_controller.PylonsTestCase.setup_class()
tests.CreateTestData.create()
cls.app = paste.fixture.TestApp(pylons.test.pylonsapp)
joeadmin = model.User.get('joeadmin')
cls.joeadmin = {'id': joeadmin.id,
'apikey': joeadmin.apikey,
}
testsysadmin = model.User.get('testsysadmin')
cls.testsysadmin = {'id': testsysadmin.id,
'apikey': testsysadmin.apikey,
}
annafan = model.User.get('annafan')
cls.annafan = {'id': annafan.id,
'apikey': annafan.apikey,
}
@classmethod
def teardown_class(self):
mock_mail_server.SmtpServerHarness.teardown_class()
pylons_controller.PylonsTestCase.teardown_class()
model.repo.rebuild_db()
def check_email(self, email, address, name, subject):
assert email[1] == 'info@test.ckan.net'
assert email[2] == [address]
encoded_subject = 'Subject: =?utf-8?q?{subject}'.format(
subject=subject.replace(' ', '_'))
assert encoded_subject in email[3]
# TODO: Check that body contains link to dashboard and email prefs.
def test_00_send_email_notifications_not_logged_in(self):
'''Not-logged-in users shouldn't be able to send email notifications.
'''
tests.call_action_api(self.app, 'send_email_notifications',
status=403)
def test_00_send_email_notifications_not_authorized(self):
'''Unauthorized users shouldn't be able to send email notifications.
'''
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.annafan['apikey'], status=403)
def test_01_no_email_notifications_after_registration(self):
'''A new user who isn't following anything shouldn't get any emails.'''
# Clear any emails already sent due to CreateTestData.create().
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
self.clear_smtp_messages()
# Register a new user.
sara = tests.call_action_api(self.app, 'user_create',
apikey=self.testsysadmin['apikey'], name='sara',
email='sara@sararollins.com', password='sara',
fullname='Sara Rollins',
activity_streams_email_notifications=True)
# Save the user for later tests to use.
TestEmailNotifications.sara = sara
# No notification emails should be sent to anyone at this point.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
def test_02_one_new_activity(self):
'''A user with one new activity should get one email.'''
# Make Sara follow something, have to do this to get new activity.
tests.call_action_api(self.app, 'follow_dataset',
apikey=self.sara['apikey'], id='warandpeace')
# Make someone else update the dataset Sara's following, this should
# create a new activity on Sara's dashboard.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], name='warandpeace',
notes='updated')
# Run the email notifier job, it should send one notification email
# to Sara.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 1
email = self.get_smtp_messages()[0]
self.check_email(email, 'sara@sararollins.com', 'Sara Rollins',
'New activity from CKAN')
self.clear_smtp_messages()
def test_03_multiple_new_activities(self):
'''Test that a user with multiple new activities gets just one email.
'''
# Make someone else update the dataset Sara's following three times,
# this should create three new activities on Sara's dashboard.
for i in range(1, 4):
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], name='warandpeace',
notes='updated {0} times'.format(i))
# Run the email notifier job, it should send one notification email
# to Sara.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 1
email = self.get_smtp_messages()[0]
self.check_email(email, 'sara@sararollins.com', 'Sara Rollins',
'New activity from CKAN')
self.clear_smtp_messages()
def test_04_no_repeat_email_notifications(self):
'''Test that a user does not get a second email notification for the
same new activity.
'''
# TODO: Assert that Sara has some new activities and has already had
# an email about them.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
def test_05_no_email_if_seen_on_dashboard(self):
'''Test that emails are not sent for activities already seen on dash.
If a user gets some new activities in her dashboard activity stream,
then views her dashboard activity stream, then she should not got any
email notifications about these new activities.
'''
# Make someone else update the dataset Sara's following, this should
# create a new activity on Sara's dashboard.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], name='warandpeace',
notes='updated by test_05_no_email_if_seen_on_dashboard')
# At this point Sara should have a new activity on her dashboard.
num_new_activities = tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey'])
assert num_new_activities > 0, num_new_activities
# View Sara's dashboard.
tests.call_action_api(self.app, 'dashboard_mark_activities_old',
apikey=self.sara['apikey'])
# No email should be sent.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
def test_05_no_email_notifications_when_disabled_site_wide(self):
'''Users should not get email notifications when the feature is
disabled site-wide by a sysadmin.'''
def test_06_enable_email_notifications_sitewide(self):
'''When a sysadamin enables email notifications site wide, users
should not get emails for new activities from before email
notifications were enabled.
'''
# It's just easier to separate these tests into their own test class.
class TestEmailNotificationsUserPreference(
mock_mail_server.SmtpServerHarness,
pylons_controller.PylonsTestCase):
'''Tests for the email notifications (on/off) user preference.'''
@classmethod
def setup_class(cls):
mock_mail_server.SmtpServerHarness.setup_class()
pylons_controller.PylonsTestCase.setup_class()
tests.CreateTestData.create()
cls.app = paste.fixture.TestApp(pylons.test.pylonsapp)
joeadmin = model.User.get('joeadmin')
cls.joeadmin = {'id': joeadmin.id,
'apikey': joeadmin.apikey,
}
testsysadmin = model.User.get('testsysadmin')
cls.testsysadmin = {'id': testsysadmin.id,
'apikey': testsysadmin.apikey,
}
@classmethod
def teardown_class(self):
mock_mail_server.SmtpServerHarness.teardown_class()
pylons_controller.PylonsTestCase.teardown_class()
model.repo.rebuild_db()
def test_00_email_notifications_disabled_by_default(self):
'''Email notifications should be disabled for new users.'''
# Register a new user.
sara = tests.call_action_api(self.app, 'user_create',
apikey=self.testsysadmin['apikey'], name='sara',
email='sara@sararollins.com', password='sara',
fullname='Sara Rollins')
# Save the user for later tests to use.
TestEmailNotificationsUserPreference.sara = sara
# Email notifications should be disabled for the new user.
assert sara['activity_streams_email_notifications'] is False
assert (tests.call_action_api(self.app, 'user_show',
apikey=self.sara['apikey'], id='sara')[
'activity_streams_email_notifications'] is False)
def test_01_no_email_notifications_when_disabled(self):
'''Users with email notifications turned off should not get emails.'''
# First make Sara follow something so she gets some new activity in
# her dashboard activity stream.
tests.call_action_api(self.app, 'follow_dataset',
apikey=self.sara['apikey'], id='warandpeace')
# Now make someone else update the dataset so Sara gets a new activity.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated')
# Test that Sara has a new activity, just to make sure.
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
# No email notifications should be sent to Sara.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
def test_02_enable_email_notifications(self):
'''Users should be able to turn email notifications on.'''
# Mark all Sara's new activities as old, just to get a fresh start.
tests.call_action_api(self.app, 'dashboard_mark_activities_old',
apikey=self.sara['apikey'])
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) == 0
# Update the followed dataset a few times so Sara gets a few new
# activities.
for i in range(1, 4):
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated {0} times'.format(i))
# Now Sara should have new activities.
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) == 3
# Run the email notifier job.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
# Enable email notifications for Sara.
self.sara['activity_streams_email_notifications'] = True
tests.call_action_api(self.app, 'user_update', **self.sara)
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0, ("After a user enables "
"email notifications she should _not_ get emails about activities "
"that happened before she enabled them, even if those activities "
"are still marked as 'new' on her dashboard.")
# Update the package to generate another new activity.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated yet again')
# Check that Sara has a new activity.
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) == 4
# Run the email notifier job, this time Sara should get one email.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 1
self.clear_smtp_messages()
def test_03_disable_email_notifications(self):
'''Users should be able to turn email notifications off.'''
self.sara['activity_streams_email_notifications'] = False
tests.call_action_api(self.app, 'user_update', **self.sara)
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated yet again')
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0
class TestEmailNotificationsIniSetting(
mock_mail_server.SmtpServerHarness,
pylons_controller.PylonsTestCase):
'''Tests for the ckan.activity_streams_email_notifications config setting.
'''
@classmethod
def setup_class(cls):
config = paste.deploy.appconfig('config:test.ini',
relative_to=ckan.tests.conf_dir)
# Disable the email notifications feature.
config.local_conf['ckan.activity_streams_email_notifications'] = False
wsgiapp = ckan.config.middleware.make_app(config.global_conf,
**config.local_conf)
cls.app = paste.fixture.TestApp(wsgiapp)
mock_mail_server.SmtpServerHarness.setup_class()
pylons_controller.PylonsTestCase.setup_class()
tests.CreateTestData.create()
joeadmin = model.User.get('joeadmin')
cls.joeadmin = {'id': joeadmin.id,
'apikey': joeadmin.apikey,
}
testsysadmin = model.User.get('testsysadmin')
cls.testsysadmin = {'id': testsysadmin.id,
'apikey': testsysadmin.apikey,
}
@classmethod
def teardown_class(self):
mock_mail_server.SmtpServerHarness.teardown_class()
pylons_controller.PylonsTestCase.teardown_class()
model.repo.rebuild_db()
def test_00_send_email_notifications_feature_disabled(self):
'''Send_email_notifications API should error when feature disabled.'''
# Register a new user.
sara = tests.call_action_api(self.app, 'user_create',
apikey=self.testsysadmin['apikey'], name='sara',
email='sara@sararollins.com', password='sara',
fullname='Sara Rollins')
# Save the user for later tests to use.
TestEmailNotificationsIniSetting.sara = sara
# Enable the new user's email notifications preference.
sara['activity_streams_email_notifications'] = True
tests.call_action_api(self.app, 'user_update', **sara)
assert (tests.call_action_api(self.app, 'user_show',
apikey=self.sara['apikey'], id='sara')[
'activity_streams_email_notifications']
is True)
# Make Sara follow something so she gets some new activity in her
# dashboard activity stream.
tests.call_action_api(self.app, 'follow_dataset',
apikey=self.sara['apikey'], id='warandpeace')
# Now make someone else update the dataset so Sara gets a new activity.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated')
# Test that Sara has a new activity, just to make sure.
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
# We expect an error when trying to call the send_email_notifications
# API, because the feature is disabled by the ini file setting.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'], status=409)
def test_01_no_emails_sent_if_turned_off(self):
'''No emails should be sent if the feature is disabled site-wide.'''
# No emails should have been sent by the last test.
assert len(self.get_smtp_messages()) == 0
class TestEmailNotificationsSinceIniSetting(
mock_mail_server.SmtpServerHarness,
pylons_controller.PylonsTestCase):
'''Tests for the ckan.email_notifications_since config setting.'''
@classmethod
def setup_class(cls):
config = paste.deploy.appconfig('config:test.ini',
relative_to=ckan.tests.conf_dir)
# Don't send email notifications for activities older than 1
# microsecond.
config.local_conf['ckan.email_notifications_since'] = '.000001'
wsgiapp = ckan.config.middleware.make_app(config.global_conf,
**config.local_conf)
cls.app = paste.fixture.TestApp(wsgiapp)
mock_mail_server.SmtpServerHarness.setup_class()
pylons_controller.PylonsTestCase.setup_class()
tests.CreateTestData.create()
joeadmin = model.User.get('joeadmin')
cls.joeadmin = {'id': joeadmin.id,
'apikey': joeadmin.apikey,
}
testsysadmin = model.User.get('testsysadmin')
cls.testsysadmin = {'id': testsysadmin.id,
'apikey': testsysadmin.apikey,
}
@classmethod
def teardown_class(self):
mock_mail_server.SmtpServerHarness.teardown_class()
pylons_controller.PylonsTestCase.teardown_class()
model.repo.rebuild_db()
def test_00_email_notifications_since(self):
'''No emails should be sent for activities older than
email_notifications_since.
'''
# Register a new user.
sara = tests.call_action_api(self.app, 'user_create',
apikey=self.testsysadmin['apikey'], name='sara',
email='sara@sararollins.com', password='sara',
fullname='Sara Rollins')
# Save the user for later tests to use.
TestEmailNotificationsSinceIniSetting.sara = sara
# Enable the new user's email notifications preference.
sara['activity_streams_email_notifications'] = True
tests.call_action_api(self.app, 'user_update', **sara)
assert (tests.call_action_api(self.app, 'user_show',
apikey=self.sara['apikey'], id='sara')[
'activity_streams_email_notifications']
is True)
# Make Sara follow something so she gets some new activity in her
# dashboard activity stream.
tests.call_action_api(self.app, 'follow_dataset',
apikey=self.sara['apikey'], id='warandpeace')
# Now make someone else update the dataset so Sara gets a new activity.
tests.call_action_api(self.app, 'package_update',
apikey=self.joeadmin['apikey'], id='warandpeace',
notes='updated')
# Test that Sara has a new activity, just to make sure.
assert tests.call_action_api(self.app,
'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
# Wait 1 microsecond, just to make sure we're passed the 'since' time.
time.sleep(0.000001)
# No emails should be sent.
tests.call_action_api(self.app, 'send_email_notifications',
apikey=self.testsysadmin['apikey'])
assert len(self.get_smtp_messages()) == 0