Added tests for custom file name using API
[mediagoblin.git] / mediagoblin / tests / test_api.py
CommitLineData
57c6473a
JW
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/>.
ee9956c3 16import json
57c6473a 17
3a02813c
CAW
18try:
19 import mock
20except ImportError:
21 import unittest.mock as mock
5c2ece74
CAW
22import pytest
23
967df5ef
JT
24from webtest import AppError
25
247a3b78 26from .resources import GOOD_JPG
57c6473a 27from mediagoblin import mg_globals
0d053bff 28from mediagoblin.db.models import User, Activity, MediaEntry, TextComment
9c602458 29from mediagoblin.tools.routing import extract_url_arguments
5c2ece74 30from mediagoblin.tests.tools import fixture_add_user
ee9956c3 31from mediagoblin.moderation.tools import take_away_privileges
57c6473a 32
57c6473a 33class TestAPI(object):
a14d90c2 34 """ Test mediagoblin's pump.io complient APIs """
57c6473a 35
ee9956c3
JT
36 @pytest.fixture(autouse=True)
37 def setup(self, test_app):
38 self.test_app = test_app
57c6473a 39 self.db = mg_globals.database
57c6473a 40
5e5d4458 41 self.user = fixture_add_user(privileges=[u'active', u'uploader', u'commenter'])
8917ffb1
JT
42 self.other_user = fixture_add_user(
43 username="otheruser",
44 privileges=[u'active', u'uploader', u'commenter']
45 )
9246a6ba 46 self.active_user = self.user
57c6473a 47
51ab5192
JT
48 def _activity_to_feed(self, test_app, activity, headers=None):
49 """ Posts an activity to the user's feed """
50 if headers:
51 headers.setdefault("Content-Type", "application/json")
52 else:
53 headers = {"Content-Type": "application/json"}
54
9246a6ba 55 with self.mock_oauth():
51ab5192 56 response = test_app.post(
9246a6ba 57 "/api/user/{0}/feed".format(self.active_user.username),
51ab5192
JT
58 json.dumps(activity),
59 headers=headers
60 )
61
21cbf829 62 return response, json.loads(response.body.decode())
51ab5192 63
f2b32fbf 64 def _upload_image(self, test_app, image, custom_filename=None):
51ab5192
JT
65 """ Uploads and image to MediaGoblin via pump.io API """
66 data = open(image, "rb").read()
67 headers = {
68 "Content-Type": "image/jpeg",
69 "Content-Length": str(len(data))
70 }
71
f2b32fbf
RP
72 if custom_filename is not None:
73 headers["X-File-Name"] = custom_filename
51ab5192 74
9246a6ba 75 with self.mock_oauth():
51ab5192 76 response = test_app.post(
9246a6ba 77 "/api/user/{0}/uploads".format(self.active_user.username),
51ab5192
JT
78 data,
79 headers=headers
80 )
21cbf829 81 image = json.loads(response.body.decode())
51ab5192
JT
82
83 return response, image
84
85 def _post_image_to_feed(self, test_app, image):
86 """ Posts an already uploaded image to feed """
87 activity = {
88 "verb": "post",
89 "object": image,
90 }
91
92 return self._activity_to_feed(test_app, activity)
93
967df5ef
JT
94 def mocked_oauth_required(self, *args, **kwargs):
95 """ Mocks mediagoblin.decorator.oauth_required to always validate """
96
97 def fake_controller(controller, request, *args, **kwargs):
9246a6ba 98 request.user = User.query.filter_by(id=self.active_user.id).first()
967df5ef
JT
99 return controller(request, *args, **kwargs)
100
101 def oauth_required(c):
102 return lambda *args, **kwargs: fake_controller(c, *args, **kwargs)
103
104 return oauth_required
105
9246a6ba
JT
106 def mock_oauth(self):
107 """ Returns a mock.patch for the oauth_required decorator """
108 return mock.patch(
109 target="mediagoblin.decorators.oauth_required",
110 new_callable=self.mocked_oauth_required
111 )
112
ee9956c3
JT
113 def test_can_post_image(self, test_app):
114 """ Tests that an image can be posted to the API """
115 # First request we need to do is to upload the image
51ab5192 116 response, image = self._upload_image(test_app, GOOD_JPG)
ee9956c3 117
51ab5192
JT
118 # I should have got certain things back
119 assert response.status_code == 200
ee9956c3 120
51ab5192
JT
121 assert "id" in image
122 assert "fullImage" in image
123 assert "url" in image["fullImage"]
124 assert "url" in image
125 assert "author" in image
126 assert "published" in image
127 assert "updated" in image
128 assert image["objectType"] == "image"
247a3b78 129
51ab5192 130 # Check that we got the response we're expecting
f2b32fbf 131 response, data = self._post_image_to_feed(test_app, image)
51ab5192 132 assert response.status_code == 200
f2b32fbf
RP
133 assert data["object"]["fullImage"]["url"].endswith("unknown.jpe")
134 assert data["object"]["image"]["url"].endswith("unknown.thumbnail.jpe")
135
136 def test_can_post_image_custom_filename(self, test_app):
137 """ Tests that an image can be posted to the API with custom filename """
138 # First request we need to do is to upload the image
139 response, image = self._upload_image(test_app, GOOD_JPG,
140 custom_filename="hello.jpg")
141
142 # I should have got certain things back
143 assert response.status_code == 200
144
145 assert "id" in image
146 assert "fullImage" in image
147 assert "url" in image["fullImage"]
148 assert "url" in image
149 assert "author" in image
150 assert "published" in image
151 assert "updated" in image
152 assert image["objectType"] == "image"
153
154 # Check that we got the response we're expecting
155 response, data = self._post_image_to_feed(test_app, image)
156 assert response.status_code == 200
157 assert data["object"]["fullImage"]["url"].endswith("hello.jpg")
158 assert data["object"]["image"]["url"].endswith("hello.thumbnail.jpg")
8d75091d 159
8917ffb1
JT
160 def test_unable_to_upload_as_someone_else(self, test_app):
161 """ Test that can't upload as someoen else """
162 data = open(GOOD_JPG, "rb").read()
163 headers = {
164 "Content-Type": "image/jpeg",
165 "Content-Length": str(len(data))
166 }
8d75091d 167
9246a6ba 168 with self.mock_oauth():
8917ffb1
JT
169 # Will be self.user trying to upload as self.other_user
170 with pytest.raises(AppError) as excinfo:
171 test_app.post(
172 "/api/user/{0}/uploads".format(self.other_user.username),
173 data,
174 headers=headers
175 )
8d75091d 176
6430ae97 177 assert "403 FORBIDDEN" in excinfo.value.args[0]
8d75091d 178
8917ffb1
JT
179 def test_unable_to_post_feed_as_someone_else(self, test_app):
180 """ Tests that can't post an image to someone else's feed """
181 response, data = self._upload_image(test_app, GOOD_JPG)
8d75091d 182
8917ffb1
JT
183 activity = {
184 "verb": "post",
185 "object": data
186 }
8d75091d 187
8917ffb1
JT
188 headers = {
189 "Content-Type": "application/json",
190 }
8d75091d 191
9246a6ba 192 with self.mock_oauth():
8917ffb1
JT
193 with pytest.raises(AppError) as excinfo:
194 test_app.post(
195 "/api/user/{0}/feed".format(self.other_user.username),
196 json.dumps(activity),
197 headers=headers
198 )
8d75091d 199
6430ae97 200 assert "403 FORBIDDEN" in excinfo.value.args[0]
8d75091d
JT
201
202 def test_only_able_to_update_own_image(self, test_app):
203 """ Test's that the uploader is the only person who can update an image """
204 response, data = self._upload_image(test_app, GOOD_JPG)
205 response, data = self._post_image_to_feed(test_app, data)
206
207 activity = {
208 "verb": "update",
209 "object": data["object"],
210 }
211
212 headers = {
213 "Content-Type": "application/json",
214 }
215
216 # Lets change the image uploader to be self.other_user, this is easier
217 # than uploading the image as someone else as the way self.mocked_oauth_required
218 # and self._upload_image.
64a456a4 219 media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first()
0f3bf8d4 220 media.actor = self.other_user.id
8d75091d
JT
221 media.save()
222
223 # Now lets try and edit the image as self.user, this should produce a 403 error.
9246a6ba 224 with self.mock_oauth():
8d75091d
JT
225 with pytest.raises(AppError) as excinfo:
226 test_app.post(
227 "/api/user/{0}/feed".format(self.user.username),
228 json.dumps(activity),
229 headers=headers
230 )
231
6430ae97 232 assert "403 FORBIDDEN" in excinfo.value.args[0]
57c6473a 233
51ab5192
JT
234 def test_upload_image_with_filename(self, test_app):
235 """ Tests that you can upload an image with filename and description """
236 response, data = self._upload_image(test_app, GOOD_JPG)
237 response, data = self._post_image_to_feed(test_app, data)
ee9956c3 238
51ab5192
JT
239 image = data["object"]
240
241 # Now we need to add a title and description
242 title = "My image ^_^"
243 description = "This is my super awesome image :D"
244 license = "CC-BY-SA"
245
246 image["displayName"] = title
247 image["content"] = description
248 image["license"] = license
249
250 activity = {"verb": "update", "object": image}
251
9246a6ba 252 with self.mock_oauth():
ee9956c3
JT
253 response = test_app.post(
254 "/api/user/{0}/feed".format(self.user.username),
51ab5192
JT
255 json.dumps(activity),
256 headers={"Content-Type": "application/json"}
ee9956c3
JT
257 )
258
21cbf829 259 image = json.loads(response.body.decode())["object"]
51ab5192
JT
260
261 # Check everything has been set on the media correctly
64a456a4 262 media = MediaEntry.query.filter_by(public_id=image["id"]).first()
51ab5192
JT
263 assert media.title == title
264 assert media.description == description
265 assert media.license == license
266
267 # Check we're being given back everything we should on an update
64a456a4 268 assert image["id"] == media.public_id
51ab5192
JT
269 assert image["displayName"] == title
270 assert image["content"] == description
271 assert image["license"] == license
272
ee9956c3
JT
273
274 def test_only_uploaders_post_image(self, test_app):
275 """ Test that only uploaders can upload images """
276 # Remove uploader permissions from user
277 take_away_privileges(self.user.username, u"uploader")
278
279 # Now try and upload a image
280 data = open(GOOD_JPG, "rb").read()
281 headers = {
282 "Content-Type": "image/jpeg",
283 "Content-Length": str(len(data)),
284 }
285
9246a6ba 286 with self.mock_oauth():
967df5ef 287 with pytest.raises(AppError) as excinfo:
a14d90c2 288 test_app.post(
967df5ef
JT
289 "/api/user/{0}/uploads".format(self.user.username),
290 data,
291 headers=headers
292 )
57c6473a 293
ee9956c3 294 # Assert that we've got a 403
6430ae97 295 assert "403 FORBIDDEN" in excinfo.value.args[0]
51ab5192 296
3c8bd177
JT
297 def test_object_endpoint(self, test_app):
298 """ Tests that object can be looked up at endpoint """
299 # Post an image
300 response, data = self._upload_image(test_app, GOOD_JPG)
301 response, data = self._post_image_to_feed(test_app, data)
302
303 # Now lookup image to check that endpoint works.
304 image = data["object"]
305
306 assert "links" in image
307 assert "self" in image["links"]
308
309 # Get URI and strip testing host off
310 object_uri = image["links"]["self"]["href"]
311 object_uri = object_uri.replace("http://localhost:80", "")
312
9246a6ba 313 with self.mock_oauth():
3c8bd177
JT
314 request = test_app.get(object_uri)
315
1db2bd3f 316 image = json.loads(request.body.decode())
64a456a4 317 entry = MediaEntry.query.filter_by(public_id=image["id"]).first()
3c8bd177
JT
318
319 assert request.status_code == 200
3c8bd177
JT
320
321 assert "image" in image
322 assert "fullImage" in image
323 assert "pump_io" in image
324 assert "links" in image
51ab5192
JT
325
326 def test_post_comment(self, test_app):
327 """ Tests that I can post an comment media """
328 # Upload some media to comment on
329 response, data = self._upload_image(test_app, GOOD_JPG)
330 response, data = self._post_image_to_feed(test_app, data)
331
332 content = "Hai this is a comment on this lovely picture ^_^"
333
334 activity = {
335 "verb": "post",
336 "object": {
337 "objectType": "comment",
338 "content": content,
339 "inReplyTo": data["object"],
340 }
341 }
342
343 response, comment_data = self._activity_to_feed(test_app, activity)
344 assert response.status_code == 200
345
346 # Find the objects in the database
64a456a4 347 media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first()
161bc6b2 348 comment = media.get_comments()[0].comment()
51ab5192
JT
349
350 # Tests that it matches in the database
0f3bf8d4 351 assert comment.actor == self.user.id
51ab5192
JT
352 assert comment.content == content
353
354 # Test that the response is what we should be given
51ab5192 355 assert comment.content == comment_data["object"]["content"]
8d75091d 356
8917ffb1
JT
357 def test_unable_to_post_comment_as_someone_else(self, test_app):
358 """ Tests that you're unable to post a comment as someone else. """
359 # Upload some media to comment on
360 response, data = self._upload_image(test_app, GOOD_JPG)
361 response, data = self._post_image_to_feed(test_app, data)
8d75091d 362
8917ffb1
JT
363 activity = {
364 "verb": "post",
365 "object": {
366 "objectType": "comment",
367 "content": "comment commenty comment ^_^",
368 "inReplyTo": data["object"],
369 }
370 }
8d75091d 371
8917ffb1
JT
372 headers = {
373 "Content-Type": "application/json",
374 }
8d75091d 375
9246a6ba 376 with self.mock_oauth():
8917ffb1
JT
377 with pytest.raises(AppError) as excinfo:
378 test_app.post(
379 "/api/user/{0}/feed".format(self.other_user.username),
380 json.dumps(activity),
381 headers=headers
382 )
8d75091d 383
6430ae97 384 assert "403 FORBIDDEN" in excinfo.value.args[0]
8917ffb1 385
8d75091d
JT
386 def test_unable_to_update_someone_elses_comment(self, test_app):
387 """ Test that you're able to update someoen elses comment. """
388 # Upload some media to comment on
389 response, data = self._upload_image(test_app, GOOD_JPG)
390 response, data = self._post_image_to_feed(test_app, data)
391
392 activity = {
393 "verb": "post",
394 "object": {
395 "objectType": "comment",
396 "content": "comment commenty comment ^_^",
397 "inReplyTo": data["object"],
398 }
399 }
400
401 headers = {
402 "Content-Type": "application/json",
403 }
404
405 # Post the comment.
406 response, comment_data = self._activity_to_feed(test_app, activity)
407
408 # change who uploaded the comment as it's easier than changing
64a456a4 409 comment = TextComment.query.filter_by(public_id=comment_data["object"]["id"]).first()
0f3bf8d4 410 comment.actor = self.other_user.id
9246a6ba 411 comment.save()
8d75091d
JT
412
413 # Update the comment as someone else.
414 comment_data["object"]["content"] = "Yep"
415 activity = {
416 "verb": "update",
417 "object": comment_data["object"]
418 }
419
9246a6ba 420 with self.mock_oauth():
8d75091d
JT
421 with pytest.raises(AppError) as excinfo:
422 test_app.post(
423 "/api/user/{0}/feed".format(self.user.username),
424 json.dumps(activity),
425 headers=headers
426 )
427
6430ae97 428 assert "403 FORBIDDEN" in excinfo.value.args[0]
51ab5192
JT
429
430 def test_profile(self, test_app):
431 """ Tests profile endpoint """
432 uri = "/api/user/{0}/profile".format(self.user.username)
9246a6ba 433 with self.mock_oauth():
51ab5192 434 response = test_app.get(uri)
21cbf829 435 profile = json.loads(response.body.decode())
51ab5192
JT
436
437 assert response.status_code == 200
438
439 assert profile["preferredUsername"] == self.user.username
440 assert profile["objectType"] == "person"
441
442 assert "links" in profile
8ac7a653 443
9246a6ba
JT
444 def test_user(self, test_app):
445 """ Test the user endpoint """
446 uri = "/api/user/{0}/".format(self.user.username)
447 with self.mock_oauth():
448 response = test_app.get(uri)
21cbf829 449 user = json.loads(response.body.decode())
57c6473a 450
9246a6ba 451 assert response.status_code == 200
57c6473a 452
9246a6ba
JT
453 assert user["nickname"] == self.user.username
454 assert user["updated"] == self.user.created.isoformat()
455 assert user["published"] == self.user.created.isoformat()
57c6473a 456
9246a6ba
JT
457 # Test profile exists but self.test_profile will test the value
458 assert "profile" in response
57c6473a 459
5e5d4458
JT
460 def test_whoami_without_login(self, test_app):
461 """ Test that whoami endpoint returns error when not logged in """
462 with pytest.raises(AppError) as excinfo:
463 response = test_app.get("/api/whoami")
57c6473a 464
6430ae97 465 assert "401 UNAUTHORIZED" in excinfo.value.args[0]
57c6473a 466
9246a6ba
JT
467 def test_read_feed(self, test_app):
468 """ Test able to read objects from the feed """
7c9af02a
LD
469 response, image_data = self._upload_image(test_app, GOOD_JPG)
470 response, data = self._post_image_to_feed(test_app, image_data)
57c6473a 471
9246a6ba
JT
472 uri = "/api/user/{0}/feed".format(self.active_user.username)
473 with self.mock_oauth():
474 response = test_app.get(uri)
21cbf829 475 feed = json.loads(response.body.decode())
57c6473a 476
9246a6ba 477 assert response.status_code == 200
57c6473a 478
9246a6ba
JT
479 # Check it has the attributes it should
480 assert "displayName" in feed
481 assert "objectTypes" in feed
482 assert "url" in feed
483 assert "links" in feed
484 assert "author" in feed
485 assert "items" in feed
57c6473a 486
9246a6ba
JT
487 # Check that image i uploaded is there
488 assert feed["items"][0]["verb"] == "post"
0d053bff
JT
489 assert feed["items"][0]["id"] == data["id"]
490 assert feed["items"][0]["object"]["objectType"] == "image"
491 assert feed["items"][0]["object"]["id"] == data["object"]["id"]
492
7c9af02a
LD
493 default_limit = 20
494 items_count = default_limit * 2
495 for i in range(items_count):
496 response, image_data = self._upload_image(test_app, GOOD_JPG)
497 self._post_image_to_feed(test_app, image_data)
498 items_count += 1 # because there already is one
499
500 #
501 # default returns default_limit items
502 #
503 with self.mock_oauth():
504 response = test_app.get(uri)
505 feed = json.loads(response.body.decode())
506 assert len(feed["items"]) == default_limit
507
508 #
509 # silentely ignore count and offset that that are
510 # not a number
511 #
512 with self.mock_oauth():
513 response = test_app.get(uri + "?count=BAD&offset=WORSE")
514 feed = json.loads(response.body.decode())
515 assert len(feed["items"]) == default_limit
516
517 #
518 # if offset is less than default_limit items
519 # from the end of the feed, return less than
520 # default_limit
521 #
522 with self.mock_oauth():
523 near_the_end = items_count - default_limit / 2
524 response = test_app.get(uri + "?offset=%d" % near_the_end)
525 feed = json.loads(response.body.decode())
526 assert len(feed["items"]) < default_limit
527
528 #
529 # count=5 returns 5 items
530 #
531 with self.mock_oauth():
532 response = test_app.get(uri + "?count=5")
533 feed = json.loads(response.body.decode())
534 assert len(feed["items"]) == 5
0d053bff
JT
535
536 def test_read_another_feed(self, test_app):
537 """ Test able to read objects from someone else's feed """
538 response, data = self._upload_image(test_app, GOOD_JPG)
539 response, data = self._post_image_to_feed(test_app, data)
540
541 # Change the active user to someone else.
542 self.active_user = self.other_user
543
544 # Fetch the feed
545 url = "/api/user/{0}/feed".format(self.user.username)
546 with self.mock_oauth():
547 response = test_app.get(url)
548 feed = json.loads(response.body.decode())
549
550 assert response.status_code == 200
551
552 # Check it has the attributes it ought to.
553 assert "displayName" in feed
554 assert "objectTypes" in feed
555 assert "url" in feed
556 assert "links" in feed
557 assert "author" in feed
558 assert "items" in feed
559
560 # Assert the uploaded image is there
561 assert feed["items"][0]["verb"] == "post"
562 assert feed["items"][0]["id"] == data["id"]
563 assert feed["items"][0]["object"]["objectType"] == "image"
564 assert feed["items"][0]["object"]["id"] == data["object"]["id"]
57c6473a 565
9246a6ba
JT
566 def test_cant_post_to_someone_elses_feed(self, test_app):
567 """ Test that can't post to someone elses feed """
568 response, data = self._upload_image(test_app, GOOD_JPG)
569 self.active_user = self.other_user
57c6473a 570
9246a6ba
JT
571 with self.mock_oauth():
572 with pytest.raises(AppError) as excinfo:
573 self._post_image_to_feed(test_app, data)
57c6473a 574
6430ae97 575 assert "403 FORBIDDEN" in excinfo.value.args[0]
57c6473a 576
f6bad0eb 577 def test_object_endpoint_requestable(self, test_app):
9246a6ba
JT
578 """ Test that object endpoint can be requested """
579 response, data = self._upload_image(test_app, GOOD_JPG)
580 response, data = self._post_image_to_feed(test_app, data)
581 object_id = data["object"]["id"]
57c6473a 582
9246a6ba
JT
583 with self.mock_oauth():
584 response = test_app.get(data["object"]["links"]["self"]["href"])
21cbf829 585 data = json.loads(response.body.decode())
57c6473a 586
9246a6ba 587 assert response.status_code == 200
57c6473a 588
9246a6ba
JT
589 assert object_id == data["id"]
590 assert "url" in data
591 assert "links" in data
592 assert data["objectType"] == "image"
4dec1cd6
JT
593
594 def test_delete_media_by_activity(self, test_app):
595 """ Test that an image can be deleted by a delete activity to feed """
596 response, data = self._upload_image(test_app, GOOD_JPG)
597 response, data = self._post_image_to_feed(test_app, data)
598 object_id = data["object"]["id"]
599
600 activity = {
601 "verb": "delete",
602 "object": {
603 "id": object_id,
604 "objectType": "image",
605 }
606 }
607
608 response = self._activity_to_feed(test_app, activity)[1]
609
610 # Check the media is no longer in the database
64a456a4 611 media = MediaEntry.query.filter_by(public_id=object_id).first()
4dec1cd6
JT
612
613 assert media is None
614
615 # Check we've been given the full delete activity back
616 assert "id" in response
617 assert response["verb"] == "delete"
618 assert "object" in response
619 assert response["object"]["id"] == object_id
620 assert response["object"]["objectType"] == "image"
621
622 def test_delete_comment_by_activity(self, test_app):
623 """ Test that a comment is deleted by a delete activity to feed """
624 # First upload an image to comment against
625 response, data = self._upload_image(test_app, GOOD_JPG)
626 response, data = self._post_image_to_feed(test_app, data)
627
628 # Post a comment to delete
629 activity = {
630 "verb": "post",
631 "object": {
632 "objectType": "comment",
633 "content": "This is a comment.",
634 "inReplyTo": data["object"],
635 }
636 }
637
638 comment = self._activity_to_feed(test_app, activity)[1]
639
640 # Now delete the image
641 activity = {
642 "verb": "delete",
643 "object": {
644 "id": comment["object"]["id"],
645 "objectType": "comment",
646 }
647 }
648
649 delete = self._activity_to_feed(test_app, activity)[1]
650
651 # Verify the comment no longer exists
64a456a4
JT
652 assert TextComment.query.filter_by(public_id=comment["object"]["id"]).first() is None
653 comment_id = comment["object"]["id"]
4dec1cd6
JT
654
655 # Check we've got a delete activity back
656 assert "id" in delete
657 assert delete["verb"] == "delete"
658 assert "object" in delete
659 assert delete["object"]["id"] == comment["object"]["id"]
660 assert delete["object"]["objectType"] == "comment"
9e715bb0
JT
661
662 def test_edit_comment(self, test_app):
663 """ Test that someone can update their own comment """
664 # First upload an image to comment against
665 response, data = self._upload_image(test_app, GOOD_JPG)
666 response, data = self._post_image_to_feed(test_app, data)
667
668 # Post a comment to edit
669 activity = {
670 "verb": "post",
671 "object": {
672 "objectType": "comment",
673 "content": "This is a comment",
674 "inReplyTo": data["object"],
675 }
676 }
677
678 comment = self._activity_to_feed(test_app, activity)[1]
679
680 # Now create an update activity to change the content
681 activity = {
682 "verb": "update",
683 "object": {
684 "id": comment["object"]["id"],
685 "content": "This is my fancy new content string!",
686 "objectType": "comment",
687 },
688 }
689
690 comment = self._activity_to_feed(test_app, activity)[1]
691
692 # Verify the comment reflects the changes
64a456a4 693 model = TextComment.query.filter_by(public_id=comment["object"]["id"]).first()
9e715bb0
JT
694
695 assert model.content == activity["object"]["content"]