Dot-Notation: MediaComment and some random places
[mediagoblin.git] / mediagoblin / tests / test_submission.py
CommitLineData
1975b5dd 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
1975b5dd
CM
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
17import urlparse
9df37e8a 18import pkg_resources
a246ccca 19import re
1975b5dd 20
afe4e513 21from nose.tools import assert_equal, assert_true, assert_false
1975b5dd 22
9754802d
E
23from mediagoblin.tests.tools import setup_fresh_app, get_test_app, \
24 fixture_add_user
1975b5dd 25from mediagoblin import mg_globals
ae3bc7fa 26from mediagoblin.tools import template, common
1975b5dd 27
9df37e8a
CM
28GOOD_JPG = pkg_resources.resource_filename(
29 'mediagoblin.tests', 'test_submission/good.jpg')
30GOOD_PNG = pkg_resources.resource_filename(
31 'mediagoblin.tests', 'test_submission/good.png')
32EVIL_FILE = pkg_resources.resource_filename(
33 'mediagoblin.tests', 'test_submission/evil')
34EVIL_JPG = pkg_resources.resource_filename(
35 'mediagoblin.tests', 'test_submission/evil.jpg')
36EVIL_PNG = pkg_resources.resource_filename(
37 'mediagoblin.tests', 'test_submission/evil.png')
75ce65cf 38
8ff4dec7
CFD
39GOOD_TAG_STRING = 'yin,yang'
40BAD_TAG_STRING = 'rage,' + 'f' * 26 + 'u' * 26
41
1975b5dd 42
1975b5dd
CM
43class TestSubmission:
44 def setUp(self):
0a78be3e
CM
45 self.test_app = get_test_app()
46
75ce65cf
CM
47 # TODO: Possibly abstract into a decorator like:
48 # @as_authenticated_user('chris')
9754802d 49 test_user = fixture_add_user()
1975b5dd 50
afe4e513
JW
51 self.test_user = test_user
52
c2d6792d
E
53 self.login()
54
55 def login(self):
75ce65cf
CM
56 self.test_app.post(
57 '/auth/login/', {
58 'username': u'chris',
59 'password': 'toast'})
60
c2d6792d
E
61 def logout(self):
62 self.test_app.get('/auth/logout/')
63
75ce65cf 64 def test_missing_fields(self):
ad35dd49
CM
65 # Test blank form
66 # ---------------
ae3bc7fa 67 template.clear_test_template_context()
ad35dd49
CM
68 response = self.test_app.post(
69 '/submit/', {})
ae3bc7fa 70 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
ad35dd49
CM
71 form = context['submit_form']
72 assert form.file.errors == [u'You must provide a file.']
73
74 # Test blank file
75 # ---------------
ae3bc7fa 76 template.clear_test_template_context()
ad35dd49
CM
77 response = self.test_app.post(
78 '/submit/', {
79 'title': 'test title'})
ae3bc7fa 80 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
ad35dd49
CM
81 form = context['submit_form']
82 assert form.file.errors == [u'You must provide a file.']
83
75ce65cf
CM
84
85 def test_normal_uploads(self):
75ce65cf 86 # Test JPG
ad35dd49 87 # --------
ae3bc7fa 88 template.clear_test_template_context()
ad35dd49
CM
89 response = self.test_app.post(
90 '/submit/', {
91 'title': 'Normal upload 1'
92 }, upload_files=[(
9df37e8a 93 'file', GOOD_JPG)])
ad35dd49
CM
94
95 # User should be redirected
96 response.follow()
97 assert_equal(
98 urlparse.urlsplit(response.location)[2],
9df37e8a 99 '/u/chris/')
ae3bc7fa 100 assert template.TEMPLATE_TEST_CONTEXT.has_key(
9df37e8a 101 'mediagoblin/user_pages/user.html')
ad35dd49 102
c2d6792d
E
103 # Make sure the media view is at least reachable, logged in...
104 self.test_app.get('/u/chris/m/normal-upload-1/')
105 # ... and logged out too.
106 self.logout()
107 self.test_app.get('/u/chris/m/normal-upload-1/')
108 # Log back in for the remaining tests.
109 self.login()
110
75ce65cf 111 # Test PNG
ad35dd49 112 # --------
ae3bc7fa 113 template.clear_test_template_context()
ad35dd49
CM
114 response = self.test_app.post(
115 '/submit/', {
116 'title': 'Normal upload 2'
117 }, upload_files=[(
9df37e8a 118 'file', GOOD_PNG)])
ad35dd49
CM
119
120 response.follow()
121 assert_equal(
122 urlparse.urlsplit(response.location)[2],
9df37e8a 123 '/u/chris/')
ae3bc7fa 124 assert template.TEMPLATE_TEST_CONTEXT.has_key(
9df37e8a 125 'mediagoblin/user_pages/user.html')
75ce65cf 126
8ff4dec7
CFD
127 def test_tags(self):
128 # Good tag string
129 # --------
ae3bc7fa 130 template.clear_test_template_context()
8ff4dec7
CFD
131 response = self.test_app.post(
132 '/submit/', {
133 'title': 'Balanced Goblin',
134 'tags': GOOD_TAG_STRING
135 }, upload_files=[(
136 'file', GOOD_JPG)])
137
138 # New media entry with correct tags should be created
139 response.follow()
ae3bc7fa 140 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
8ff4dec7
CFD
141 request = context['request']
142 media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
8efcd405 143 assert_equal(media.tags,
8ff4dec7
CFD
144 [{'name': u'yin', 'slug': u'yin'},
145 {'name': u'yang', 'slug': u'yang'}])
146
147 # Test tags that are too long
148 # ---------------
ae3bc7fa 149 template.clear_test_template_context()
8ff4dec7
CFD
150 response = self.test_app.post(
151 '/submit/', {
152 'title': 'Balanced Goblin',
153 'tags': BAD_TAG_STRING
154 }, upload_files=[(
155 'file', GOOD_JPG)])
156
157 # Too long error should be raised
ae3bc7fa 158 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
8ff4dec7
CFD
159 form = context['submit_form']
160 assert form.tags.errors == [
161 u'Tags must be shorter than 50 characters. Tags that are too long'\
162 ': ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu']
75ce65cf 163
afe4e513 164 def test_delete(self):
ae3bc7fa 165 template.clear_test_template_context()
afe4e513
JW
166 response = self.test_app.post(
167 '/submit/', {
168 'title': 'Balanced Goblin',
169 }, upload_files=[(
170 'file', GOOD_JPG)])
171
172 # Post image
173 response.follow()
174
ae3bc7fa 175 request = template.TEMPLATE_TEST_CONTEXT[
afe4e513
JW
176 'mediagoblin/user_pages/user.html']['request']
177
178 media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
179
180 # Does media entry exist?
181 assert_true(media)
182
183 # Do not confirm deletion
184 # ---------------------------------------------------
185 response = self.test_app.post(
502073f2 186 request.urlgen('mediagoblin.user_pages.media_confirm_delete',
afe4e513 187 # No work: user=media.uploader().username,
5a4e3ff1 188 user=self.test_user.username,
bcc9ee32 189 media=media._id),
9a64272e
CAW
190 # no value means no confirm
191 {})
afe4e513
JW
192
193 response.follow()
194
ae3bc7fa 195 request = template.TEMPLATE_TEST_CONTEXT[
afe4e513
JW
196 'mediagoblin/user_pages/user.html']['request']
197
198 media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
199
200 # Does media entry still exist?
201 assert_true(media)
202
203 # Confirm deletion
204 # ---------------------------------------------------
205 response = self.test_app.post(
502073f2 206 request.urlgen('mediagoblin.user_pages.media_confirm_delete',
afe4e513 207 # No work: user=media.uploader().username,
5a4e3ff1 208 user=self.test_user.username,
bcc9ee32 209 media=media._id),
9a64272e 210 {'confirm': 'y'})
afe4e513
JW
211
212 response.follow()
213
ae3bc7fa 214 request = template.TEMPLATE_TEST_CONTEXT[
afe4e513
JW
215 'mediagoblin/user_pages/user.html']['request']
216
217 # Does media entry still exist?
218 assert_false(
219 request.db.MediaEntry.find(
eabe6b67 220 {'_id': media._id}).count())
afe4e513 221
75ce65cf 222 def test_malicious_uploads(self):
ad35dd49
CM
223 # Test non-suppoerted file with non-supported extension
224 # -----------------------------------------------------
ae3bc7fa 225 template.clear_test_template_context()
ad35dd49
CM
226 response = self.test_app.post(
227 '/submit/', {
68f3ffbe 228 'title': 'Malicious Upload 1'
ad35dd49 229 }, upload_files=[(
9df37e8a 230 'file', EVIL_FILE)])
ad35dd49 231
ae3bc7fa 232 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
ad35dd49 233 form = context['submit_form']
a246ccca
JW
234 assert re.match(r'^Could not extract any file extension from ".*?"$', str(form.file.errors[0]))
235 assert len(form.file.errors) == 1
ad35dd49 236
68f3ffbe
CAW
237 # NOTE: The following 2 tests will ultimately fail, but they
238 # *will* pass the initial form submission step. Instead,
239 # they'll be caught as failures during the processing step.
9df37e8a 240
75ce65cf 241 # Test non-supported file with .jpg extension
ad35dd49 242 # -------------------------------------------
ae3bc7fa 243 template.clear_test_template_context()
68f3ffbe
CAW
244 response = self.test_app.post(
245 '/submit/', {
246 'title': 'Malicious Upload 2'
247 }, upload_files=[(
248 'file', EVIL_JPG)])
249 response.follow()
250 assert_equal(
251 urlparse.urlsplit(response.location)[2],
252 '/u/chris/')
ad35dd49 253
68f3ffbe
CAW
254 entry = mg_globals.database.MediaEntry.find_one(
255 {'title': 'Malicious Upload 2'})
049284b1 256 assert_equal(entry.state, 'failed')
68f3ffbe 257 assert_equal(
8efcd405 258 entry.fail_error,
0bce749b 259 u'mediagoblin.processing:BadMediaFail')
ad35dd49 260
75ce65cf 261 # Test non-supported file with .png extension
ad35dd49 262 # -------------------------------------------
ae3bc7fa 263 template.clear_test_template_context()
68f3ffbe
CAW
264 response = self.test_app.post(
265 '/submit/', {
266 'title': 'Malicious Upload 3'
267 }, upload_files=[(
268 'file', EVIL_PNG)])
269 response.follow()
270 assert_equal(
271 urlparse.urlsplit(response.location)[2],
272 '/u/chris/')
0a78be3e 273
68f3ffbe
CAW
274 entry = mg_globals.database.MediaEntry.find_one(
275 {'title': 'Malicious Upload 3'})
049284b1 276 assert_equal(entry.state, 'failed')
68f3ffbe 277 assert_equal(
8efcd405 278 entry.fail_error,
0bce749b 279 u'mediagoblin.processing:BadMediaFail')