bookwyrm-mastodon/bookwyrm/tests/views/test_inbox.py

233 lines
9.0 KiB
Python
Raw Normal View History

2021-02-15 19:26:48 -05:00
''' tests incoming activities'''
import json
2021-02-15 22:41:22 -05:00
import pathlib
2021-02-15 19:26:48 -05:00
from unittest.mock import patch
from django.http import HttpResponseNotAllowed, HttpResponseNotFound
from django.test import TestCase, Client
2021-02-15 22:41:22 -05:00
from bookwyrm import models, views
2021-02-15 19:26:48 -05:00
class Inbox(TestCase):
''' readthrough tests '''
def setUp(self):
''' basic user and book data '''
self.client = Client()
self.local_user = models.User.objects.create_user(
'mouse@example.com', 'mouse@mouse.com', 'mouseword',
local=True, localname='mouse')
self.local_user.remote_id = 'https://example.com/user/mouse'
self.local_user.save(broadcast=False)
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',
)
with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'):
self.status = models.Status.objects.create(
user=self.local_user,
content='Test status',
remote_id='https://example.com/status/1',
)
2021-02-15 22:41:22 -05:00
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-02-15 19:26:48 -05:00
models.SiteSettings.objects.create()
def test_inbox_invalid_get(self):
''' shouldn't try to handle if the user is not found '''
result = self.client.get(
'/inbox', content_type="application/json"
)
self.assertIsInstance(result, HttpResponseNotAllowed)
def test_inbox_invalid_user(self):
''' shouldn't try to handle if the user is not found '''
result = self.client.post(
'/user/bleh/inbox',
'{"type": "Test", "object": "exists"}',
content_type="application/json"
)
self.assertIsInstance(result, HttpResponseNotFound)
def test_inbox_invalid_bad_signature(self):
''' bad request for invalid signature '''
with patch('bookwyrm.views.inbox.has_valid_signature') as mock_valid:
mock_valid.return_value = False
result = self.client.post(
'/user/mouse/inbox',
'{"type": "Test", "object": "exists"}',
content_type="application/json"
)
self.assertEqual(result.status_code, 401)
def test_inbox_invalid_bad_signature_delete(self):
''' invalid signature for Delete is okay though '''
with patch('bookwyrm.views.inbox.has_valid_signature') as mock_valid:
mock_valid.return_value = False
result = self.client.post(
'/user/mouse/inbox',
'{"type": "Delete", "object": "exists"}',
content_type="application/json"
)
self.assertEqual(result.status_code, 200)
def test_inbox_unknown_type(self):
''' never heard of that activity type, don't have a handler for it '''
with patch('bookwyrm.views.inbox.has_valid_signature') as mock_valid:
result = self.client.post(
'/inbox',
'{"type": "Fish", "object": "exists"}',
content_type="application/json"
)
mock_valid.return_value = True
self.assertIsInstance(result, HttpResponseNotFound)
def test_inbox_success(self):
''' a known type, for which we start a task '''
2021-02-15 22:41:22 -05:00
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",
2021-02-15 21:47:08 -05:00
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.com/user/mouse/followers"
],
2021-02-15 22:41:22 -05:00
"summary": "summary text",
"curation": "curated",
"@context": "https://www.w3.org/ns/activitystreams"
2021-02-15 19:26:48 -05:00
}
with patch('bookwyrm.views.inbox.has_valid_signature') as mock_valid:
mock_valid.return_value = True
2021-02-15 21:47:08 -05:00
with patch('bookwyrm.views.inbox.activity_task.delay'):
result = self.client.post(
'/inbox',
json.dumps(activity),
content_type="application/json"
)
2021-02-15 19:26:48 -05:00
self.assertEqual(result.status_code, 200)
2021-02-15 22:41:22 -05:00
def test_handle_create_status(self):
''' the "it justs works" mode '''
self.assertEqual(models.Status.objects.count(), 1)
datafile = pathlib.Path(__file__).parent.joinpath(
'../data/ap_quotation.json')
status_data = json.loads(datafile.read_bytes())
models.Edition.objects.create(
title='Test Book', remote_id='https://example.com/book/1')
activity = self.create_json
activity['object'] = status_data
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(models.Status.objects.count(), 2)
# while we're here, lets ensure we avoid dupes
views.inbox.activity_task(activity)
self.assertEqual(models.Status.objects.count(), 2)
def test_handle_create_status_remote_note_with_mention(self):
''' should only create it under the right circumstances '''
self.assertEqual(models.Status.objects.count(), 1)
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
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')
def test_handle_create_status_remote_note_with_reply(self):
''' should only create it under the right circumstances '''
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']
status_data['inReplyTo'] = self.status.remote_id
activity = self.create_json
activity['object'] = status_data
views.inbox.activity_task(activity)
status = models.Status.objects.last()
self.assertEqual(status.content, 'test content in note')
self.assertEqual(status.reply_parent, self.status)
self.assertTrue(
models.Notification.objects.filter(user=self.local_user))
self.assertEqual(
models.Notification.objects.get().notification_type, 'REPLY')
def test_handle_create_list(self):
''' 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')