Fix another tests.
[mediagoblin:mediagoblin.git] / mediagoblin / tests / test_notifications.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors.  See AUTHORS.
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import pytest
18
19 import six.moves.urllib.parse as urlparse
20
21 from mediagoblin.tools import template, mail
22
23 from mediagoblin.db.models import Notification, CommentNotification, \
24         CommentSubscription
25 from mediagoblin.db.base import Session
26
27 from mediagoblin.notifications import mark_comment_notification_seen
28
29 from mediagoblin.tests.tools import fixture_add_comment, \
30     fixture_media_entry, fixture_add_user, \
31     fixture_comment_subscription
32
33
34 class TestNotifications:
35     @pytest.fixture(autouse=True)
36     def setup(self, test_app):
37         self.test_app = test_app
38
39         # TODO: Possibly abstract into a decorator like:
40         # @as_authenticated_user('chris')
41         self.test_user = fixture_add_user(privileges=[u'active',u'commenter'])
42
43         self.current_user = None
44
45         self.login()
46
47     def login(self, username=u'chris', password=u'toast'):
48         response = self.test_app.post(
49             '/auth/login/', {
50                 'username': username,
51                 'password': password})
52
53         response.follow()
54
55         assert urlparse.urlsplit(response.location)[2] == '/'
56         assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
57
58         ctx = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
59
60         assert Session.merge(ctx['request'].user).username == username
61
62         self.current_user = ctx['request'].user
63
64     def logout(self):
65         self.test_app.get('/auth/logout/')
66         self.current_user = None
67
68     @pytest.mark.parametrize('wants_email', [True, False])
69     def test_comment_notification(self, wants_email):
70         '''
71         Test
72         - if a notification is created when posting a comment on
73           another users media entry.
74         - that the comment data is consistent and exists.
75
76         '''
77         user = fixture_add_user('otherperson', password='nosreprehto',
78                                 wants_comment_notification=wants_email,
79                                 privileges=[u'active',u'commenter'])
80
81         assert user.wants_comment_notification == wants_email
82
83         user_id = user.id
84
85         media_entry = fixture_media_entry(uploader=user.id, state=u'processed')
86
87         media_entry_id = media_entry.id
88
89         subscription = fixture_comment_subscription(media_entry)
90
91         subscription_id = subscription.id
92
93         media_uri_id = '/u/{0}/m/{1}/'.format(user.username,
94                                               media_entry.id)
95         media_uri_slug = '/u/{0}/m/{1}/'.format(user.username,
96                                                 media_entry.slug)
97
98         self.test_app.post(
99             media_uri_id + 'comment/add/',
100             {
101                 'comment_content': u'Test comment #42'
102             }
103         )
104
105         notifications = Notification.query.filter_by(
106             user_id=user.id).all()
107
108         assert len(notifications) == 1
109
110         notification = notifications[0]
111
112         assert type(notification) == CommentNotification
113         assert notification.seen == False
114         assert notification.user_id == user.id
115         assert notification.subject.get_author.id == self.test_user.id
116         assert notification.subject.content == u'Test comment #42'
117
118         if wants_email == True:
119             assert mail.EMAIL_TEST_MBOX_INBOX == [
120                 {'from': 'notice@mediagoblin.example.org',
121                 'message': 'Content-Type: text/plain; \
122 charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: \
123 base64\nSubject: GNU MediaGoblin - chris commented on your \
124 post\nFrom: notice@mediagoblin.example.org\nTo: \
125 otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyIHBvc3QgKGh0dHA6Ly9sb2Nh\nbGhvc3Q6ODAvdS9vdGhlcnBlcnNvbi9tL3NvbWUtdGl0bGUvYy8xLyNjb21tZW50KSBhdCBHTlUg\nTWVkaWFHb2JsaW4KClRlc3QgY29tbWVudCAjNDIKCkdOVSBNZWRpYUdvYmxpbg==\n',
126                 'to': [u'otherperson@example.com']}]
127         else:
128             assert mail.EMAIL_TEST_MBOX_INBOX == []
129
130
131         # Save the ids temporarily because of DetachedInstanceError
132         notification_id = notification.id
133         comment_id = notification.subject.id
134
135         self.logout()
136         self.login('otherperson', 'nosreprehto')
137
138         self.test_app.get(media_uri_slug + 'c/{0}/'.format(comment_id))
139
140         notification = Notification.query.filter_by(id=notification_id).first()
141
142         assert notification.seen == True
143
144         self.test_app.get(media_uri_slug + 'notifications/silence/')
145
146         subscription = CommentSubscription.query.filter_by(id=subscription_id)\
147                 .first()
148
149         assert subscription.notify == False
150
151         notifications = Notification.query.filter_by(
152             user_id=user_id).all()
153
154         # User should not have been notified
155         assert len(notifications) == 1
156
157     def test_mark_all_comment_notifications_seen(self):
158         """ Test that mark_all_comments_seen works"""
159
160         user = fixture_add_user('otherperson', password='nosreprehto',
161                         privileges=[u'active'])
162
163         media_entry = fixture_media_entry(uploader=user.id, state=u'processed')
164
165         fixture_comment_subscription(media_entry)
166
167         media_uri_id = '/u/{0}/m/{1}/'.format(user.username,
168                                               media_entry.id)
169
170         # add 2 comments
171         self.test_app.post(
172             media_uri_id + 'comment/add/',
173             {
174                 'comment_content': u'Test comment #43'
175             }
176         )
177
178         self.test_app.post(
179             media_uri_id + 'comment/add/',
180             {
181                 'comment_content': u'Test comment #44'
182             }
183         )
184
185         notifications = Notification.query.filter_by(
186             user_id=user.id).all()
187
188         assert len(notifications) == 2
189
190         # both comments should not be marked seen
191         assert notifications[0].seen == False
192         assert notifications[1].seen == False
193
194         # login with other user to mark notifications seen
195         self.logout()
196         self.login('otherperson', 'nosreprehto')
197
198         # mark all comment notifications seen
199         res = self.test_app.get('/notifications/comments/mark_all_seen/')
200         res.follow()
201
202         assert urlparse.urlsplit(res.location)[2] == '/'
203
204         notifications = Notification.query.filter_by(
205             user_id=user.id).all()
206
207         # both notifications should be marked seen
208         assert notifications[0].seen == True
209         assert notifications[1].seen == True