Commit | Line | Data |
---|---|---|
c8ccd23e | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
cf29e8a8 | 2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. |
c8ccd23e JK |
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 | ||
6430ae97 | 17 | import six |
9459fa3c | 18 | import six.moves.urllib.parse as urlparse |
f6bad0eb | 19 | import pytest |
a3b98853 | 20 | |
c8ccd23e | 21 | from mediagoblin import mg_globals |
414c682f | 22 | from mediagoblin.db.models import User, MediaEntry |
23 | from mediagoblin.tests.tools import fixture_add_user, fixture_media_entry | |
b194f29f | 24 | from mediagoblin import auth |
377db0e7 | 25 | from mediagoblin.tools import template, mail |
fa723291 | 26 | |
c8ccd23e | 27 | |
a3b98853 | 28 | class TestUserEdit(object): |
958080be | 29 | def setup(self): |
a3b98853 SS |
30 | # set up new user |
31 | self.user_password = u'toast' | |
2c901db0 | 32 | self.user = fixture_add_user(password = self.user_password, |
33 | privileges=[u'active']) | |
a3b98853 | 34 | |
5c2ece74 CAW |
35 | def login(self, test_app): |
36 | test_app.post( | |
a3b98853 SS |
37 | '/auth/login/', { |
38 | 'username': self.user.username, | |
39 | 'password': self.user_password}) | |
40 | ||
41 | ||
5c2ece74 | 42 | def test_user_deletion(self, test_app): |
6deb589d | 43 | """Delete user via web interface""" |
5c2ece74 CAW |
44 | self.login(test_app) |
45 | ||
6deb589d SS |
46 | # Make sure user exists |
47 | assert User.query.filter_by(username=u'chris').first() | |
48 | ||
5c2ece74 | 49 | res = test_app.post('/edit/account/delete/', {'confirmed': 'y'}) |
6deb589d SS |
50 | |
51 | # Make sure user has been deleted | |
52 | assert User.query.filter_by(username=u'chris').first() == None | |
53 | ||
54 | #TODO: make sure all corresponding items comments etc have been | |
55 | # deleted too. Perhaps in submission test? | |
56 | ||
57 | #Restore user at end of test | |
2c901db0 | 58 | self.user = fixture_add_user(password = self.user_password, |
59 | privileges=[u'active']) | |
5c2ece74 | 60 | self.login(test_app) |
6deb589d SS |
61 | |
62 | ||
5c2ece74 | 63 | def test_change_bio_url(self, test_app): |
a3b98853 | 64 | """Test changing bio and URL""" |
5c2ece74 CAW |
65 | self.login(test_app) |
66 | ||
a3b98853 | 67 | # Test if legacy profile editing URL redirects correctly |
5c2ece74 | 68 | res = test_app.post( |
a3b98853 SS |
69 | '/edit/profile/', { |
70 | 'bio': u'I love toast!', | |
71 | 'url': u'http://dustycloud.org/'}, expect_errors=True) | |
72 | ||
73 | # Should redirect to /u/chris/edit/ | |
7d503a89 | 74 | assert res.status_int == 302 |
a3b98853 SS |
75 | assert res.headers['Location'].endswith("/u/chris/edit/") |
76 | ||
5c2ece74 | 77 | res = test_app.post( |
a3b98853 SS |
78 | '/u/chris/edit/', { |
79 | 'bio': u'I love toast!', | |
80 | 'url': u'http://dustycloud.org/'}) | |
81 | ||
82 | test_user = User.query.filter_by(username=u'chris').first() | |
7d503a89 CAW |
83 | assert test_user.bio == u'I love toast!' |
84 | assert test_user.url == u'http://dustycloud.org/' | |
a3b98853 SS |
85 | |
86 | # change a different user than the logged in (should fail with 403) | |
2c901db0 | 87 | fixture_add_user(username=u"foo", |
88 | privileges=[u'active']) | |
5c2ece74 | 89 | res = test_app.post( |
a3b98853 SS |
90 | '/u/foo/edit/', { |
91 | 'bio': u'I love toast!', | |
92 | 'url': u'http://dustycloud.org/'}, expect_errors=True) | |
7d503a89 | 93 | assert res.status_int == 403 |
a3b98853 SS |
94 | |
95 | # test changing the bio and the URL inproperly | |
96 | too_long_bio = 150 * 'T' + 150 * 'o' + 150 * 'a' + 150 * 's' + 150* 't' | |
97 | ||
5c2ece74 | 98 | test_app.post( |
a3b98853 SS |
99 | '/u/chris/edit/', { |
100 | # more than 500 characters | |
101 | 'bio': too_long_bio, | |
102 | 'url': 'this-is-no-url'}) | |
103 | ||
104 | # Check form errors | |
7d503a89 CAW |
105 | context = template.TEMPLATE_TEST_CONTEXT[ |
106 | 'mediagoblin/edit/edit_profile.html'] | |
a3b98853 SS |
107 | form = context['form'] |
108 | ||
7d503a89 CAW |
109 | assert form.bio.errors == [ |
110 | u'Field must be between 0 and 500 characters long.'] | |
111 | assert form.url.errors == [ | |
112 | u'This address contains errors'] | |
a3b98853 | 113 | |
377db0e7 RE |
114 | def test_email_change(self, test_app): |
115 | self.login(test_app) | |
116 | ||
377db0e7 RE |
117 | # Test email already in db |
118 | template.clear_test_template_context() | |
119 | test_app.post( | |
4710097b | 120 | '/edit/email/', { |
377db0e7 RE |
121 | 'new_email': 'chris@example.com', |
122 | 'password': 'toast'}) | |
123 | ||
124 | # Check form errors | |
125 | context = template.TEMPLATE_TEST_CONTEXT[ | |
4710097b | 126 | 'mediagoblin/edit/change_email.html'] |
377db0e7 RE |
127 | assert context['form'].new_email.errors == [ |
128 | u'Sorry, a user with that email address already exists.'] | |
129 | ||
377db0e7 RE |
130 | # Test successful email change |
131 | template.clear_test_template_context() | |
132 | res = test_app.post( | |
4710097b | 133 | '/edit/email/', { |
377db0e7 RE |
134 | 'new_email': 'new@example.com', |
135 | 'password': 'toast'}) | |
136 | res.follow() | |
137 | ||
138 | # Correct redirect? | |
4710097b | 139 | assert urlparse.urlsplit(res.location)[2] == '/edit/account/' |
377db0e7 RE |
140 | |
141 | # Make sure we get email verification and try verifying | |
142 | assert len(mail.EMAIL_TEST_INBOX) == 1 | |
143 | message = mail.EMAIL_TEST_INBOX.pop() | |
144 | assert message['To'] == 'new@example.com' | |
145 | email_context = template.TEMPLATE_TEST_CONTEXT[ | |
146 | 'mediagoblin/edit/verification.txt'] | |
cda3055b | 147 | assert email_context['verification_url'].encode('ascii') in message.get_payload(decode=True) |
377db0e7 RE |
148 | |
149 | path = urlparse.urlsplit(email_context['verification_url'])[2] | |
150 | assert path == u'/edit/verify_email/' | |
151 | ||
152 | ## Try verifying with bs verification key, shouldn't work | |
153 | template.clear_test_template_context() | |
154 | res = test_app.get( | |
155 | "/edit/verify_email/?token=total_bs") | |
156 | res.follow() | |
157 | ||
158 | # Correct redirect? | |
159 | assert urlparse.urlsplit(res.location)[2] == '/' | |
160 | ||
161 | # Email shouldn't be saved | |
44082b12 RE |
162 | email_in_db = mg_globals.database.User.query.filter_by( |
163 | email='new@example.com').first() | |
377db0e7 RE |
164 | email = User.query.filter_by(username='chris').first().email |
165 | assert email_in_db is None | |
166 | assert email == 'chris@example.com' | |
167 | ||
168 | # Verify email activation works | |
169 | template.clear_test_template_context() | |
170 | get_params = urlparse.urlsplit(email_context['verification_url'])[3] | |
171 | res = test_app.get('%s?%s' % (path, get_params)) | |
172 | res.follow() | |
173 | ||
174 | # New email saved? | |
175 | email = User.query.filter_by(username='chris').first().email | |
176 | assert email == 'new@example.com' | |
a3b98853 | 177 | # test changing the url inproperly |
414c682f | 178 | |
179 | class TestMetaDataEdit: | |
180 | @pytest.fixture(autouse=True) | |
181 | def setup(self, test_app): | |
182 | # set up new user | |
183 | self.user_password = u'toast' | |
184 | self.user = fixture_add_user(password = self.user_password, | |
185 | privileges=[u'active',u'admin']) | |
186 | self.test_app = test_app | |
187 | ||
188 | def login(self, test_app): | |
189 | test_app.post( | |
190 | '/auth/login/', { | |
191 | 'username': self.user.username, | |
192 | 'password': self.user_password}) | |
193 | ||
194 | def do_post(self, data, *context_keys, **kwargs): | |
195 | url = kwargs.pop('url', '/submit/') | |
196 | do_follow = kwargs.pop('do_follow', False) | |
197 | template.clear_test_template_context() | |
198 | response = self.test_app.post(url, data, **kwargs) | |
199 | if do_follow: | |
200 | response.follow() | |
201 | context_data = template.TEMPLATE_TEST_CONTEXT | |
202 | for key in context_keys: | |
203 | context_data = context_data[key] | |
204 | return response, context_data | |
205 | ||
206 | def test_edit_metadata(self, test_app): | |
207 | media_entry = fixture_media_entry(uploader=self.user.id, | |
208 | state=u'processed') | |
209 | media_slug = "/u/{username}/m/{media_id}/metadata/".format( | |
210 | username = str(self.user.username), | |
211 | media_id = str(media_entry.id)) | |
212 | ||
213 | self.login(test_app) | |
214 | response = test_app.get(media_slug) | |
215 | assert response.status == '200 OK' | |
216 | assert media_entry.media_metadata == {} | |
217 | # First test adding in metadata | |
218 | ################################ | |
219 | response, context = self.do_post({ | |
220 | "media_metadata-0-identifier":"dc:title", | |
221 | "media_metadata-0-value":"Some title", | |
222 | "media_metadata-1-identifier":"dc:creator", | |
223 | "media_metadata-1-value":"Me"},url=media_slug) | |
224 | ||
225 | media_entry = MediaEntry.query.first() | |
226 | new_metadata = media_entry.media_metadata | |
227 | assert new_metadata != {} | |
228 | assert new_metadata.get("dc:title") == "Some title" | |
229 | assert new_metadata.get("dc:creator") == "Me" | |
230 | # Now test removing the metadata | |
231 | ################################ | |
232 | response, context = self.do_post({ | |
233 | "media_metadata-0-identifier":"dc:title", | |
234 | "media_metadata-0-value":"Some title"},url=media_slug) | |
235 | ||
236 | media_entry = MediaEntry.query.first() | |
237 | new_metadata = media_entry.media_metadata | |
238 | assert new_metadata.get("dc:title") == "Some title" | |
239 | assert new_metadata.get("dc:creator") is None | |
240 | # Now test adding bad metadata | |
241 | ############################### | |
242 | response, context = self.do_post({ | |
243 | "media_metadata-0-identifier":"dc:title", | |
244 | "media_metadata-0-value":"Some title", | |
245 | "media_metadata-1-identifier":"dc:creator", | |
246 | "media_metadata-1-value":"Me", | |
247 | "media_metadata-2-identifier":"dc:created", | |
248 | "media_metadata-2-value":"On the worst day"},url=media_slug) | |
249 | ||
250 | media_entry = MediaEntry.query.first() | |
251 | old_metadata = new_metadata | |
252 | new_metadata = media_entry.media_metadata | |
253 | assert new_metadata == old_metadata | |
dd41141d CAW |
254 | context = template.TEMPLATE_TEST_CONTEXT[ |
255 | 'mediagoblin/edit/metadata.html'] | |
6430ae97 CAW |
256 | if six.PY2: |
257 | expected = "u'On the worst day' is not a 'date-time'" | |
258 | else: | |
259 | expected = "'On the worst day' is not a 'date-time'" | |
260 | assert context['form'].errors[ | |
261 | 'media_metadata'][0]['identifier'][0] == expected |