moviewyrm/bookwyrm/tests/views/inbox/test_inbox_create.py

258 lines
10 KiB
Python
Raw Normal View History

""" tests incoming activities"""
import json
import pathlib
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models, views
from bookwyrm.activitypub import ActivitySerializerError
# pylint: disable=too-many-public-methods
2021-11-12 17:17:00 +00:00
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
2021-09-06 23:59:58 +00:00
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
class InboxCreate(TestCase):
2021-04-26 16:15:42 +00:00
"""readthrough tests"""
def setUp(self):
2021-04-26 16:15:42 +00:00
"""basic user and book data"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
2021-12-09 23:02:53 +00:00
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
2021-08-03 20:27:32 +00:00
self.local_user = models.User.objects.create_user(
"mouse@example.com",
"mouse@mouse.com",
"mouseword",
local=True,
localname="mouse",
)
2021-08-02 23:05:40 +00:00
self.local_user.remote_id = "https://example.com/user/mouse"
2021-08-03 20:27:32 +00:00
self.local_user.save(broadcast=False, update_fields=["remote_id"])
2021-08-02 23:05:40 +00:00
with patch("bookwyrm.models.user.set_remote_server.delay"):
self.remote_user = models.User.objects.create_user(
"rat",
"rat@rat.com",
"ratword",
local=False,
remote_id="https://example.com/users/rat",
inbox="https://example.com/users/rat/inbox",
outbox="https://example.com/users/rat/outbox",
)
self.create_json = {
"id": "hi",
"type": "Create",
"actor": "hi",
"to": ["https://www.w3.org/ns/activitystreams#public"],
"cc": ["https://example.com/user/mouse/followers"],
"object": {},
}
2021-08-02 23:05:40 +00:00
models.SiteSettings.objects.create()
2021-08-07 21:46:33 +00:00
def test_create_status(self, *_):
2021-04-26 16:15:42 +00:00
"""the "it justs works" mode"""
datafile = pathlib.Path(__file__).parent.joinpath(
"../../data/ap_quotation.json"
)
status_data = json.loads(datafile.read_bytes())
2021-05-26 21:57:29 +00:00
2021-08-02 23:05:40 +00:00
models.Edition.objects.create(
title="Test Book", remote_id="https://example.com/book/1"
)
activity = self.create_json
activity["object"] = status_data
2021-09-06 23:59:58 +00:00
views.inbox.activity_task(activity)
status = models.Quotation.objects.get()
self.assertEqual(
status.remote_id, "https://example.com/user/mouse/quotation/13"
)
self.assertEqual(status.quote, "quote body")
self.assertEqual(status.content, "commentary")
self.assertEqual(status.user, self.local_user)
self.assertEqual(status.thread_id, status.id)
# while we're here, lets ensure we avoid dupes
views.inbox.activity_task(activity)
2021-08-03 00:31:25 +00:00
self.assertEqual(models.Status.objects.count(), 1)
2021-08-16 20:59:15 +00:00
def test_create_comment_with_reading_status(self, *_):
"""the "it justs works" mode"""
2021-08-16 21:00:11 +00:00
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_comment.json")
2021-08-16 20:59:15 +00:00
status_data = json.loads(datafile.read_bytes())
status_data["readingStatus"] = "to-read"
models.Edition.objects.create(
title="Test Book", remote_id="https://example.com/book/1"
)
activity = self.create_json
activity["object"] = status_data
2021-09-06 23:59:58 +00:00
views.inbox.activity_task(activity)
2021-08-16 20:59:15 +00:00
status = models.Comment.objects.get()
2021-08-16 21:00:11 +00:00
self.assertEqual(status.remote_id, "https://example.com/user/mouse/comment/6")
2021-08-16 20:59:15 +00:00
self.assertEqual(status.content, "commentary")
self.assertEqual(status.reading_status, "to-read")
self.assertEqual(status.user, self.local_user)
# while we're here, lets ensure we avoid dupes
views.inbox.activity_task(activity)
self.assertEqual(models.Status.objects.count(), 1)
2021-09-06 23:59:58 +00:00
def test_create_status_remote_note_with_mention(self, *_):
2021-04-26 16:15:42 +00:00
"""should only create it under the right circumstances"""
self.assertFalse(
models.Notification.objects.filter(user=self.local_user).exists()
)
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_note.json")
status_data = json.loads(datafile.read_bytes())
activity = self.create_json
activity["object"] = status_data
2021-09-06 23:59:58 +00:00
views.inbox.activity_task(activity)
status = models.Status.objects.last()
self.assertEqual(status.content, "test content in note")
self.assertEqual(status.mention_users.first(), self.local_user)
self.assertTrue(
models.Notification.objects.filter(user=self.local_user).exists()
)
self.assertEqual(models.Notification.objects.get().notification_type, "MENTION")
2021-09-06 23:59:58 +00:00
def test_create_status_remote_note_with_reply(self, *_):
2021-04-26 16:15:42 +00:00
"""should only create it under the right circumstances"""
2021-09-06 23:59:58 +00:00
parent_status = models.Status.objects.create(
user=self.local_user,
content="Test status",
remote_id="https://example.com/status/1",
)
self.assertEqual(models.Status.objects.count(), 1)
self.assertFalse(models.Notification.objects.filter(user=self.local_user))
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_note.json")
status_data = json.loads(datafile.read_bytes())
del status_data["tag"]
2021-08-03 00:31:25 +00:00
status_data["inReplyTo"] = parent_status.remote_id
activity = self.create_json
activity["object"] = status_data
2021-09-06 23:59:58 +00:00
views.inbox.activity_task(activity)
status = models.Status.objects.last()
self.assertEqual(status.content, "test content in note")
2021-08-03 00:31:25 +00:00
self.assertEqual(status.reply_parent, parent_status)
self.assertEqual(status.thread_id, parent_status.id)
self.assertTrue(models.Notification.objects.filter(user=self.local_user))
self.assertEqual(models.Notification.objects.get().notification_type, "REPLY")
2021-09-06 23:59:58 +00:00
def test_create_rating(self, *_):
2021-04-29 21:43:14 +00:00
"""a remote rating activity"""
2021-08-02 23:05:40 +00:00
book = models.Edition.objects.create(
title="Test Book", remote_id="https://example.com/book/1"
)
2021-04-29 21:43:14 +00:00
activity = self.create_json
activity["object"] = {
"id": "https://example.com/user/mouse/reviewrating/12",
"type": "Rating",
"published": "2021-04-29T21:27:30.014235+00:00",
"attributedTo": "https://example.com/user/mouse",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/mouse/followers"],
"replies": {
"id": "https://example.com/user/mouse/reviewrating/12/replies",
"type": "OrderedCollection",
"totalItems": 0,
"first": "https://example.com/u/mouse/reviewrating/12/replies?page=1",
"last": "https://example.com/u/mouse/reviewrating/12/replies?page=1",
2021-04-29 21:43:14 +00:00
"@context": "https://www.w3.org/ns/activitystreams",
},
"inReplyTo": "",
"summary": "",
"tag": [],
"attachment": [],
"sensitive": False,
"inReplyToBook": "https://example.com/book/1",
"rating": 3,
"@context": "https://www.w3.org/ns/activitystreams",
}
2021-09-06 23:59:58 +00:00
views.inbox.activity_task(activity)
2021-04-29 22:16:51 +00:00
rating = models.ReviewRating.objects.first()
self.assertEqual(rating.book, book)
2021-04-29 21:43:14 +00:00
self.assertEqual(rating.rating, 3.0)
2021-09-06 23:59:58 +00:00
def test_create_list(self, *_):
2021-04-26 16:15:42 +00:00
"""a new list"""
activity = self.create_json
activity["object"] = {
"id": "https://example.com/list/22",
"type": "BookList",
"totalItems": 1,
"first": "https://example.com/list/22?page=1",
"last": "https://example.com/list/22?page=1",
"name": "Test List",
"owner": "https://example.com/user/mouse",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/mouse/followers"],
"summary": "summary text",
"curation": "curated",
"@context": "https://www.w3.org/ns/activitystreams",
}
views.inbox.activity_task(activity)
book_list = models.List.objects.get()
self.assertEqual(book_list.name, "Test List")
self.assertEqual(book_list.curation, "curated")
self.assertEqual(book_list.description, "summary text")
self.assertEqual(book_list.remote_id, "https://example.com/list/22")
def test_create_unsupported_type_question(self, *_):
2021-04-26 16:15:42 +00:00
"""ignore activities we know we can't handle"""
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Question",
}
# just observe how it doesn't throw an error
views.inbox.activity_task(activity)
def test_create_unsupported_type_article(self, *_):
"""special case in unsupported type because we do know what it is"""
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Article",
"name": "hello",
"published": "2021-04-29T21:27:30.014235+00:00",
"attributedTo": "https://example.com/user/mouse",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/mouse/followers"],
"sensitive": False,
"@context": "https://www.w3.org/ns/activitystreams",
}
# just observe how it doesn't throw an error
views.inbox.activity_task(activity)
def test_create_unsupported_type_unknown(self, *_):
"""Something truly unexpected should throw an error"""
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Blaaaah",
}
# error this time
with self.assertRaises(ActivitySerializerError):
views.inbox.activity_task(activity)
2021-09-06 23:59:58 +00:00
def test_create_unknown_type(self, *_):
2021-04-26 16:15:42 +00:00
"""ignore activities we know we've never heard of"""
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Threnody",
}
with self.assertRaises(ActivitySerializerError):
views.inbox.activity_task(activity)