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