Runs black
This commit is contained in:
parent
a07f955781
commit
70296e760b
198 changed files with 10239 additions and 8572 deletions
|
@ -1,4 +1,4 @@
|
|||
''' testing model activitypub utilities '''
|
||||
""" testing model activitypub utilities """
|
||||
from unittest.mock import patch
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
|
@ -12,238 +12,249 @@ from bookwyrm.models import base_model
|
|||
from bookwyrm.models.activitypub_mixin import ActivitypubMixin
|
||||
from bookwyrm.models.activitypub_mixin import ActivityMixin, ObjectMixin
|
||||
|
||||
|
||||
class ActivitypubMixins(TestCase):
|
||||
''' functionality shared across models '''
|
||||
""" functionality shared across models """
|
||||
|
||||
def setUp(self):
|
||||
''' shared data '''
|
||||
""" shared data """
|
||||
self.local_user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.com', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
self.local_user.remote_id = 'http://example.com/a/b'
|
||||
"mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
self.local_user.remote_id = "http://example.com/a/b"
|
||||
self.local_user.save(broadcast=False)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
self.remote_user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'ratword',
|
||||
"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',
|
||||
remote_id="https://example.com/users/rat",
|
||||
inbox="https://example.com/users/rat/inbox",
|
||||
outbox="https://example.com/users/rat/outbox",
|
||||
)
|
||||
|
||||
self.object_mock = {
|
||||
'to': 'to field', 'cc': 'cc field',
|
||||
'content': 'hi', 'id': 'bip', 'type': 'Test',
|
||||
'published': '2020-12-04T17:52:22.623807+00:00',
|
||||
"to": "to field",
|
||||
"cc": "cc field",
|
||||
"content": "hi",
|
||||
"id": "bip",
|
||||
"type": "Test",
|
||||
"published": "2020-12-04T17:52:22.623807+00:00",
|
||||
}
|
||||
|
||||
|
||||
# ActivitypubMixin
|
||||
def test_to_activity(self):
|
||||
''' model to ActivityPub json '''
|
||||
""" model to ActivityPub json """
|
||||
|
||||
@dataclass(init=False)
|
||||
class TestActivity(ActivityObject):
|
||||
''' real simple mock '''
|
||||
type: str = 'Test'
|
||||
""" real simple mock """
|
||||
|
||||
type: str = "Test"
|
||||
|
||||
class TestModel(ActivitypubMixin, base_model.BookWyrmModel):
|
||||
''' real simple mock model because BookWyrmModel is abstract '''
|
||||
""" real simple mock model because BookWyrmModel is abstract """
|
||||
|
||||
instance = TestModel()
|
||||
instance.remote_id = 'https://www.example.com/test'
|
||||
instance.remote_id = "https://www.example.com/test"
|
||||
instance.activity_serializer = TestActivity
|
||||
|
||||
activity = instance.to_activity()
|
||||
self.assertIsInstance(activity, dict)
|
||||
self.assertEqual(activity['id'], 'https://www.example.com/test')
|
||||
self.assertEqual(activity['type'], 'Test')
|
||||
|
||||
self.assertEqual(activity["id"], "https://www.example.com/test")
|
||||
self.assertEqual(activity["type"], "Test")
|
||||
|
||||
def test_find_existing_by_remote_id(self):
|
||||
''' attempt to match a remote id to an object in the db '''
|
||||
""" attempt to match a remote id to an object in the db """
|
||||
# uses a different remote id scheme
|
||||
# this isn't really part of this test directly but it's helpful to state
|
||||
book = models.Edition.objects.create(
|
||||
title='Test Edition', remote_id='http://book.com/book')
|
||||
title="Test Edition", remote_id="http://book.com/book"
|
||||
)
|
||||
|
||||
self.assertEqual(book.origin_id, 'http://book.com/book')
|
||||
self.assertNotEqual(book.remote_id, 'http://book.com/book')
|
||||
self.assertEqual(book.origin_id, "http://book.com/book")
|
||||
self.assertNotEqual(book.remote_id, "http://book.com/book")
|
||||
|
||||
# uses subclasses
|
||||
with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'):
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
models.Comment.objects.create(
|
||||
user=self.local_user, content='test status', book=book, \
|
||||
remote_id='https://comment.net')
|
||||
user=self.local_user,
|
||||
content="test status",
|
||||
book=book,
|
||||
remote_id="https://comment.net",
|
||||
)
|
||||
|
||||
result = models.User.find_existing_by_remote_id('hi')
|
||||
result = models.User.find_existing_by_remote_id("hi")
|
||||
self.assertIsNone(result)
|
||||
|
||||
result = models.User.find_existing_by_remote_id(
|
||||
'http://example.com/a/b')
|
||||
result = models.User.find_existing_by_remote_id("http://example.com/a/b")
|
||||
self.assertEqual(result, self.local_user)
|
||||
|
||||
# test using origin id
|
||||
result = models.Edition.find_existing_by_remote_id(
|
||||
'http://book.com/book')
|
||||
result = models.Edition.find_existing_by_remote_id("http://book.com/book")
|
||||
self.assertEqual(result, book)
|
||||
|
||||
# test subclass match
|
||||
result = models.Status.find_existing_by_remote_id(
|
||||
'https://comment.net')
|
||||
|
||||
result = models.Status.find_existing_by_remote_id("https://comment.net")
|
||||
|
||||
def test_find_existing(self):
|
||||
''' match a blob of data to a model '''
|
||||
""" match a blob of data to a model """
|
||||
book = models.Edition.objects.create(
|
||||
title='Test edition',
|
||||
openlibrary_key='OL1234',
|
||||
title="Test edition",
|
||||
openlibrary_key="OL1234",
|
||||
)
|
||||
|
||||
result = models.Edition.find_existing(
|
||||
{'openlibraryKey': 'OL1234'})
|
||||
result = models.Edition.find_existing({"openlibraryKey": "OL1234"})
|
||||
self.assertEqual(result, book)
|
||||
|
||||
|
||||
def test_get_recipients_public_object(self):
|
||||
''' determines the recipients for an object's broadcast '''
|
||||
MockSelf = namedtuple('Self', ('privacy'))
|
||||
mock_self = MockSelf('public')
|
||||
""" determines the recipients for an object's broadcast """
|
||||
MockSelf = namedtuple("Self", ("privacy"))
|
||||
mock_self = MockSelf("public")
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], self.remote_user.inbox)
|
||||
|
||||
|
||||
def test_get_recipients_public_user_object_no_followers(self):
|
||||
''' determines the recipients for a user's object broadcast '''
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
""" determines the recipients for a user's object broadcast """
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 0)
|
||||
|
||||
|
||||
def test_get_recipients_public_user_object(self):
|
||||
''' determines the recipients for a user's object broadcast '''
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
""" determines the recipients for a user's object broadcast """
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
self.local_user.followers.add(self.remote_user)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], self.remote_user.inbox)
|
||||
|
||||
|
||||
def test_get_recipients_public_user_object_with_mention(self):
|
||||
''' determines the recipients for a user's object broadcast '''
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
""" determines the recipients for a user's object broadcast """
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
self.local_user.followers.add(self.remote_user)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
another_remote_user = models.User.objects.create_user(
|
||||
'nutria', 'nutria@nutria.com', 'nutriaword',
|
||||
"nutria",
|
||||
"nutria@nutria.com",
|
||||
"nutriaword",
|
||||
local=False,
|
||||
remote_id='https://example.com/users/nutria',
|
||||
inbox='https://example.com/users/nutria/inbox',
|
||||
outbox='https://example.com/users/nutria/outbox',
|
||||
remote_id="https://example.com/users/nutria",
|
||||
inbox="https://example.com/users/nutria/inbox",
|
||||
outbox="https://example.com/users/nutria/outbox",
|
||||
)
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user', 'recipients'))
|
||||
mock_self = MockSelf('public', self.local_user, [another_remote_user])
|
||||
MockSelf = namedtuple("Self", ("privacy", "user", "recipients"))
|
||||
mock_self = MockSelf("public", self.local_user, [another_remote_user])
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 2)
|
||||
self.assertEqual(recipients[0], another_remote_user.inbox)
|
||||
self.assertEqual(recipients[1], self.remote_user.inbox)
|
||||
|
||||
|
||||
def test_get_recipients_direct(self):
|
||||
''' determines the recipients for a user's object broadcast '''
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
""" determines the recipients for a user's object broadcast """
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
self.local_user.followers.add(self.remote_user)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
another_remote_user = models.User.objects.create_user(
|
||||
'nutria', 'nutria@nutria.com', 'nutriaword',
|
||||
"nutria",
|
||||
"nutria@nutria.com",
|
||||
"nutriaword",
|
||||
local=False,
|
||||
remote_id='https://example.com/users/nutria',
|
||||
inbox='https://example.com/users/nutria/inbox',
|
||||
outbox='https://example.com/users/nutria/outbox',
|
||||
remote_id="https://example.com/users/nutria",
|
||||
inbox="https://example.com/users/nutria/inbox",
|
||||
outbox="https://example.com/users/nutria/outbox",
|
||||
)
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user', 'recipients'))
|
||||
mock_self = MockSelf('direct', self.local_user, [another_remote_user])
|
||||
MockSelf = namedtuple("Self", ("privacy", "user", "recipients"))
|
||||
mock_self = MockSelf("direct", self.local_user, [another_remote_user])
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], another_remote_user.inbox)
|
||||
|
||||
|
||||
def test_get_recipients_combine_inboxes(self):
|
||||
''' should combine users with the same shared_inbox '''
|
||||
self.remote_user.shared_inbox = 'http://example.com/inbox'
|
||||
""" should combine users with the same shared_inbox """
|
||||
self.remote_user.shared_inbox = "http://example.com/inbox"
|
||||
self.remote_user.save(broadcast=False)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
another_remote_user = models.User.objects.create_user(
|
||||
'nutria', 'nutria@nutria.com', 'nutriaword',
|
||||
"nutria",
|
||||
"nutria@nutria.com",
|
||||
"nutriaword",
|
||||
local=False,
|
||||
remote_id='https://example.com/users/nutria',
|
||||
inbox='https://example.com/users/nutria/inbox',
|
||||
shared_inbox='http://example.com/inbox',
|
||||
outbox='https://example.com/users/nutria/outbox',
|
||||
remote_id="https://example.com/users/nutria",
|
||||
inbox="https://example.com/users/nutria/inbox",
|
||||
shared_inbox="http://example.com/inbox",
|
||||
outbox="https://example.com/users/nutria/outbox",
|
||||
)
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
self.local_user.followers.add(self.remote_user)
|
||||
self.local_user.followers.add(another_remote_user)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], 'http://example.com/inbox')
|
||||
|
||||
self.assertEqual(recipients[0], "http://example.com/inbox")
|
||||
|
||||
def test_get_recipients_software(self):
|
||||
''' should differentiate between bookwyrm and other remote users '''
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
""" should differentiate between bookwyrm and other remote users """
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
another_remote_user = models.User.objects.create_user(
|
||||
'nutria', 'nutria@nutria.com', 'nutriaword',
|
||||
"nutria",
|
||||
"nutria@nutria.com",
|
||||
"nutriaword",
|
||||
local=False,
|
||||
remote_id='https://example.com/users/nutria',
|
||||
inbox='https://example.com/users/nutria/inbox',
|
||||
outbox='https://example.com/users/nutria/outbox',
|
||||
remote_id="https://example.com/users/nutria",
|
||||
inbox="https://example.com/users/nutria/inbox",
|
||||
outbox="https://example.com/users/nutria/outbox",
|
||||
bookwyrm_user=False,
|
||||
)
|
||||
MockSelf = namedtuple('Self', ('privacy', 'user'))
|
||||
mock_self = MockSelf('public', self.local_user)
|
||||
MockSelf = namedtuple("Self", ("privacy", "user"))
|
||||
mock_self = MockSelf("public", self.local_user)
|
||||
self.local_user.followers.add(self.remote_user)
|
||||
self.local_user.followers.add(another_remote_user)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self)
|
||||
self.assertEqual(len(recipients), 2)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(
|
||||
mock_self, software='bookwyrm')
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self, software="bookwyrm")
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], self.remote_user.inbox)
|
||||
|
||||
recipients = ActivitypubMixin.get_recipients(
|
||||
mock_self, software='other')
|
||||
recipients = ActivitypubMixin.get_recipients(mock_self, software="other")
|
||||
self.assertEqual(len(recipients), 1)
|
||||
self.assertEqual(recipients[0], another_remote_user.inbox)
|
||||
|
||||
|
||||
# ObjectMixin
|
||||
def test_object_save_create(self):
|
||||
''' should save uneventufully when broadcast is disabled '''
|
||||
""" should save uneventufully when broadcast is disabled """
|
||||
|
||||
class Success(Exception):
|
||||
''' this means we got to the right method '''
|
||||
""" this means we got to the right method """
|
||||
|
||||
class ObjectModel(ObjectMixin, base_model.BookWyrmModel):
|
||||
''' real simple mock model because BookWyrmModel is abstract '''
|
||||
user = models.fields.ForeignKey('User', on_delete=db.models.CASCADE)
|
||||
""" real simple mock model because BookWyrmModel is abstract """
|
||||
|
||||
user = models.fields.ForeignKey("User", on_delete=db.models.CASCADE)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
with patch('django.db.models.Model.save'):
|
||||
with patch("django.db.models.Model.save"):
|
||||
super().save(*args, **kwargs)
|
||||
def broadcast(self, activity, sender, **kwargs):#pylint: disable=arguments-differ
|
||||
''' do something '''
|
||||
|
||||
def broadcast(
|
||||
self, activity, sender, **kwargs
|
||||
): # pylint: disable=arguments-differ
|
||||
""" do something """
|
||||
raise Success()
|
||||
def to_create_activity(self, user):#pylint: disable=arguments-differ
|
||||
|
||||
def to_create_activity(self, user): # pylint: disable=arguments-differ
|
||||
return {}
|
||||
|
||||
with self.assertRaises(Success):
|
||||
|
@ -253,20 +264,24 @@ class ActivitypubMixins(TestCase):
|
|||
ObjectModel(user=self.local_user).save(broadcast=False)
|
||||
ObjectModel(user=None).save()
|
||||
|
||||
|
||||
def test_object_save_update(self):
|
||||
''' should save uneventufully when broadcast is disabled '''
|
||||
""" should save uneventufully when broadcast is disabled """
|
||||
|
||||
class Success(Exception):
|
||||
''' this means we got to the right method '''
|
||||
""" this means we got to the right method """
|
||||
|
||||
class UpdateObjectModel(ObjectMixin, base_model.BookWyrmModel):
|
||||
''' real simple mock model because BookWyrmModel is abstract '''
|
||||
user = models.fields.ForeignKey('User', on_delete=db.models.CASCADE)
|
||||
""" real simple mock model because BookWyrmModel is abstract """
|
||||
|
||||
user = models.fields.ForeignKey("User", on_delete=db.models.CASCADE)
|
||||
last_edited_by = models.fields.ForeignKey(
|
||||
'User', on_delete=db.models.CASCADE)
|
||||
"User", on_delete=db.models.CASCADE
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
with patch('django.db.models.Model.save'):
|
||||
with patch("django.db.models.Model.save"):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def to_update_activity(self, user):
|
||||
raise Success()
|
||||
|
||||
|
@ -275,87 +290,71 @@ class ActivitypubMixins(TestCase):
|
|||
with self.assertRaises(Success):
|
||||
UpdateObjectModel(id=1, last_edited_by=self.local_user).save()
|
||||
|
||||
|
||||
def test_object_save_delete(self):
|
||||
''' should create delete activities when objects are deleted by flag '''
|
||||
""" should create delete activities when objects are deleted by flag """
|
||||
|
||||
class ActivitySuccess(Exception):
|
||||
''' this means we got to the right method '''
|
||||
""" this means we got to the right method """
|
||||
|
||||
class DeletableObjectModel(ObjectMixin, base_model.BookWyrmModel):
|
||||
''' real simple mock model because BookWyrmModel is abstract '''
|
||||
user = models.fields.ForeignKey('User', on_delete=db.models.CASCADE)
|
||||
""" real simple mock model because BookWyrmModel is abstract """
|
||||
|
||||
user = models.fields.ForeignKey("User", on_delete=db.models.CASCADE)
|
||||
deleted = models.fields.BooleanField()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
with patch('django.db.models.Model.save'):
|
||||
with patch("django.db.models.Model.save"):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def to_delete_activity(self, user):
|
||||
raise ActivitySuccess()
|
||||
|
||||
with self.assertRaises(ActivitySuccess):
|
||||
DeletableObjectModel(
|
||||
id=1, user=self.local_user, deleted=True).save()
|
||||
|
||||
DeletableObjectModel(id=1, user=self.local_user, deleted=True).save()
|
||||
|
||||
def test_to_delete_activity(self):
|
||||
''' wrapper for Delete activity '''
|
||||
MockSelf = namedtuple('Self', ('remote_id', 'to_activity'))
|
||||
""" wrapper for Delete activity """
|
||||
MockSelf = namedtuple("Self", ("remote_id", "to_activity"))
|
||||
mock_self = MockSelf(
|
||||
'https://example.com/status/1',
|
||||
lambda *args: self.object_mock
|
||||
"https://example.com/status/1", lambda *args: self.object_mock
|
||||
)
|
||||
activity = ObjectMixin.to_delete_activity(
|
||||
mock_self, self.local_user)
|
||||
activity = ObjectMixin.to_delete_activity(mock_self, self.local_user)
|
||||
self.assertEqual(activity["id"], "https://example.com/status/1/activity")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["type"], "Delete")
|
||||
self.assertEqual(activity["to"], ["%s/followers" % self.local_user.remote_id])
|
||||
self.assertEqual(
|
||||
activity['id'],
|
||||
'https://example.com/status/1/activity'
|
||||
activity["cc"], ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
)
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Delete')
|
||||
self.assertEqual(
|
||||
activity['to'],
|
||||
['%s/followers' % self.local_user.remote_id])
|
||||
self.assertEqual(
|
||||
activity['cc'],
|
||||
['https://www.w3.org/ns/activitystreams#Public'])
|
||||
|
||||
|
||||
def test_to_update_activity(self):
|
||||
''' ditto above but for Update '''
|
||||
MockSelf = namedtuple('Self', ('remote_id', 'to_activity'))
|
||||
""" ditto above but for Update """
|
||||
MockSelf = namedtuple("Self", ("remote_id", "to_activity"))
|
||||
mock_self = MockSelf(
|
||||
'https://example.com/status/1',
|
||||
lambda *args: self.object_mock
|
||||
"https://example.com/status/1", lambda *args: self.object_mock
|
||||
)
|
||||
activity = ObjectMixin.to_update_activity(
|
||||
mock_self, self.local_user)
|
||||
activity = ObjectMixin.to_update_activity(mock_self, self.local_user)
|
||||
self.assertIsNotNone(
|
||||
re.match(
|
||||
r'^https:\/\/example\.com\/status\/1#update\/.*',
|
||||
activity['id']
|
||||
)
|
||||
re.match(r"^https:\/\/example\.com\/status\/1#update\/.*", activity["id"])
|
||||
)
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Update')
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["type"], "Update")
|
||||
self.assertEqual(
|
||||
activity['to'],
|
||||
['https://www.w3.org/ns/activitystreams#Public'])
|
||||
self.assertIsInstance(activity['object'], dict)
|
||||
|
||||
activity["to"], ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
)
|
||||
self.assertIsInstance(activity["object"], dict)
|
||||
|
||||
# Activity mixin
|
||||
def test_to_undo_activity(self):
|
||||
''' and again, for Undo '''
|
||||
MockSelf = namedtuple('Self', ('remote_id', 'to_activity', 'user'))
|
||||
""" and again, for Undo """
|
||||
MockSelf = namedtuple("Self", ("remote_id", "to_activity", "user"))
|
||||
mock_self = MockSelf(
|
||||
'https://example.com/status/1',
|
||||
"https://example.com/status/1",
|
||||
lambda *args: self.object_mock,
|
||||
self.local_user,
|
||||
)
|
||||
activity = ActivityMixin.to_undo_activity(mock_self)
|
||||
self.assertEqual(
|
||||
activity['id'],
|
||||
'https://example.com/status/1#undo'
|
||||
)
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Undo')
|
||||
self.assertIsInstance(activity['object'], dict)
|
||||
self.assertEqual(activity["id"], "https://example.com/status/1#undo")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["type"], "Undo")
|
||||
self.assertIsInstance(activity["object"], dict)
|
||||
|
|
|
@ -1,42 +1,41 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from django.test import TestCase
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.models import base_model
|
||||
from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
class BaseModel(TestCase):
|
||||
''' functionality shared across models '''
|
||||
""" functionality shared across models """
|
||||
|
||||
def test_remote_id(self):
|
||||
''' these should be generated '''
|
||||
""" these should be generated """
|
||||
instance = base_model.BookWyrmModel()
|
||||
instance.id = 1
|
||||
expected = instance.get_remote_id()
|
||||
self.assertEqual(expected, 'https://%s/bookwyrmmodel/1' % DOMAIN)
|
||||
self.assertEqual(expected, "https://%s/bookwyrmmodel/1" % DOMAIN)
|
||||
|
||||
def test_remote_id_with_user(self):
|
||||
''' format of remote id when there's a user object '''
|
||||
""" format of remote id when there's a user object """
|
||||
user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.com', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
"mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
instance = base_model.BookWyrmModel()
|
||||
instance.user = user
|
||||
instance.id = 1
|
||||
expected = instance.get_remote_id()
|
||||
self.assertEqual(
|
||||
expected,
|
||||
'https://%s/user/mouse/bookwyrmmodel/1' % DOMAIN)
|
||||
self.assertEqual(expected, "https://%s/user/mouse/bookwyrmmodel/1" % DOMAIN)
|
||||
|
||||
def test_execute_after_save(self):
|
||||
''' this function sets remote ids after creation '''
|
||||
""" this function sets remote ids after creation """
|
||||
# using Work because it BookWrymModel is abstract and this requires save
|
||||
# Work is a relatively not-fancy model.
|
||||
instance = models.Work.objects.create(title='work title')
|
||||
instance = models.Work.objects.create(title="work title")
|
||||
instance.remote_id = None
|
||||
base_model.execute_after_save(None, instance, True)
|
||||
self.assertEqual(
|
||||
instance.remote_id,
|
||||
'https://%s/book/%d' % (DOMAIN, instance.id)
|
||||
instance.remote_id, "https://%s/book/%d" % (DOMAIN, instance.id)
|
||||
)
|
||||
|
||||
# shouldn't set remote_id if it's not created
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from dateutil.parser import parse
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
@ -8,88 +8,80 @@ from bookwyrm.models.book import isbn_10_to_13, isbn_13_to_10
|
|||
|
||||
|
||||
class Book(TestCase):
|
||||
''' not too much going on in the books model but here we are '''
|
||||
""" not too much going on in the books model but here we are """
|
||||
|
||||
def setUp(self):
|
||||
''' we'll need some books '''
|
||||
""" we'll need some books """
|
||||
self.work = models.Work.objects.create(
|
||||
title='Example Work',
|
||||
remote_id='https://example.com/book/1'
|
||||
title="Example Work", remote_id="https://example.com/book/1"
|
||||
)
|
||||
self.first_edition = models.Edition.objects.create(
|
||||
title='Example Edition',
|
||||
title="Example Edition",
|
||||
parent_work=self.work,
|
||||
)
|
||||
self.second_edition = models.Edition.objects.create(
|
||||
title='Another Example Edition',
|
||||
title="Another Example Edition",
|
||||
parent_work=self.work,
|
||||
)
|
||||
|
||||
def test_remote_id(self):
|
||||
''' fanciness with remote/origin ids '''
|
||||
remote_id = 'https://%s/book/%d' % (settings.DOMAIN, self.work.id)
|
||||
""" fanciness with remote/origin ids """
|
||||
remote_id = "https://%s/book/%d" % (settings.DOMAIN, self.work.id)
|
||||
self.assertEqual(self.work.get_remote_id(), remote_id)
|
||||
self.assertEqual(self.work.remote_id, remote_id)
|
||||
|
||||
def test_create_book(self):
|
||||
''' you shouldn't be able to create Books (only editions and works) '''
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
models.Book.objects.create,
|
||||
title='Invalid Book'
|
||||
)
|
||||
""" you shouldn't be able to create Books (only editions and works) """
|
||||
self.assertRaises(ValueError, models.Book.objects.create, title="Invalid Book")
|
||||
|
||||
def test_isbn_10_to_13(self):
|
||||
''' checksums and so on '''
|
||||
isbn_10 = '178816167X'
|
||||
""" checksums and so on """
|
||||
isbn_10 = "178816167X"
|
||||
isbn_13 = isbn_10_to_13(isbn_10)
|
||||
self.assertEqual(isbn_13, '9781788161671')
|
||||
self.assertEqual(isbn_13, "9781788161671")
|
||||
|
||||
isbn_10 = '1-788-16167-X'
|
||||
isbn_10 = "1-788-16167-X"
|
||||
isbn_13 = isbn_10_to_13(isbn_10)
|
||||
self.assertEqual(isbn_13, '9781788161671')
|
||||
|
||||
self.assertEqual(isbn_13, "9781788161671")
|
||||
|
||||
def test_isbn_13_to_10(self):
|
||||
''' checksums and so on '''
|
||||
isbn_13 = '9781788161671'
|
||||
""" checksums and so on """
|
||||
isbn_13 = "9781788161671"
|
||||
isbn_10 = isbn_13_to_10(isbn_13)
|
||||
self.assertEqual(isbn_10, '178816167X')
|
||||
self.assertEqual(isbn_10, "178816167X")
|
||||
|
||||
isbn_13 = '978-1788-16167-1'
|
||||
isbn_13 = "978-1788-16167-1"
|
||||
isbn_10 = isbn_13_to_10(isbn_13)
|
||||
self.assertEqual(isbn_10, '178816167X')
|
||||
|
||||
self.assertEqual(isbn_10, "178816167X")
|
||||
|
||||
def test_get_edition_info(self):
|
||||
''' text slug about an edition '''
|
||||
book = models.Edition.objects.create(title='Test Edition')
|
||||
self.assertEqual(book.edition_info, '')
|
||||
""" text slug about an edition """
|
||||
book = models.Edition.objects.create(title="Test Edition")
|
||||
self.assertEqual(book.edition_info, "")
|
||||
|
||||
book.physical_format = 'worm'
|
||||
book.physical_format = "worm"
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm')
|
||||
self.assertEqual(book.edition_info, "worm")
|
||||
|
||||
book.languages = ['English']
|
||||
book.languages = ["English"]
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm')
|
||||
self.assertEqual(book.edition_info, "worm")
|
||||
|
||||
book.languages = ['Glorbish', 'English']
|
||||
book.languages = ["Glorbish", "English"]
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm, Glorbish language')
|
||||
self.assertEqual(book.edition_info, "worm, Glorbish language")
|
||||
|
||||
book.published_date = timezone.make_aware(parse('2020'))
|
||||
book.published_date = timezone.make_aware(parse("2020"))
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
|
||||
self.assertEqual(
|
||||
book.alt_text, 'Test Edition (worm, Glorbish language, 2020)')
|
||||
|
||||
self.assertEqual(book.edition_info, "worm, Glorbish language, 2020")
|
||||
self.assertEqual(book.alt_text, "Test Edition (worm, Glorbish language, 2020)")
|
||||
|
||||
def test_get_rank(self):
|
||||
''' sets the data quality index for the book '''
|
||||
""" sets the data quality index for the book """
|
||||
# basic rank
|
||||
self.assertEqual(self.first_edition.edition_rank, 0)
|
||||
|
||||
self.first_edition.description = 'hi'
|
||||
self.first_edition.description = "hi"
|
||||
self.first_edition.save()
|
||||
self.assertEqual(self.first_edition.edition_rank, 1)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from io import BytesIO
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
|
@ -23,408 +23,388 @@ from bookwyrm.models import fields, User, Status
|
|||
from bookwyrm.models.base_model import BookWyrmModel
|
||||
from bookwyrm.models.activitypub_mixin import ActivitypubMixin
|
||||
|
||||
#pylint: disable=too-many-public-methods
|
||||
# pylint: disable=too-many-public-methods
|
||||
class ActivitypubFields(TestCase):
|
||||
''' overwrites standard model feilds to work with activitypub '''
|
||||
""" overwrites standard model feilds to work with activitypub """
|
||||
|
||||
def test_validate_remote_id(self):
|
||||
''' should look like a url '''
|
||||
self.assertIsNone(fields.validate_remote_id('http://www.example.com'))
|
||||
self.assertIsNone(fields.validate_remote_id('https://www.example.com'))
|
||||
self.assertIsNone(fields.validate_remote_id('http://exle.com/dlg-23/x'))
|
||||
""" should look like a url """
|
||||
self.assertIsNone(fields.validate_remote_id("http://www.example.com"))
|
||||
self.assertIsNone(fields.validate_remote_id("https://www.example.com"))
|
||||
self.assertIsNone(fields.validate_remote_id("http://exle.com/dlg-23/x"))
|
||||
self.assertRaises(
|
||||
ValidationError, fields.validate_remote_id,
|
||||
'http:/example.com/dlfjg-23/x')
|
||||
ValidationError, fields.validate_remote_id, "http:/example.com/dlfjg-23/x"
|
||||
)
|
||||
self.assertRaises(
|
||||
ValidationError, fields.validate_remote_id,
|
||||
'www.example.com/dlfjg-23/x')
|
||||
ValidationError, fields.validate_remote_id, "www.example.com/dlfjg-23/x"
|
||||
)
|
||||
self.assertRaises(
|
||||
ValidationError, fields.validate_remote_id,
|
||||
'http://www.example.com/dlfjg 23/x')
|
||||
ValidationError,
|
||||
fields.validate_remote_id,
|
||||
"http://www.example.com/dlfjg 23/x",
|
||||
)
|
||||
|
||||
def test_activitypub_field_mixin(self):
|
||||
''' generic mixin with super basic to and from functionality '''
|
||||
""" generic mixin with super basic to and from functionality """
|
||||
instance = fields.ActivitypubFieldMixin()
|
||||
self.assertEqual(instance.field_to_activity('fish'), 'fish')
|
||||
self.assertEqual(instance.field_from_activity('fish'), 'fish')
|
||||
self.assertEqual(instance.field_to_activity("fish"), "fish")
|
||||
self.assertEqual(instance.field_from_activity("fish"), "fish")
|
||||
self.assertFalse(instance.deduplication_field)
|
||||
|
||||
instance = fields.ActivitypubFieldMixin(
|
||||
activitypub_wrapper='endpoints', activitypub_field='outbox'
|
||||
activitypub_wrapper="endpoints", activitypub_field="outbox"
|
||||
)
|
||||
self.assertEqual(
|
||||
instance.field_to_activity('fish'),
|
||||
{'outbox': 'fish'}
|
||||
)
|
||||
self.assertEqual(
|
||||
instance.field_from_activity({'outbox': 'fish'}),
|
||||
'fish'
|
||||
)
|
||||
self.assertEqual(instance.get_activitypub_field(), 'endpoints')
|
||||
self.assertEqual(instance.field_to_activity("fish"), {"outbox": "fish"})
|
||||
self.assertEqual(instance.field_from_activity({"outbox": "fish"}), "fish")
|
||||
self.assertEqual(instance.get_activitypub_field(), "endpoints")
|
||||
|
||||
instance = fields.ActivitypubFieldMixin()
|
||||
instance.name = 'snake_case_name'
|
||||
self.assertEqual(instance.get_activitypub_field(), 'snakeCaseName')
|
||||
instance.name = "snake_case_name"
|
||||
self.assertEqual(instance.get_activitypub_field(), "snakeCaseName")
|
||||
|
||||
def test_set_field_from_activity(self):
|
||||
''' setter from entire json blob '''
|
||||
""" setter from entire json blob """
|
||||
|
||||
@dataclass
|
||||
class TestModel:
|
||||
''' real simple mock '''
|
||||
""" real simple mock """
|
||||
|
||||
field_name: str
|
||||
|
||||
mock_model = TestModel(field_name='bip')
|
||||
TestActivity = namedtuple('test', ('fieldName', 'unrelated'))
|
||||
data = TestActivity(fieldName='hi', unrelated='bfkjh')
|
||||
mock_model = TestModel(field_name="bip")
|
||||
TestActivity = namedtuple("test", ("fieldName", "unrelated"))
|
||||
data = TestActivity(fieldName="hi", unrelated="bfkjh")
|
||||
|
||||
instance = fields.ActivitypubFieldMixin()
|
||||
instance.name = 'field_name'
|
||||
instance.name = "field_name"
|
||||
|
||||
instance.set_field_from_activity(mock_model, data)
|
||||
self.assertEqual(mock_model.field_name, 'hi')
|
||||
self.assertEqual(mock_model.field_name, "hi")
|
||||
|
||||
def test_set_activity_from_field(self):
|
||||
''' set json field given entire model '''
|
||||
""" set json field given entire model """
|
||||
|
||||
@dataclass
|
||||
class TestModel:
|
||||
''' real simple mock '''
|
||||
""" real simple mock """
|
||||
|
||||
field_name: str
|
||||
unrelated: str
|
||||
mock_model = TestModel(field_name='bip', unrelated='field')
|
||||
|
||||
mock_model = TestModel(field_name="bip", unrelated="field")
|
||||
instance = fields.ActivitypubFieldMixin()
|
||||
instance.name = 'field_name'
|
||||
instance.name = "field_name"
|
||||
|
||||
data = {}
|
||||
instance.set_activity_from_field(data, mock_model)
|
||||
self.assertEqual(data['fieldName'], 'bip')
|
||||
self.assertEqual(data["fieldName"], "bip")
|
||||
|
||||
def test_remote_id_field(self):
|
||||
''' just sets some defaults on charfield '''
|
||||
""" just sets some defaults on charfield """
|
||||
instance = fields.RemoteIdField()
|
||||
self.assertEqual(instance.max_length, 255)
|
||||
self.assertTrue(instance.deduplication_field)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
instance.run_validators('http://www.example.com/dlfjg 23/x')
|
||||
instance.run_validators("http://www.example.com/dlfjg 23/x")
|
||||
|
||||
def test_username_field(self):
|
||||
''' again, just setting defaults on username field '''
|
||||
""" again, just setting defaults on username field """
|
||||
instance = fields.UsernameField()
|
||||
self.assertEqual(instance.activitypub_field, 'preferredUsername')
|
||||
self.assertEqual(instance.activitypub_field, "preferredUsername")
|
||||
self.assertEqual(instance.max_length, 150)
|
||||
self.assertEqual(instance.unique, True)
|
||||
with self.assertRaises(ValidationError):
|
||||
instance.run_validators('mouse')
|
||||
instance.run_validators('mouseexample.com')
|
||||
instance.run_validators('mouse@example.c')
|
||||
instance.run_validators('@example.com')
|
||||
instance.run_validators('mouse@examplecom')
|
||||
instance.run_validators('one two@fish.aaaa')
|
||||
instance.run_validators('a*&@exampke.com')
|
||||
instance.run_validators('trailingwhite@example.com ')
|
||||
self.assertIsNone(instance.run_validators('mouse@example.com'))
|
||||
self.assertIsNone(instance.run_validators('mo-2use@ex3ample.com'))
|
||||
self.assertIsNone(instance.run_validators('aksdhf@sdkjf-df.cm'))
|
||||
|
||||
self.assertEqual(instance.field_to_activity('test@example.com'), 'test')
|
||||
instance.run_validators("mouse")
|
||||
instance.run_validators("mouseexample.com")
|
||||
instance.run_validators("mouse@example.c")
|
||||
instance.run_validators("@example.com")
|
||||
instance.run_validators("mouse@examplecom")
|
||||
instance.run_validators("one two@fish.aaaa")
|
||||
instance.run_validators("a*&@exampke.com")
|
||||
instance.run_validators("trailingwhite@example.com ")
|
||||
self.assertIsNone(instance.run_validators("mouse@example.com"))
|
||||
self.assertIsNone(instance.run_validators("mo-2use@ex3ample.com"))
|
||||
self.assertIsNone(instance.run_validators("aksdhf@sdkjf-df.cm"))
|
||||
|
||||
self.assertEqual(instance.field_to_activity("test@example.com"), "test")
|
||||
|
||||
def test_privacy_field_defaults(self):
|
||||
''' post privacy field's many default values '''
|
||||
""" post privacy field's many default values """
|
||||
instance = fields.PrivacyField()
|
||||
self.assertEqual(instance.max_length, 255)
|
||||
self.assertEqual(
|
||||
[c[0] for c in instance.choices],
|
||||
['public', 'unlisted', 'followers', 'direct'])
|
||||
self.assertEqual(instance.default, 'public')
|
||||
["public", "unlisted", "followers", "direct"],
|
||||
)
|
||||
self.assertEqual(instance.default, "public")
|
||||
self.assertEqual(
|
||||
instance.public, 'https://www.w3.org/ns/activitystreams#Public')
|
||||
instance.public, "https://www.w3.org/ns/activitystreams#Public"
|
||||
)
|
||||
|
||||
def test_privacy_field_set_field_from_activity(self):
|
||||
''' translate between to/cc fields and privacy '''
|
||||
""" translate between to/cc fields and privacy """
|
||||
|
||||
@dataclass(init=False)
|
||||
class TestActivity(ActivityObject):
|
||||
''' real simple mock '''
|
||||
""" real simple mock """
|
||||
|
||||
to: List[str]
|
||||
cc: List[str]
|
||||
id: str = 'http://hi.com'
|
||||
type: str = 'Test'
|
||||
id: str = "http://hi.com"
|
||||
type: str = "Test"
|
||||
|
||||
class TestPrivacyModel(ActivitypubMixin, BookWyrmModel):
|
||||
''' real simple mock model because BookWyrmModel is abstract '''
|
||||
""" real simple mock model because BookWyrmModel is abstract """
|
||||
|
||||
privacy_field = fields.PrivacyField()
|
||||
mention_users = fields.TagField(User)
|
||||
user = fields.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
public = 'https://www.w3.org/ns/activitystreams#Public'
|
||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
||||
data = TestActivity(
|
||||
to=[public],
|
||||
cc=['bleh'],
|
||||
cc=["bleh"],
|
||||
)
|
||||
model_instance = TestPrivacyModel(privacy_field='direct')
|
||||
self.assertEqual(model_instance.privacy_field, 'direct')
|
||||
model_instance = TestPrivacyModel(privacy_field="direct")
|
||||
self.assertEqual(model_instance.privacy_field, "direct")
|
||||
|
||||
instance = fields.PrivacyField()
|
||||
instance.name = 'privacy_field'
|
||||
instance.name = "privacy_field"
|
||||
instance.set_field_from_activity(model_instance, data)
|
||||
self.assertEqual(model_instance.privacy_field, 'public')
|
||||
self.assertEqual(model_instance.privacy_field, "public")
|
||||
|
||||
data.to = ['bleh']
|
||||
data.to = ["bleh"]
|
||||
data.cc = []
|
||||
instance.set_field_from_activity(model_instance, data)
|
||||
self.assertEqual(model_instance.privacy_field, 'direct')
|
||||
self.assertEqual(model_instance.privacy_field, "direct")
|
||||
|
||||
data.to = ['bleh']
|
||||
data.cc = [public, 'waah']
|
||||
data.to = ["bleh"]
|
||||
data.cc = [public, "waah"]
|
||||
instance.set_field_from_activity(model_instance, data)
|
||||
self.assertEqual(model_instance.privacy_field, 'unlisted')
|
||||
self.assertEqual(model_instance.privacy_field, "unlisted")
|
||||
|
||||
|
||||
@patch('bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast')
|
||||
@patch("bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast")
|
||||
def test_privacy_field_set_activity_from_field(self, _):
|
||||
''' translate between to/cc fields and privacy '''
|
||||
""" translate between to/cc fields and privacy """
|
||||
user = User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword',
|
||||
local=True, localname='rat')
|
||||
public = 'https://www.w3.org/ns/activitystreams#Public'
|
||||
followers = '%s/followers' % user.remote_id
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
||||
followers = "%s/followers" % user.remote_id
|
||||
|
||||
instance = fields.PrivacyField()
|
||||
instance.name = 'privacy_field'
|
||||
instance.name = "privacy_field"
|
||||
|
||||
model_instance = Status.objects.create(user=user, content='hi')
|
||||
model_instance = Status.objects.create(user=user, content="hi")
|
||||
activity = {}
|
||||
instance.set_activity_from_field(activity, model_instance)
|
||||
self.assertEqual(activity['to'], [public])
|
||||
self.assertEqual(activity['cc'], [followers])
|
||||
self.assertEqual(activity["to"], [public])
|
||||
self.assertEqual(activity["cc"], [followers])
|
||||
|
||||
model_instance = Status.objects.create(
|
||||
user=user, content='hi', privacy='unlisted')
|
||||
user=user, content="hi", privacy="unlisted"
|
||||
)
|
||||
activity = {}
|
||||
instance.set_activity_from_field(activity, model_instance)
|
||||
self.assertEqual(activity['to'], [followers])
|
||||
self.assertEqual(activity['cc'], [public])
|
||||
self.assertEqual(activity["to"], [followers])
|
||||
self.assertEqual(activity["cc"], [public])
|
||||
|
||||
model_instance = Status.objects.create(
|
||||
user=user, content='hi', privacy='followers')
|
||||
user=user, content="hi", privacy="followers"
|
||||
)
|
||||
activity = {}
|
||||
instance.set_activity_from_field(activity, model_instance)
|
||||
self.assertEqual(activity['to'], [followers])
|
||||
self.assertEqual(activity['cc'], [])
|
||||
self.assertEqual(activity["to"], [followers])
|
||||
self.assertEqual(activity["cc"], [])
|
||||
|
||||
model_instance = Status.objects.create(
|
||||
user=user,
|
||||
content='hi',
|
||||
privacy='direct',
|
||||
content="hi",
|
||||
privacy="direct",
|
||||
)
|
||||
model_instance.mention_users.set([user])
|
||||
activity = {}
|
||||
instance.set_activity_from_field(activity, model_instance)
|
||||
self.assertEqual(activity['to'], [user.remote_id])
|
||||
self.assertEqual(activity['cc'], [])
|
||||
|
||||
self.assertEqual(activity["to"], [user.remote_id])
|
||||
self.assertEqual(activity["cc"], [])
|
||||
|
||||
def test_foreign_key(self):
|
||||
''' should be able to format a related model '''
|
||||
instance = fields.ForeignKey('User', on_delete=models.CASCADE)
|
||||
Serializable = namedtuple('Serializable', ('to_activity', 'remote_id'))
|
||||
item = Serializable(lambda: {'a': 'b'}, 'https://e.b/c')
|
||||
""" should be able to format a related model """
|
||||
instance = fields.ForeignKey("User", on_delete=models.CASCADE)
|
||||
Serializable = namedtuple("Serializable", ("to_activity", "remote_id"))
|
||||
item = Serializable(lambda: {"a": "b"}, "https://e.b/c")
|
||||
# returns the remote_id field of the related object
|
||||
self.assertEqual(instance.field_to_activity(item), 'https://e.b/c')
|
||||
|
||||
self.assertEqual(instance.field_to_activity(item), "https://e.b/c")
|
||||
|
||||
@responses.activate
|
||||
def test_foreign_key_from_activity_str(self):
|
||||
''' create a new object from a foreign key '''
|
||||
""" create a new object from a foreign key """
|
||||
instance = fields.ForeignKey(User, on_delete=models.CASCADE)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ap_user.json')
|
||||
datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json")
|
||||
userdata = json.loads(datafile.read_bytes())
|
||||
# don't try to load the user icon
|
||||
del userdata['icon']
|
||||
del userdata["icon"]
|
||||
|
||||
# it shouldn't match with this unrelated user:
|
||||
unrelated_user = User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword',
|
||||
local=True, localname='rat')
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
|
||||
# test receiving an unknown remote id and loading data
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://example.com/user/mouse',
|
||||
json=userdata,
|
||||
status=200)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
value = instance.field_from_activity(
|
||||
'https://example.com/user/mouse')
|
||||
responses.GET, "https://example.com/user/mouse", json=userdata, status=200
|
||||
)
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
value = instance.field_from_activity("https://example.com/user/mouse")
|
||||
self.assertIsInstance(value, User)
|
||||
self.assertNotEqual(value, unrelated_user)
|
||||
self.assertEqual(value.remote_id, 'https://example.com/user/mouse')
|
||||
self.assertEqual(value.name, 'MOUSE?? MOUSE!!')
|
||||
|
||||
self.assertEqual(value.remote_id, "https://example.com/user/mouse")
|
||||
self.assertEqual(value.name, "MOUSE?? MOUSE!!")
|
||||
|
||||
def test_foreign_key_from_activity_dict(self):
|
||||
''' test recieving activity json '''
|
||||
""" test recieving activity json """
|
||||
instance = fields.ForeignKey(User, on_delete=models.CASCADE)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ap_user.json')
|
||||
datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json")
|
||||
userdata = json.loads(datafile.read_bytes())
|
||||
# don't try to load the user icon
|
||||
del userdata['icon']
|
||||
del userdata["icon"]
|
||||
|
||||
# it shouldn't match with this unrelated user:
|
||||
unrelated_user = User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword',
|
||||
local=True, localname='rat')
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
value = instance.field_from_activity(activitypub.Person(**userdata))
|
||||
self.assertIsInstance(value, User)
|
||||
self.assertNotEqual(value, unrelated_user)
|
||||
self.assertEqual(value.remote_id, 'https://example.com/user/mouse')
|
||||
self.assertEqual(value.name, 'MOUSE?? MOUSE!!')
|
||||
self.assertEqual(value.remote_id, "https://example.com/user/mouse")
|
||||
self.assertEqual(value.name, "MOUSE?? MOUSE!!")
|
||||
# et cetera but we're not testing serializing user json
|
||||
|
||||
|
||||
def test_foreign_key_from_activity_dict_existing(self):
|
||||
''' test receiving a dict of an existing object in the db '''
|
||||
""" test receiving a dict of an existing object in the db """
|
||||
instance = fields.ForeignKey(User, on_delete=models.CASCADE)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ap_user.json'
|
||||
)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json")
|
||||
userdata = json.loads(datafile.read_bytes())
|
||||
user = User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
user.remote_id = 'https://example.com/user/mouse'
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
user.remote_id = "https://example.com/user/mouse"
|
||||
user.save(broadcast=False)
|
||||
User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword',
|
||||
local=True, localname='rat')
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
|
||||
with patch('bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast'):
|
||||
with patch("bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast"):
|
||||
value = instance.field_from_activity(activitypub.Person(**userdata))
|
||||
self.assertEqual(value, user)
|
||||
|
||||
|
||||
def test_foreign_key_from_activity_str_existing(self):
|
||||
''' test receiving a remote id of an existing object in the db '''
|
||||
""" test receiving a remote id of an existing object in the db """
|
||||
instance = fields.ForeignKey(User, on_delete=models.CASCADE)
|
||||
user = User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword',
|
||||
local=True, localname='rat')
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
|
||||
value = instance.field_from_activity(user.remote_id)
|
||||
self.assertEqual(value, user)
|
||||
|
||||
|
||||
def test_one_to_one_field(self):
|
||||
''' a gussied up foreign key '''
|
||||
instance = fields.OneToOneField('User', on_delete=models.CASCADE)
|
||||
Serializable = namedtuple('Serializable', ('to_activity', 'remote_id'))
|
||||
item = Serializable(lambda: {'a': 'b'}, 'https://e.b/c')
|
||||
self.assertEqual(instance.field_to_activity(item), {'a': 'b'})
|
||||
""" a gussied up foreign key """
|
||||
instance = fields.OneToOneField("User", on_delete=models.CASCADE)
|
||||
Serializable = namedtuple("Serializable", ("to_activity", "remote_id"))
|
||||
item = Serializable(lambda: {"a": "b"}, "https://e.b/c")
|
||||
self.assertEqual(instance.field_to_activity(item), {"a": "b"})
|
||||
|
||||
def test_many_to_many_field(self):
|
||||
''' lists! '''
|
||||
instance = fields.ManyToManyField('User')
|
||||
""" lists! """
|
||||
instance = fields.ManyToManyField("User")
|
||||
|
||||
Serializable = namedtuple('Serializable', ('to_activity', 'remote_id'))
|
||||
Queryset = namedtuple('Queryset', ('all', 'instance'))
|
||||
item = Serializable(lambda: {'a': 'b'}, 'https://e.b/c')
|
||||
another_item = Serializable(lambda: {}, 'example.com')
|
||||
Serializable = namedtuple("Serializable", ("to_activity", "remote_id"))
|
||||
Queryset = namedtuple("Queryset", ("all", "instance"))
|
||||
item = Serializable(lambda: {"a": "b"}, "https://e.b/c")
|
||||
another_item = Serializable(lambda: {}, "example.com")
|
||||
|
||||
items = Queryset(lambda: [item], another_item)
|
||||
|
||||
self.assertEqual(instance.field_to_activity(items), ['https://e.b/c'])
|
||||
self.assertEqual(instance.field_to_activity(items), ["https://e.b/c"])
|
||||
|
||||
instance = fields.ManyToManyField('User', link_only=True)
|
||||
instance.name = 'snake_case'
|
||||
self.assertEqual(
|
||||
instance.field_to_activity(items),
|
||||
'example.com/snake_case'
|
||||
)
|
||||
instance = fields.ManyToManyField("User", link_only=True)
|
||||
instance.name = "snake_case"
|
||||
self.assertEqual(instance.field_to_activity(items), "example.com/snake_case")
|
||||
|
||||
@responses.activate
|
||||
def test_many_to_many_field_from_activity(self):
|
||||
''' resolve related fields for a list, takes a list of remote ids '''
|
||||
""" resolve related fields for a list, takes a list of remote ids """
|
||||
instance = fields.ManyToManyField(User)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ap_user.json'
|
||||
)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json")
|
||||
userdata = json.loads(datafile.read_bytes())
|
||||
# don't try to load the user icon
|
||||
del userdata['icon']
|
||||
del userdata["icon"]
|
||||
|
||||
# test receiving an unknown remote id and loading data
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://example.com/user/mouse',
|
||||
json=userdata,
|
||||
status=200)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
responses.GET, "https://example.com/user/mouse", json=userdata, status=200
|
||||
)
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
value = instance.field_from_activity(
|
||||
['https://example.com/user/mouse', 'bleh']
|
||||
["https://example.com/user/mouse", "bleh"]
|
||||
)
|
||||
self.assertIsInstance(value, list)
|
||||
self.assertEqual(len(value), 1)
|
||||
self.assertIsInstance(value[0], User)
|
||||
|
||||
def test_tag_field(self):
|
||||
''' a special type of many to many field '''
|
||||
instance = fields.TagField('User')
|
||||
""" a special type of many to many field """
|
||||
instance = fields.TagField("User")
|
||||
|
||||
Serializable = namedtuple(
|
||||
'Serializable',
|
||||
('to_activity', 'remote_id', 'name_field', 'name')
|
||||
"Serializable", ("to_activity", "remote_id", "name_field", "name")
|
||||
)
|
||||
Queryset = namedtuple('Queryset', ('all', 'instance'))
|
||||
item = Serializable(
|
||||
lambda: {'a': 'b'}, 'https://e.b/c', 'name', 'Name')
|
||||
another_item = Serializable(
|
||||
lambda: {}, 'example.com', '', '')
|
||||
Queryset = namedtuple("Queryset", ("all", "instance"))
|
||||
item = Serializable(lambda: {"a": "b"}, "https://e.b/c", "name", "Name")
|
||||
another_item = Serializable(lambda: {}, "example.com", "", "")
|
||||
items = Queryset(lambda: [item], another_item)
|
||||
|
||||
result = instance.field_to_activity(items)
|
||||
self.assertIsInstance(result, list)
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0].href, 'https://e.b/c')
|
||||
self.assertEqual(result[0].name, 'Name')
|
||||
self.assertEqual(result[0].type, 'Serializable')
|
||||
|
||||
self.assertEqual(result[0].href, "https://e.b/c")
|
||||
self.assertEqual(result[0].name, "Name")
|
||||
self.assertEqual(result[0].type, "Serializable")
|
||||
|
||||
def test_tag_field_from_activity(self):
|
||||
''' loadin' a list of items from Links '''
|
||||
""" loadin' a list of items from Links """
|
||||
# TODO
|
||||
|
||||
|
||||
@responses.activate
|
||||
@patch('bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast')
|
||||
@patch("bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast")
|
||||
def test_image_field(self, _):
|
||||
''' storing images '''
|
||||
""" storing images """
|
||||
user = User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
'../../static/images/default_avi.jpg')
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
user.avatar.save(
|
||||
'test.jpg',
|
||||
ContentFile(output.getvalue())
|
||||
)
|
||||
user.avatar.save("test.jpg", ContentFile(output.getvalue()))
|
||||
|
||||
output = fields.image_serializer(user.avatar, alt='alt text')
|
||||
output = fields.image_serializer(user.avatar, alt="alt text")
|
||||
self.assertIsNotNone(
|
||||
re.match(
|
||||
r'.*\.jpg',
|
||||
r".*\.jpg",
|
||||
output.url,
|
||||
)
|
||||
)
|
||||
self.assertEqual(output.name, 'alt text')
|
||||
self.assertEqual(output.type, 'Image')
|
||||
self.assertEqual(output.name, "alt text")
|
||||
self.assertEqual(output.type, "Image")
|
||||
|
||||
instance = fields.ImageField()
|
||||
|
||||
|
@ -433,36 +413,30 @@ class ActivitypubFields(TestCase):
|
|||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'http://www.example.com/image.jpg',
|
||||
"http://www.example.com/image.jpg",
|
||||
body=user.avatar.file.read(),
|
||||
status=200)
|
||||
loaded_image = instance.field_from_activity(
|
||||
'http://www.example.com/image.jpg')
|
||||
status=200,
|
||||
)
|
||||
loaded_image = instance.field_from_activity("http://www.example.com/image.jpg")
|
||||
self.assertIsInstance(loaded_image, list)
|
||||
self.assertIsInstance(loaded_image[1], ContentFile)
|
||||
|
||||
|
||||
def test_datetime_field(self):
|
||||
''' this one is pretty simple, it just has to use isoformat '''
|
||||
""" this one is pretty simple, it just has to use isoformat """
|
||||
instance = fields.DateTimeField()
|
||||
now = timezone.now()
|
||||
self.assertEqual(instance.field_to_activity(now), now.isoformat())
|
||||
self.assertEqual(
|
||||
instance.field_from_activity(now.isoformat()), now
|
||||
)
|
||||
self.assertEqual(instance.field_from_activity('bip'), None)
|
||||
|
||||
self.assertEqual(instance.field_from_activity(now.isoformat()), now)
|
||||
self.assertEqual(instance.field_from_activity("bip"), None)
|
||||
|
||||
def test_array_field(self):
|
||||
''' idk why it makes them strings but probably for a good reason '''
|
||||
""" idk why it makes them strings but probably for a good reason """
|
||||
instance = fields.ArrayField(fields.IntegerField)
|
||||
self.assertEqual(instance.field_to_activity([0, 1]), ['0', '1'])
|
||||
|
||||
self.assertEqual(instance.field_to_activity([0, 1]), ["0", "1"])
|
||||
|
||||
def test_html_field(self):
|
||||
''' sanitizes html, the sanitizer has its own tests '''
|
||||
""" sanitizes html, the sanitizer has its own tests """
|
||||
instance = fields.HtmlField()
|
||||
self.assertEqual(
|
||||
instance.field_from_activity('<marquee><p>hi</p></marquee>'),
|
||||
'<p>hi</p>'
|
||||
instance.field_from_activity("<marquee><p>hi</p></marquee>"), "<p>hi</p>"
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
import datetime
|
||||
import json
|
||||
import pathlib
|
||||
|
@ -14,165 +14,166 @@ from bookwyrm.connectors.abstract_connector import SearchResult
|
|||
|
||||
|
||||
class ImportJob(TestCase):
|
||||
''' this is a fancy one!!! '''
|
||||
""" this is a fancy one!!! """
|
||||
|
||||
def setUp(self):
|
||||
''' data is from a goodreads export of The Raven Tower '''
|
||||
""" data is from a goodreads export of The Raven Tower """
|
||||
read_data = {
|
||||
'Book Id': 39395857,
|
||||
'Title': 'The Raven Tower',
|
||||
'Author': 'Ann Leckie',
|
||||
'Author l-f': 'Leckie, Ann',
|
||||
'Additional Authors': '',
|
||||
'ISBN': '="0356506991"',
|
||||
'ISBN13': '="9780356506999"',
|
||||
'My Rating': 0,
|
||||
'Average Rating': 4.06,
|
||||
'Publisher': 'Orbit',
|
||||
'Binding': 'Hardcover',
|
||||
'Number of Pages': 416,
|
||||
'Year Published': 2019,
|
||||
'Original Publication Year': 2019,
|
||||
'Date Read': '2019/04/12',
|
||||
'Date Added': '2019/04/09',
|
||||
'Bookshelves': '',
|
||||
'Bookshelves with positions': '',
|
||||
'Exclusive Shelf': 'read',
|
||||
'My Review': '',
|
||||
'Spoiler': '',
|
||||
'Private Notes': '',
|
||||
'Read Count': 1,
|
||||
'Recommended For': '',
|
||||
'Recommended By': '',
|
||||
'Owned Copies': 0,
|
||||
'Original Purchase Date': '',
|
||||
'Original Purchase Location': '',
|
||||
'Condition': '',
|
||||
'Condition Description': '',
|
||||
'BCID': ''
|
||||
"Book Id": 39395857,
|
||||
"Title": "The Raven Tower",
|
||||
"Author": "Ann Leckie",
|
||||
"Author l-f": "Leckie, Ann",
|
||||
"Additional Authors": "",
|
||||
"ISBN": '="0356506991"',
|
||||
"ISBN13": '="9780356506999"',
|
||||
"My Rating": 0,
|
||||
"Average Rating": 4.06,
|
||||
"Publisher": "Orbit",
|
||||
"Binding": "Hardcover",
|
||||
"Number of Pages": 416,
|
||||
"Year Published": 2019,
|
||||
"Original Publication Year": 2019,
|
||||
"Date Read": "2019/04/12",
|
||||
"Date Added": "2019/04/09",
|
||||
"Bookshelves": "",
|
||||
"Bookshelves with positions": "",
|
||||
"Exclusive Shelf": "read",
|
||||
"My Review": "",
|
||||
"Spoiler": "",
|
||||
"Private Notes": "",
|
||||
"Read Count": 1,
|
||||
"Recommended For": "",
|
||||
"Recommended By": "",
|
||||
"Owned Copies": 0,
|
||||
"Original Purchase Date": "",
|
||||
"Original Purchase Location": "",
|
||||
"Condition": "",
|
||||
"Condition Description": "",
|
||||
"BCID": "",
|
||||
}
|
||||
currently_reading_data = read_data.copy()
|
||||
currently_reading_data['Exclusive Shelf'] = 'currently-reading'
|
||||
currently_reading_data['Date Read'] = ''
|
||||
currently_reading_data["Exclusive Shelf"] = "currently-reading"
|
||||
currently_reading_data["Date Read"] = ""
|
||||
|
||||
unknown_read_data = currently_reading_data.copy()
|
||||
unknown_read_data['Exclusive Shelf'] = 'read'
|
||||
unknown_read_data['Date Read'] = ''
|
||||
unknown_read_data["Exclusive Shelf"] = "read"
|
||||
unknown_read_data["Date Read"] = ""
|
||||
|
||||
user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
job = models.ImportJob.objects.create(user=user)
|
||||
self.item_1 = models.ImportItem.objects.create(
|
||||
job=job, index=1, data=currently_reading_data)
|
||||
self.item_2 = models.ImportItem.objects.create(
|
||||
job=job, index=2, data=read_data)
|
||||
job=job, index=1, data=currently_reading_data
|
||||
)
|
||||
self.item_2 = models.ImportItem.objects.create(job=job, index=2, data=read_data)
|
||||
self.item_3 = models.ImportItem.objects.create(
|
||||
job=job, index=3, data=unknown_read_data)
|
||||
|
||||
job=job, index=3, data=unknown_read_data
|
||||
)
|
||||
|
||||
def test_isbn(self):
|
||||
''' it unquotes the isbn13 field from data '''
|
||||
expected = '9780356506999'
|
||||
""" it unquotes the isbn13 field from data """
|
||||
expected = "9780356506999"
|
||||
item = models.ImportItem.objects.get(index=1)
|
||||
self.assertEqual(item.isbn, expected)
|
||||
|
||||
|
||||
def test_shelf(self):
|
||||
''' converts to the local shelf typology '''
|
||||
expected = 'reading'
|
||||
""" converts to the local shelf typology """
|
||||
expected = "reading"
|
||||
self.assertEqual(self.item_1.shelf, expected)
|
||||
|
||||
|
||||
def test_date_added(self):
|
||||
''' converts to the local shelf typology '''
|
||||
""" converts to the local shelf typology """
|
||||
expected = datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
|
||||
item = models.ImportItem.objects.get(index=1)
|
||||
self.assertEqual(item.date_added, expected)
|
||||
|
||||
|
||||
def test_date_read(self):
|
||||
''' converts to the local shelf typology '''
|
||||
""" converts to the local shelf typology """
|
||||
expected = datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc)
|
||||
item = models.ImportItem.objects.get(index=2)
|
||||
self.assertEqual(item.date_read, expected)
|
||||
|
||||
|
||||
def test_currently_reading_reads(self):
|
||||
''' infer currently reading dates where available '''
|
||||
expected = [models.ReadThrough(
|
||||
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
|
||||
)]
|
||||
""" infer currently reading dates where available """
|
||||
expected = [
|
||||
models.ReadThrough(
|
||||
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
|
||||
)
|
||||
]
|
||||
actual = models.ImportItem.objects.get(index=1)
|
||||
self.assertEqual(actual.reads[0].start_date, expected[0].start_date)
|
||||
self.assertEqual(actual.reads[0].finish_date, expected[0].finish_date)
|
||||
|
||||
def test_read_reads(self):
|
||||
''' infer read dates where available '''
|
||||
""" infer read dates where available """
|
||||
actual = self.item_2
|
||||
self.assertEqual(
|
||||
actual.reads[0].start_date,
|
||||
datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))
|
||||
datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
self.assertEqual(
|
||||
actual.reads[0].finish_date,
|
||||
datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc))
|
||||
datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
def test_unread_reads(self):
|
||||
''' handle books with no read dates '''
|
||||
""" handle books with no read dates """
|
||||
expected = []
|
||||
actual = models.ImportItem.objects.get(index=3)
|
||||
self.assertEqual(actual.reads, expected)
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_get_book_from_isbn(self):
|
||||
''' search and load books by isbn (9780356506999) '''
|
||||
""" search and load books by isbn (9780356506999) """
|
||||
connector_info = models.Connector.objects.create(
|
||||
identifier='openlibrary.org',
|
||||
name='OpenLibrary',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://openlibrary.org',
|
||||
books_url='https://openlibrary.org',
|
||||
covers_url='https://covers.openlibrary.org',
|
||||
search_url='https://openlibrary.org/search?q=',
|
||||
identifier="openlibrary.org",
|
||||
name="OpenLibrary",
|
||||
connector_file="openlibrary",
|
||||
base_url="https://openlibrary.org",
|
||||
books_url="https://openlibrary.org",
|
||||
covers_url="https://covers.openlibrary.org",
|
||||
search_url="https://openlibrary.org/search?q=",
|
||||
priority=3,
|
||||
)
|
||||
connector = connector_manager.load_connector(connector_info)
|
||||
result = SearchResult(
|
||||
title='Test Result',
|
||||
key='https://openlibrary.org/works/OL1234W',
|
||||
author='An Author',
|
||||
year='1980',
|
||||
title="Test Result",
|
||||
key="https://openlibrary.org/works/OL1234W",
|
||||
author="An Author",
|
||||
year="1980",
|
||||
connector=connector,
|
||||
)
|
||||
|
||||
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ol_edition.json')
|
||||
datafile = pathlib.Path(__file__).parent.joinpath("../data/ol_edition.json")
|
||||
bookdata = json.loads(datafile.read_bytes())
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL1234W',
|
||||
"https://openlibrary.org/works/OL1234W",
|
||||
json=bookdata,
|
||||
status=200)
|
||||
status=200,
|
||||
)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL15832982W',
|
||||
"https://openlibrary.org/works/OL15832982W",
|
||||
json=bookdata,
|
||||
status=200)
|
||||
status=200,
|
||||
)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/authors/OL382982A',
|
||||
json={'name': 'test author'},
|
||||
status=200)
|
||||
"https://openlibrary.org/authors/OL382982A",
|
||||
json={"name": "test author"},
|
||||
status=200,
|
||||
)
|
||||
|
||||
with patch(
|
||||
'bookwyrm.connectors.abstract_connector.load_more_data.delay'):
|
||||
with patch("bookwyrm.connectors.abstract_connector.load_more_data.delay"):
|
||||
with patch(
|
||||
'bookwyrm.connectors.connector_manager.first_search_result'
|
||||
) as search:
|
||||
"bookwyrm.connectors.connector_manager.first_search_result"
|
||||
) as search:
|
||||
search.return_value = result
|
||||
with patch('bookwyrm.connectors.openlibrary.Connector.' \
|
||||
'get_authors_from_data'):
|
||||
with patch(
|
||||
"bookwyrm.connectors.openlibrary.Connector." "get_authors_from_data"
|
||||
):
|
||||
book = self.item_1.get_book_from_isbn()
|
||||
|
||||
self.assertEqual(book.title, 'Sabriel')
|
||||
self.assertEqual(book.title, "Sabriel")
|
||||
|
|
|
@ -1,43 +1,41 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
|
||||
from bookwyrm import models, settings
|
||||
|
||||
|
||||
@patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay')
|
||||
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
|
||||
class List(TestCase):
|
||||
''' some activitypub oddness ahead '''
|
||||
""" some activitypub oddness ahead """
|
||||
|
||||
def setUp(self):
|
||||
''' look, a list '''
|
||||
""" look, a list """
|
||||
self.user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'):
|
||||
self.list = models.List.objects.create(
|
||||
name='Test List', user=self.user)
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
self.list = models.List.objects.create(name="Test List", user=self.user)
|
||||
|
||||
def test_remote_id(self, _):
|
||||
''' shelves use custom remote ids '''
|
||||
expected_id = 'https://%s/list/%d' % \
|
||||
(settings.DOMAIN, self.list.id)
|
||||
""" shelves use custom remote ids """
|
||||
expected_id = "https://%s/list/%d" % (settings.DOMAIN, self.list.id)
|
||||
self.assertEqual(self.list.get_remote_id(), expected_id)
|
||||
|
||||
|
||||
def test_to_activity(self, _):
|
||||
''' jsonify it '''
|
||||
""" jsonify it """
|
||||
activity_json = self.list.to_activity()
|
||||
self.assertIsInstance(activity_json, dict)
|
||||
self.assertEqual(activity_json['id'], self.list.remote_id)
|
||||
self.assertEqual(activity_json['totalItems'], 0)
|
||||
self.assertEqual(activity_json['type'], 'BookList')
|
||||
self.assertEqual(activity_json['name'], 'Test List')
|
||||
self.assertEqual(activity_json['owner'], self.user.remote_id)
|
||||
self.assertEqual(activity_json["id"], self.list.remote_id)
|
||||
self.assertEqual(activity_json["totalItems"], 0)
|
||||
self.assertEqual(activity_json["type"], "BookList")
|
||||
self.assertEqual(activity_json["name"], "Test List")
|
||||
self.assertEqual(activity_json["owner"], self.user.remote_id)
|
||||
|
||||
def test_list_item(self, _):
|
||||
''' a list entry '''
|
||||
work = models.Work.objects.create(title='hello')
|
||||
book = models.Edition.objects.create(title='hi', parent_work=work)
|
||||
""" a list entry """
|
||||
work = models.Work.objects.create(title="hello")
|
||||
book = models.Edition.objects.create(title="hi", parent_work=work)
|
||||
item = models.ListItem.objects.create(
|
||||
book_list=self.list,
|
||||
book=book,
|
||||
|
@ -47,11 +45,11 @@ class List(TestCase):
|
|||
self.assertTrue(item.approved)
|
||||
|
||||
add_activity = item.to_add_activity()
|
||||
self.assertEqual(add_activity['actor'], self.user.remote_id)
|
||||
self.assertEqual(add_activity['object']['id'], book.remote_id)
|
||||
self.assertEqual(add_activity['target'], self.list.remote_id)
|
||||
self.assertEqual(add_activity["actor"], self.user.remote_id)
|
||||
self.assertEqual(add_activity["object"]["id"], book.remote_id)
|
||||
self.assertEqual(add_activity["target"], self.list.remote_id)
|
||||
|
||||
remove_activity = item.to_remove_activity()
|
||||
self.assertEqual(remove_activity['actor'], self.user.remote_id)
|
||||
self.assertEqual(remove_activity['object']['id'], book.remote_id)
|
||||
self.assertEqual(remove_activity['target'], self.list.remote_id)
|
||||
self.assertEqual(remove_activity["actor"], self.user.remote_id)
|
||||
self.assertEqual(remove_activity["object"]["id"], book.remote_id)
|
||||
self.assertEqual(remove_activity["target"], self.list.remote_id)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from django.test import TestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
@ -6,39 +6,36 @@ from bookwyrm import models, settings
|
|||
|
||||
|
||||
class ReadThrough(TestCase):
|
||||
''' some activitypub oddness ahead '''
|
||||
def setUp(self):
|
||||
''' look, a shelf '''
|
||||
self.user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
""" some activitypub oddness ahead """
|
||||
|
||||
self.work = models.Work.objects.create(
|
||||
title='Example Work'
|
||||
def setUp(self):
|
||||
""" look, a shelf """
|
||||
self.user = models.User.objects.create_user(
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
|
||||
self.work = models.Work.objects.create(title="Example Work")
|
||||
|
||||
self.edition = models.Edition.objects.create(
|
||||
title='Example Edition',
|
||||
parent_work=self.work
|
||||
title="Example Edition", parent_work=self.work
|
||||
)
|
||||
self.work.default_edition = self.edition
|
||||
self.work.save()
|
||||
|
||||
self.readthrough = models.ReadThrough.objects.create(
|
||||
user=self.user,
|
||||
book=self.edition)
|
||||
user=self.user, book=self.edition
|
||||
)
|
||||
|
||||
def test_progress_update(self):
|
||||
''' Test progress updates '''
|
||||
self.readthrough.create_update() # No-op, no progress yet
|
||||
""" Test progress updates """
|
||||
self.readthrough.create_update() # No-op, no progress yet
|
||||
self.readthrough.progress = 10
|
||||
self.readthrough.create_update()
|
||||
self.readthrough.progress = 20
|
||||
self.readthrough.progress_mode = models.ProgressMode.PERCENT
|
||||
self.readthrough.create_update()
|
||||
|
||||
updates = self.readthrough.progressupdate_set \
|
||||
.order_by('created_date').all()
|
||||
updates = self.readthrough.progressupdate_set.order_by("created_date").all()
|
||||
self.assertEqual(len(updates), 2)
|
||||
self.assertEqual(updates[0].progress, 10)
|
||||
self.assertEqual(updates[0].mode, models.ProgressMode.PAGE)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
|
||||
|
@ -6,87 +6,79 @@ from bookwyrm import models
|
|||
|
||||
|
||||
class Relationship(TestCase):
|
||||
''' following, blocking, stuff like that '''
|
||||
""" following, blocking, stuff like that """
|
||||
|
||||
def setUp(self):
|
||||
''' we need some users for this '''
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
""" we need some users for this """
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
self.remote_user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'ratword',
|
||||
"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',
|
||||
remote_id="https://example.com/users/rat",
|
||||
inbox="https://example.com/users/rat/inbox",
|
||||
outbox="https://example.com/users/rat/outbox",
|
||||
)
|
||||
self.local_user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.com', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
self.local_user.remote_id = 'http://local.com/user/mouse'
|
||||
"mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
self.local_user.remote_id = "http://local.com/user/mouse"
|
||||
self.local_user.save(broadcast=False)
|
||||
|
||||
|
||||
def test_user_follows_from_request(self):
|
||||
''' convert a follow request into a follow '''
|
||||
""" convert a follow request into a follow """
|
||||
real_broadcast = models.UserFollowRequest.broadcast
|
||||
|
||||
def mock_broadcast(_, activity, user):
|
||||
''' introspect what's being sent out '''
|
||||
""" introspect what's being sent out """
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Follow')
|
||||
self.assertEqual(activity["type"], "Follow")
|
||||
|
||||
models.UserFollowRequest.broadcast = mock_broadcast
|
||||
request = models.UserFollowRequest.objects.create(
|
||||
user_subject=self.local_user,
|
||||
user_object=self.remote_user
|
||||
user_subject=self.local_user, user_object=self.remote_user
|
||||
)
|
||||
self.assertEqual(
|
||||
request.remote_id,
|
||||
'http://local.com/user/mouse#follows/%d' % request.id
|
||||
request.remote_id, "http://local.com/user/mouse#follows/%d" % request.id
|
||||
)
|
||||
self.assertEqual(request.status, 'follow_request')
|
||||
self.assertEqual(request.status, "follow_request")
|
||||
|
||||
rel = models.UserFollows.from_request(request)
|
||||
self.assertEqual(
|
||||
rel.remote_id,
|
||||
'http://local.com/user/mouse#follows/%d' % request.id
|
||||
rel.remote_id, "http://local.com/user/mouse#follows/%d" % request.id
|
||||
)
|
||||
self.assertEqual(rel.status, 'follows')
|
||||
self.assertEqual(rel.status, "follows")
|
||||
self.assertEqual(rel.user_subject, self.local_user)
|
||||
self.assertEqual(rel.user_object, self.remote_user)
|
||||
models.UserFollowRequest.broadcast = real_broadcast
|
||||
|
||||
|
||||
|
||||
def test_user_follows_from_request_custom_remote_id(self):
|
||||
''' store a specific remote id for a relationship provided by remote '''
|
||||
with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'):
|
||||
""" store a specific remote id for a relationship provided by remote """
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
request = models.UserFollowRequest.objects.create(
|
||||
user_subject=self.local_user,
|
||||
user_object=self.remote_user,
|
||||
remote_id='http://antoher.server/sdkfhskdjf/23'
|
||||
remote_id="http://antoher.server/sdkfhskdjf/23",
|
||||
)
|
||||
self.assertEqual(
|
||||
request.remote_id,
|
||||
'http://antoher.server/sdkfhskdjf/23'
|
||||
)
|
||||
self.assertEqual(request.status, 'follow_request')
|
||||
self.assertEqual(request.remote_id, "http://antoher.server/sdkfhskdjf/23")
|
||||
self.assertEqual(request.status, "follow_request")
|
||||
|
||||
rel = models.UserFollows.from_request(request)
|
||||
self.assertEqual(
|
||||
rel.remote_id,
|
||||
'http://antoher.server/sdkfhskdjf/23'
|
||||
)
|
||||
self.assertEqual(rel.status, 'follows')
|
||||
self.assertEqual(rel.remote_id, "http://antoher.server/sdkfhskdjf/23")
|
||||
self.assertEqual(rel.status, "follows")
|
||||
self.assertEqual(rel.user_subject, self.local_user)
|
||||
self.assertEqual(rel.user_object, self.remote_user)
|
||||
|
||||
|
||||
def test_follow_request_activity(self):
|
||||
''' accept a request and make it a relationship '''
|
||||
""" accept a request and make it a relationship """
|
||||
real_broadcast = models.UserFollowRequest.broadcast
|
||||
|
||||
def mock_broadcast(_, activity, user):
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object'], self.remote_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Follow')
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"], self.remote_user.remote_id)
|
||||
self.assertEqual(activity["type"], "Follow")
|
||||
|
||||
models.UserFollowRequest.broadcast = mock_broadcast
|
||||
models.UserFollowRequest.objects.create(
|
||||
|
@ -95,15 +87,15 @@ class Relationship(TestCase):
|
|||
)
|
||||
models.UserFollowRequest.broadcast = real_broadcast
|
||||
|
||||
|
||||
def test_follow_request_accept(self):
|
||||
''' accept a request and make it a relationship '''
|
||||
""" accept a request and make it a relationship """
|
||||
real_broadcast = models.UserFollowRequest.broadcast
|
||||
|
||||
def mock_broadcast(_, activity, user):
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Accept')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object']['id'], 'https://www.hi.com/')
|
||||
self.assertEqual(activity["type"], "Accept")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["id"], "https://www.hi.com/")
|
||||
|
||||
self.local_user.manually_approves_followers = True
|
||||
self.local_user.save(broadcast=False)
|
||||
|
@ -111,7 +103,7 @@ class Relationship(TestCase):
|
|||
request = models.UserFollowRequest.objects.create(
|
||||
user_subject=self.remote_user,
|
||||
user_object=self.local_user,
|
||||
remote_id='https://www.hi.com/'
|
||||
remote_id="https://www.hi.com/",
|
||||
)
|
||||
request.accept()
|
||||
|
||||
|
@ -122,16 +114,15 @@ class Relationship(TestCase):
|
|||
self.assertEqual(rel.user_object, self.local_user)
|
||||
models.UserFollowRequest.broadcast = real_broadcast
|
||||
|
||||
|
||||
def test_follow_request_reject(self):
|
||||
''' accept a request and make it a relationship '''
|
||||
""" accept a request and make it a relationship """
|
||||
real_broadcast = models.UserFollowRequest.broadcast
|
||||
|
||||
def mock_reject(_, activity, user):
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Reject')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(
|
||||
activity['object']['id'], request.remote_id)
|
||||
self.assertEqual(activity["type"], "Reject")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["id"], request.remote_id)
|
||||
|
||||
models.UserFollowRequest.broadcast = mock_reject
|
||||
self.local_user.manually_approves_followers = True
|
||||
|
|
|
@ -1,116 +1,120 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from django.test import TestCase
|
||||
|
||||
from bookwyrm import models, settings
|
||||
|
||||
|
||||
#pylint: disable=unused-argument
|
||||
# pylint: disable=unused-argument
|
||||
class Shelf(TestCase):
|
||||
''' some activitypub oddness ahead '''
|
||||
""" some activitypub oddness ahead """
|
||||
|
||||
def setUp(self):
|
||||
''' look, a shelf '''
|
||||
""" look, a shelf """
|
||||
self.local_user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
work = models.Work.objects.create(title='Test Work')
|
||||
self.book = models.Edition.objects.create(
|
||||
title='test book',
|
||||
parent_work=work)
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
work = models.Work.objects.create(title="Test Work")
|
||||
self.book = models.Edition.objects.create(title="test book", parent_work=work)
|
||||
|
||||
def test_remote_id(self):
|
||||
''' shelves use custom remote ids '''
|
||||
""" shelves use custom remote ids """
|
||||
real_broadcast = models.Shelf.broadcast
|
||||
|
||||
def broadcast_mock(_, activity, user, **kwargs):
|
||||
''' nah '''
|
||||
""" nah """
|
||||
|
||||
models.Shelf.broadcast = broadcast_mock
|
||||
shelf = models.Shelf.objects.create(
|
||||
name='Test Shelf', identifier='test-shelf',
|
||||
user=self.local_user)
|
||||
expected_id = 'https://%s/user/mouse/shelf/test-shelf' % settings.DOMAIN
|
||||
name="Test Shelf", identifier="test-shelf", user=self.local_user
|
||||
)
|
||||
expected_id = "https://%s/user/mouse/shelf/test-shelf" % settings.DOMAIN
|
||||
self.assertEqual(shelf.get_remote_id(), expected_id)
|
||||
models.Shelf.broadcast = real_broadcast
|
||||
|
||||
|
||||
def test_to_activity(self):
|
||||
''' jsonify it '''
|
||||
""" jsonify it """
|
||||
real_broadcast = models.Shelf.broadcast
|
||||
|
||||
def empty_mock(_, activity, user, **kwargs):
|
||||
''' nah '''
|
||||
""" nah """
|
||||
|
||||
models.Shelf.broadcast = empty_mock
|
||||
shelf = models.Shelf.objects.create(
|
||||
name='Test Shelf', identifier='test-shelf',
|
||||
user=self.local_user)
|
||||
name="Test Shelf", identifier="test-shelf", user=self.local_user
|
||||
)
|
||||
activity_json = shelf.to_activity()
|
||||
self.assertIsInstance(activity_json, dict)
|
||||
self.assertEqual(activity_json['id'], shelf.remote_id)
|
||||
self.assertEqual(activity_json['totalItems'], 0)
|
||||
self.assertEqual(activity_json['type'], 'Shelf')
|
||||
self.assertEqual(activity_json['name'], 'Test Shelf')
|
||||
self.assertEqual(activity_json['owner'], self.local_user.remote_id)
|
||||
self.assertEqual(activity_json["id"], shelf.remote_id)
|
||||
self.assertEqual(activity_json["totalItems"], 0)
|
||||
self.assertEqual(activity_json["type"], "Shelf")
|
||||
self.assertEqual(activity_json["name"], "Test Shelf")
|
||||
self.assertEqual(activity_json["owner"], self.local_user.remote_id)
|
||||
models.Shelf.broadcast = real_broadcast
|
||||
|
||||
|
||||
def test_create_update_shelf(self):
|
||||
''' create and broadcast shelf creation '''
|
||||
""" create and broadcast shelf creation """
|
||||
real_broadcast = models.Shelf.broadcast
|
||||
|
||||
def create_mock(_, activity, user, **kwargs):
|
||||
''' ok '''
|
||||
""" ok """
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Create')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object']['name'], 'Test Shelf')
|
||||
self.assertEqual(activity["type"], "Create")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["name"], "Test Shelf")
|
||||
|
||||
models.Shelf.broadcast = create_mock
|
||||
|
||||
shelf = models.Shelf.objects.create(
|
||||
name='Test Shelf', identifier='test-shelf', user=self.local_user)
|
||||
name="Test Shelf", identifier="test-shelf", user=self.local_user
|
||||
)
|
||||
|
||||
def update_mock(_, activity, user, **kwargs):
|
||||
''' ok '''
|
||||
""" ok """
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Update')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object']['name'], 'arthur russel')
|
||||
self.assertEqual(activity["type"], "Update")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["name"], "arthur russel")
|
||||
|
||||
models.Shelf.broadcast = update_mock
|
||||
|
||||
shelf.name = 'arthur russel'
|
||||
shelf.name = "arthur russel"
|
||||
shelf.save()
|
||||
self.assertEqual(shelf.name, 'arthur russel')
|
||||
self.assertEqual(shelf.name, "arthur russel")
|
||||
models.Shelf.broadcast = real_broadcast
|
||||
|
||||
|
||||
def test_shelve(self):
|
||||
''' create and broadcast shelf creation '''
|
||||
""" create and broadcast shelf creation """
|
||||
real_broadcast = models.Shelf.broadcast
|
||||
real_shelfbook_broadcast = models.ShelfBook.broadcast
|
||||
|
||||
def add_mock(_, activity, user, **kwargs):
|
||||
''' ok '''
|
||||
""" ok """
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Add')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object']['id'], self.book.remote_id)
|
||||
self.assertEqual(activity['target'], shelf.remote_id)
|
||||
self.assertEqual(activity["type"], "Add")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["id"], self.book.remote_id)
|
||||
self.assertEqual(activity["target"], shelf.remote_id)
|
||||
|
||||
def remove_mock(_, activity, user, **kwargs):
|
||||
''' ok '''
|
||||
""" ok """
|
||||
self.assertEqual(user.remote_id, self.local_user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Remove')
|
||||
self.assertEqual(activity['actor'], self.local_user.remote_id)
|
||||
self.assertEqual(activity['object']['id'], self.book.remote_id)
|
||||
self.assertEqual(activity['target'], shelf.remote_id)
|
||||
self.assertEqual(activity["type"], "Remove")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(activity["object"]["id"], self.book.remote_id)
|
||||
self.assertEqual(activity["target"], shelf.remote_id)
|
||||
|
||||
def empty_mock(_, activity, user, **kwargs):
|
||||
''' nah '''
|
||||
""" nah """
|
||||
|
||||
models.Shelf.broadcast = empty_mock
|
||||
shelf = models.Shelf.objects.create(
|
||||
name='Test Shelf', identifier='test-shelf', user=self.local_user)
|
||||
name="Test Shelf", identifier="test-shelf", user=self.local_user
|
||||
)
|
||||
|
||||
models.ShelfBook.broadcast = add_mock
|
||||
shelf_book = models.ShelfBook.objects.create(
|
||||
shelf=shelf,
|
||||
user=self.local_user,
|
||||
book=self.book)
|
||||
shelf=shelf, user=self.local_user, book=self.book
|
||||
)
|
||||
self.assertEqual(shelf.books.first(), self.book)
|
||||
|
||||
models.ShelfBook.broadcast = remove_mock
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from unittest.mock import patch
|
||||
from io import BytesIO
|
||||
import pathlib
|
||||
|
@ -12,44 +12,45 @@ from django.utils import timezone
|
|||
from bookwyrm import models, settings
|
||||
|
||||
|
||||
@patch('bookwyrm.models.Status.broadcast')
|
||||
@patch("bookwyrm.models.Status.broadcast")
|
||||
class Status(TestCase):
|
||||
''' lotta types of statuses '''
|
||||
""" lotta types of statuses """
|
||||
|
||||
def setUp(self):
|
||||
''' useful things for creating a status '''
|
||||
""" useful things for creating a status """
|
||||
self.user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
self.book = models.Edition.objects.create(title='Test Edition')
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
self.book = models.Edition.objects.create(title="Test Edition")
|
||||
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
'../../static/images/default_avi.jpg')
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
with patch('bookwyrm.models.Status.broadcast'):
|
||||
with patch("bookwyrm.models.Status.broadcast"):
|
||||
image.save(output, format=image.format)
|
||||
self.book.cover.save(
|
||||
'test.jpg',
|
||||
ContentFile(output.getvalue())
|
||||
)
|
||||
self.book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
||||
|
||||
def test_status_generated_fields(self, _):
|
||||
''' setting remote id '''
|
||||
status = models.Status.objects.create(content='bleh', user=self.user)
|
||||
expected_id = 'https://%s/user/mouse/status/%d' % \
|
||||
(settings.DOMAIN, status.id)
|
||||
""" setting remote id """
|
||||
status = models.Status.objects.create(content="bleh", user=self.user)
|
||||
expected_id = "https://%s/user/mouse/status/%d" % (settings.DOMAIN, status.id)
|
||||
self.assertEqual(status.remote_id, expected_id)
|
||||
self.assertEqual(status.privacy, 'public')
|
||||
self.assertEqual(status.privacy, "public")
|
||||
|
||||
def test_replies(self, _):
|
||||
''' get a list of replies '''
|
||||
parent = models.Status.objects.create(content='hi', user=self.user)
|
||||
""" get a list of replies """
|
||||
parent = models.Status.objects.create(content="hi", user=self.user)
|
||||
child = models.Status.objects.create(
|
||||
content='hello', reply_parent=parent, user=self.user)
|
||||
content="hello", reply_parent=parent, user=self.user
|
||||
)
|
||||
models.Review.objects.create(
|
||||
content='hey', reply_parent=parent, user=self.user, book=self.book)
|
||||
content="hey", reply_parent=parent, user=self.user, book=self.book
|
||||
)
|
||||
models.Status.objects.create(
|
||||
content='hi hello', reply_parent=child, user=self.user)
|
||||
content="hi hello", reply_parent=child, user=self.user
|
||||
)
|
||||
|
||||
replies = models.Status.replies(parent)
|
||||
self.assertEqual(replies.count(), 2)
|
||||
|
@ -58,199 +59,228 @@ class Status(TestCase):
|
|||
self.assertIsInstance(replies.last(), models.Review)
|
||||
|
||||
def test_status_type(self, _):
|
||||
''' class name '''
|
||||
self.assertEqual(models.Status().status_type, 'Note')
|
||||
self.assertEqual(models.Review().status_type, 'Review')
|
||||
self.assertEqual(models.Quotation().status_type, 'Quotation')
|
||||
self.assertEqual(models.Comment().status_type, 'Comment')
|
||||
self.assertEqual(models.Boost().status_type, 'Announce')
|
||||
""" class name """
|
||||
self.assertEqual(models.Status().status_type, "Note")
|
||||
self.assertEqual(models.Review().status_type, "Review")
|
||||
self.assertEqual(models.Quotation().status_type, "Quotation")
|
||||
self.assertEqual(models.Comment().status_type, "Comment")
|
||||
self.assertEqual(models.Boost().status_type, "Announce")
|
||||
|
||||
def test_boostable(self, _):
|
||||
''' can a status be boosted, based on privacy '''
|
||||
self.assertTrue(models.Status(privacy='public').boostable)
|
||||
self.assertTrue(models.Status(privacy='unlisted').boostable)
|
||||
self.assertFalse(models.Status(privacy='followers').boostable)
|
||||
self.assertFalse(models.Status(privacy='direct').boostable)
|
||||
""" can a status be boosted, based on privacy """
|
||||
self.assertTrue(models.Status(privacy="public").boostable)
|
||||
self.assertTrue(models.Status(privacy="unlisted").boostable)
|
||||
self.assertFalse(models.Status(privacy="followers").boostable)
|
||||
self.assertFalse(models.Status(privacy="direct").boostable)
|
||||
|
||||
def test_to_replies(self, _):
|
||||
''' activitypub replies collection '''
|
||||
parent = models.Status.objects.create(content='hi', user=self.user)
|
||||
""" activitypub replies collection """
|
||||
parent = models.Status.objects.create(content="hi", user=self.user)
|
||||
child = models.Status.objects.create(
|
||||
content='hello', reply_parent=parent, user=self.user)
|
||||
content="hello", reply_parent=parent, user=self.user
|
||||
)
|
||||
models.Review.objects.create(
|
||||
content='hey', reply_parent=parent, user=self.user, book=self.book)
|
||||
content="hey", reply_parent=parent, user=self.user, book=self.book
|
||||
)
|
||||
models.Status.objects.create(
|
||||
content='hi hello', reply_parent=child, user=self.user)
|
||||
content="hi hello", reply_parent=child, user=self.user
|
||||
)
|
||||
|
||||
replies = parent.to_replies()
|
||||
self.assertEqual(replies['id'], '%s/replies' % parent.remote_id)
|
||||
self.assertEqual(replies['totalItems'], 2)
|
||||
self.assertEqual(replies["id"], "%s/replies" % parent.remote_id)
|
||||
self.assertEqual(replies["totalItems"], 2)
|
||||
|
||||
def test_status_to_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
status = models.Status.objects.create(
|
||||
content='test content', user=self.user)
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Status.objects.create(content="test content", user=self.user)
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Note')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['sensitive'], False)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Note")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["sensitive"], False)
|
||||
|
||||
def test_status_to_activity_tombstone(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Status.objects.create(
|
||||
content='test content', user=self.user,
|
||||
deleted=True, deleted_date=timezone.now())
|
||||
content="test content",
|
||||
user=self.user,
|
||||
deleted=True,
|
||||
deleted_date=timezone.now(),
|
||||
)
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Tombstone')
|
||||
self.assertFalse(hasattr(activity, 'content'))
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Tombstone")
|
||||
self.assertFalse(hasattr(activity, "content"))
|
||||
|
||||
def test_status_to_pure_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
status = models.Status.objects.create(
|
||||
content='test content', user=self.user)
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Status.objects.create(content="test content", user=self.user)
|
||||
activity = status.to_activity(pure=True)
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Note')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['sensitive'], False)
|
||||
self.assertEqual(activity['attachment'], [])
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Note")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["sensitive"], False)
|
||||
self.assertEqual(activity["attachment"], [])
|
||||
|
||||
def test_generated_note_to_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.GeneratedNote.objects.create(
|
||||
content='test content', user=self.user)
|
||||
content="test content", user=self.user
|
||||
)
|
||||
status.mention_books.set([self.book])
|
||||
status.mention_users.set([self.user])
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'GeneratedNote')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['sensitive'], False)
|
||||
self.assertEqual(len(activity['tag']), 2)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "GeneratedNote")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["sensitive"], False)
|
||||
self.assertEqual(len(activity["tag"]), 2)
|
||||
|
||||
def test_generated_note_to_pure_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.GeneratedNote.objects.create(
|
||||
content='test content', user=self.user)
|
||||
content="test content", user=self.user
|
||||
)
|
||||
status.mention_books.set([self.book])
|
||||
status.mention_users.set([self.user])
|
||||
activity = status.to_activity(pure=True)
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(
|
||||
activity['content'],
|
||||
'mouse test content <a href="%s">"Test Edition"</a>' % \
|
||||
self.book.remote_id)
|
||||
self.assertEqual(len(activity['tag']), 2)
|
||||
self.assertEqual(activity['type'], 'Note')
|
||||
self.assertEqual(activity['sensitive'], False)
|
||||
self.assertIsInstance(activity['attachment'], list)
|
||||
self.assertEqual(activity['attachment'][0].type, 'Image')
|
||||
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
|
||||
(settings.DOMAIN, self.book.cover.url))
|
||||
activity["content"],
|
||||
'mouse test content <a href="%s">"Test Edition"</a>' % self.book.remote_id,
|
||||
)
|
||||
self.assertEqual(len(activity["tag"]), 2)
|
||||
self.assertEqual(activity["type"], "Note")
|
||||
self.assertEqual(activity["sensitive"], False)
|
||||
self.assertIsInstance(activity["attachment"], list)
|
||||
self.assertEqual(activity["attachment"][0].type, "Image")
|
||||
self.assertEqual(
|
||||
activity['attachment'][0].name, 'Test Edition')
|
||||
activity["attachment"][0].url,
|
||||
"https://%s%s" % (settings.DOMAIN, self.book.cover.url),
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].name, "Test Edition")
|
||||
|
||||
def test_comment_to_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Comment.objects.create(
|
||||
content='test content', user=self.user, book=self.book)
|
||||
content="test content", user=self.user, book=self.book
|
||||
)
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Comment')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['inReplyToBook'], self.book.remote_id)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Comment")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["inReplyToBook"], self.book.remote_id)
|
||||
|
||||
def test_comment_to_pure_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Comment.objects.create(
|
||||
content='test content', user=self.user, book=self.book)
|
||||
content="test content", user=self.user, book=self.book
|
||||
)
|
||||
activity = status.to_activity(pure=True)
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Note')
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Note")
|
||||
self.assertEqual(
|
||||
activity['content'],
|
||||
'test content<p>(comment on <a href="%s">"Test Edition"</a>)</p>' %
|
||||
self.book.remote_id)
|
||||
self.assertEqual(activity['attachment'][0].type, 'Image')
|
||||
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
|
||||
(settings.DOMAIN, self.book.cover.url))
|
||||
activity["content"],
|
||||
'test content<p>(comment on <a href="%s">"Test Edition"</a>)</p>'
|
||||
% self.book.remote_id,
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].type, "Image")
|
||||
self.assertEqual(
|
||||
activity['attachment'][0].name, 'Test Edition')
|
||||
activity["attachment"][0].url,
|
||||
"https://%s%s" % (settings.DOMAIN, self.book.cover.url),
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].name, "Test Edition")
|
||||
|
||||
def test_quotation_to_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Quotation.objects.create(
|
||||
quote='a sickening sense', content='test content',
|
||||
user=self.user, book=self.book)
|
||||
quote="a sickening sense",
|
||||
content="test content",
|
||||
user=self.user,
|
||||
book=self.book,
|
||||
)
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Quotation')
|
||||
self.assertEqual(activity['quote'], 'a sickening sense')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['inReplyToBook'], self.book.remote_id)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Quotation")
|
||||
self.assertEqual(activity["quote"], "a sickening sense")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["inReplyToBook"], self.book.remote_id)
|
||||
|
||||
def test_quotation_to_pure_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Quotation.objects.create(
|
||||
quote='a sickening sense', content='test content',
|
||||
user=self.user, book=self.book)
|
||||
quote="a sickening sense",
|
||||
content="test content",
|
||||
user=self.user,
|
||||
book=self.book,
|
||||
)
|
||||
activity = status.to_activity(pure=True)
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Note')
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Note")
|
||||
self.assertEqual(
|
||||
activity['content'],
|
||||
'a sickening sense <p>-- <a href="%s">"Test Edition"</a></p>' \
|
||||
'test content' % self.book.remote_id)
|
||||
self.assertEqual(activity['attachment'][0].type, 'Image')
|
||||
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
|
||||
(settings.DOMAIN, self.book.cover.url))
|
||||
activity["content"],
|
||||
'a sickening sense <p>-- <a href="%s">"Test Edition"</a></p>'
|
||||
"test content" % self.book.remote_id,
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].type, "Image")
|
||||
self.assertEqual(
|
||||
activity['attachment'][0].name, 'Test Edition')
|
||||
activity["attachment"][0].url,
|
||||
"https://%s%s" % (settings.DOMAIN, self.book.cover.url),
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].name, "Test Edition")
|
||||
|
||||
def test_review_to_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Review.objects.create(
|
||||
name='Review name', content='test content', rating=3,
|
||||
user=self.user, book=self.book)
|
||||
name="Review name",
|
||||
content="test content",
|
||||
rating=3,
|
||||
user=self.user,
|
||||
book=self.book,
|
||||
)
|
||||
activity = status.to_activity()
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Review')
|
||||
self.assertEqual(activity['rating'], 3)
|
||||
self.assertEqual(activity['name'], 'Review name')
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['inReplyToBook'], self.book.remote_id)
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Review")
|
||||
self.assertEqual(activity["rating"], 3)
|
||||
self.assertEqual(activity["name"], "Review name")
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["inReplyToBook"], self.book.remote_id)
|
||||
|
||||
def test_review_to_pure_activity(self, _):
|
||||
''' subclass of the base model version with a "pure" serializer '''
|
||||
""" subclass of the base model version with a "pure" serializer """
|
||||
status = models.Review.objects.create(
|
||||
name='Review name', content='test content', rating=3,
|
||||
user=self.user, book=self.book)
|
||||
name="Review name",
|
||||
content="test content",
|
||||
rating=3,
|
||||
user=self.user,
|
||||
book=self.book,
|
||||
)
|
||||
activity = status.to_activity(pure=True)
|
||||
self.assertEqual(activity['id'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Article')
|
||||
self.assertEqual(activity["id"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Article")
|
||||
self.assertEqual(
|
||||
activity['name'], 'Review of "%s" (3 stars): Review name' \
|
||||
% self.book.title)
|
||||
self.assertEqual(activity['content'], 'test content')
|
||||
self.assertEqual(activity['attachment'][0].type, 'Image')
|
||||
self.assertEqual(activity['attachment'][0].url, 'https://%s%s' % \
|
||||
(settings.DOMAIN, self.book.cover.url))
|
||||
activity["name"], 'Review of "%s" (3 stars): Review name' % self.book.title
|
||||
)
|
||||
self.assertEqual(activity["content"], "test content")
|
||||
self.assertEqual(activity["attachment"][0].type, "Image")
|
||||
self.assertEqual(
|
||||
activity['attachment'][0].name, 'Test Edition')
|
||||
activity["attachment"][0].url,
|
||||
"https://%s%s" % (settings.DOMAIN, self.book.cover.url),
|
||||
)
|
||||
self.assertEqual(activity["attachment"][0].name, "Test Edition")
|
||||
|
||||
def test_favorite(self, _):
|
||||
''' fav a status '''
|
||||
""" fav a status """
|
||||
real_broadcast = models.Favorite.broadcast
|
||||
|
||||
def fav_broadcast_mock(_, activity, user):
|
||||
''' ok '''
|
||||
""" ok """
|
||||
self.assertEqual(user.remote_id, self.user.remote_id)
|
||||
self.assertEqual(activity['type'], 'Like')
|
||||
self.assertEqual(activity["type"], "Like")
|
||||
|
||||
models.Favorite.broadcast = fav_broadcast_mock
|
||||
|
||||
status = models.Status.objects.create(
|
||||
content='test content', user=self.user)
|
||||
status = models.Status.objects.create(content="test content", user=self.user)
|
||||
fav = models.Favorite.objects.create(status=status, user=self.user)
|
||||
|
||||
# can't fav a status twice
|
||||
|
@ -258,50 +288,47 @@ class Status(TestCase):
|
|||
models.Favorite.objects.create(status=status, user=self.user)
|
||||
|
||||
activity = fav.to_activity()
|
||||
self.assertEqual(activity['type'], 'Like')
|
||||
self.assertEqual(activity['actor'], self.user.remote_id)
|
||||
self.assertEqual(activity['object'], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Like")
|
||||
self.assertEqual(activity["actor"], self.user.remote_id)
|
||||
self.assertEqual(activity["object"], status.remote_id)
|
||||
models.Favorite.broadcast = real_broadcast
|
||||
|
||||
def test_boost(self, _):
|
||||
''' boosting, this one's a bit fussy '''
|
||||
status = models.Status.objects.create(
|
||||
content='test content', user=self.user)
|
||||
boost = models.Boost.objects.create(
|
||||
boosted_status=status, user=self.user)
|
||||
""" boosting, this one's a bit fussy """
|
||||
status = models.Status.objects.create(content="test content", user=self.user)
|
||||
boost = models.Boost.objects.create(boosted_status=status, user=self.user)
|
||||
activity = boost.to_activity()
|
||||
self.assertEqual(activity['actor'], self.user.remote_id)
|
||||
self.assertEqual(activity['object'], status.remote_id)
|
||||
self.assertEqual(activity['type'], 'Announce')
|
||||
self.assertEqual(activity["actor"], self.user.remote_id)
|
||||
self.assertEqual(activity["object"], status.remote_id)
|
||||
self.assertEqual(activity["type"], "Announce")
|
||||
self.assertEqual(activity, boost.to_activity(pure=True))
|
||||
|
||||
def test_notification(self, _):
|
||||
''' a simple model '''
|
||||
""" a simple model """
|
||||
notification = models.Notification.objects.create(
|
||||
user=self.user, notification_type='FAVORITE')
|
||||
user=self.user, notification_type="FAVORITE"
|
||||
)
|
||||
self.assertFalse(notification.read)
|
||||
|
||||
with self.assertRaises(IntegrityError):
|
||||
models.Notification.objects.create(
|
||||
user=self.user, notification_type='GLORB')
|
||||
|
||||
user=self.user, notification_type="GLORB"
|
||||
)
|
||||
|
||||
def test_create_broadcast(self, broadcast_mock):
|
||||
''' should send out two verions of a status on create '''
|
||||
models.Comment.objects.create(
|
||||
content='hi', user=self.user, book=self.book)
|
||||
""" should send out two verions of a status on create """
|
||||
models.Comment.objects.create(content="hi", user=self.user, book=self.book)
|
||||
self.assertEqual(broadcast_mock.call_count, 2)
|
||||
pure_call = broadcast_mock.call_args_list[0]
|
||||
bw_call = broadcast_mock.call_args_list[1]
|
||||
|
||||
self.assertEqual(pure_call[1]['software'], 'other')
|
||||
self.assertEqual(pure_call[1]["software"], "other")
|
||||
args = pure_call[0][0]
|
||||
self.assertEqual(args['type'], 'Create')
|
||||
self.assertEqual(args['object']['type'], 'Note')
|
||||
self.assertTrue('content' in args['object'])
|
||||
self.assertEqual(args["type"], "Create")
|
||||
self.assertEqual(args["object"]["type"], "Note")
|
||||
self.assertTrue("content" in args["object"])
|
||||
|
||||
|
||||
self.assertEqual(bw_call[1]['software'], 'bookwyrm')
|
||||
self.assertEqual(bw_call[1]["software"], "bookwyrm")
|
||||
args = bw_call[0][0]
|
||||
self.assertEqual(args['type'], 'Create')
|
||||
self.assertEqual(args['object']['type'], 'Comment')
|
||||
self.assertEqual(args["type"], "Create")
|
||||
self.assertEqual(args["object"]["type"], "Comment")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
''' testing models '''
|
||||
""" testing models """
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
|
@ -11,75 +11,84 @@ from bookwyrm.settings import DOMAIN
|
|||
class User(TestCase):
|
||||
def setUp(self):
|
||||
self.user = models.User.objects.create_user(
|
||||
'mouse@%s' % DOMAIN, 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse', name='hi', bookwyrm_user=False)
|
||||
"mouse@%s" % DOMAIN,
|
||||
"mouse@mouse.mouse",
|
||||
"mouseword",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
name="hi",
|
||||
bookwyrm_user=False,
|
||||
)
|
||||
|
||||
def test_computed_fields(self):
|
||||
''' username instead of id here '''
|
||||
expected_id = 'https://%s/user/mouse' % DOMAIN
|
||||
""" username instead of id here """
|
||||
expected_id = "https://%s/user/mouse" % DOMAIN
|
||||
self.assertEqual(self.user.remote_id, expected_id)
|
||||
self.assertEqual(self.user.username, 'mouse@%s' % DOMAIN)
|
||||
self.assertEqual(self.user.localname, 'mouse')
|
||||
self.assertEqual(self.user.shared_inbox, 'https://%s/inbox' % DOMAIN)
|
||||
self.assertEqual(self.user.inbox, '%s/inbox' % expected_id)
|
||||
self.assertEqual(self.user.outbox, '%s/outbox' % expected_id)
|
||||
self.assertEqual(self.user.username, "mouse@%s" % DOMAIN)
|
||||
self.assertEqual(self.user.localname, "mouse")
|
||||
self.assertEqual(self.user.shared_inbox, "https://%s/inbox" % DOMAIN)
|
||||
self.assertEqual(self.user.inbox, "%s/inbox" % expected_id)
|
||||
self.assertEqual(self.user.outbox, "%s/outbox" % expected_id)
|
||||
self.assertIsNotNone(self.user.key_pair.private_key)
|
||||
self.assertIsNotNone(self.user.key_pair.public_key)
|
||||
|
||||
def test_remote_user(self):
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||
user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'ratword', local=False,
|
||||
remote_id='https://example.com/dfjkg', bookwyrm_user=False)
|
||||
self.assertEqual(user.username, 'rat@example.com')
|
||||
|
||||
"rat",
|
||||
"rat@rat.rat",
|
||||
"ratword",
|
||||
local=False,
|
||||
remote_id="https://example.com/dfjkg",
|
||||
bookwyrm_user=False,
|
||||
)
|
||||
self.assertEqual(user.username, "rat@example.com")
|
||||
|
||||
def test_user_shelves(self):
|
||||
shelves = models.Shelf.objects.filter(user=self.user).all()
|
||||
self.assertEqual(len(shelves), 3)
|
||||
names = [s.name for s in shelves]
|
||||
self.assertTrue('To Read' in names)
|
||||
self.assertTrue('Currently Reading' in names)
|
||||
self.assertTrue('Read' in names)
|
||||
self.assertTrue("To Read" in names)
|
||||
self.assertTrue("Currently Reading" in names)
|
||||
self.assertTrue("Read" in names)
|
||||
ids = [s.identifier for s in shelves]
|
||||
self.assertTrue('to-read' in ids)
|
||||
self.assertTrue('reading' in ids)
|
||||
self.assertTrue('read' in ids)
|
||||
|
||||
self.assertTrue("to-read" in ids)
|
||||
self.assertTrue("reading" in ids)
|
||||
self.assertTrue("read" in ids)
|
||||
|
||||
def test_activitypub_serialize(self):
|
||||
activity = self.user.to_activity()
|
||||
self.assertEqual(activity['id'], self.user.remote_id)
|
||||
self.assertEqual(activity['@context'], [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
{
|
||||
'manuallyApprovesFollowers': 'as:manuallyApprovesFollowers',
|
||||
'schema': 'http://schema.org#',
|
||||
'PropertyValue': 'schema:PropertyValue',
|
||||
'value': 'schema:value',
|
||||
}
|
||||
])
|
||||
self.assertEqual(activity['preferredUsername'], self.user.localname)
|
||||
self.assertEqual(activity['name'], self.user.name)
|
||||
self.assertEqual(activity['inbox'], self.user.inbox)
|
||||
self.assertEqual(activity['outbox'], self.user.outbox)
|
||||
self.assertEqual(activity['bookwyrmUser'], False)
|
||||
self.assertEqual(activity['discoverable'], True)
|
||||
self.assertEqual(activity['type'], 'Person')
|
||||
self.assertEqual(activity["id"], self.user.remote_id)
|
||||
self.assertEqual(
|
||||
activity["@context"],
|
||||
[
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
},
|
||||
],
|
||||
)
|
||||
self.assertEqual(activity["preferredUsername"], self.user.localname)
|
||||
self.assertEqual(activity["name"], self.user.name)
|
||||
self.assertEqual(activity["inbox"], self.user.inbox)
|
||||
self.assertEqual(activity["outbox"], self.user.outbox)
|
||||
self.assertEqual(activity["bookwyrmUser"], False)
|
||||
self.assertEqual(activity["discoverable"], True)
|
||||
self.assertEqual(activity["type"], "Person")
|
||||
|
||||
def test_activitypub_outbox(self):
|
||||
activity = self.user.to_outbox()
|
||||
self.assertEqual(activity['type'], 'OrderedCollection')
|
||||
self.assertEqual(activity['id'], self.user.outbox)
|
||||
self.assertEqual(activity['totalItems'], 0)
|
||||
|
||||
self.assertEqual(activity["type"], "OrderedCollection")
|
||||
self.assertEqual(activity["id"], self.user.outbox)
|
||||
self.assertEqual(activity["totalItems"], 0)
|
||||
|
||||
def test_set_remote_server(self):
|
||||
server = models.FederatedServer.objects.create(
|
||||
server_name=DOMAIN,
|
||||
application_type='test type',
|
||||
application_version=3
|
||||
server_name=DOMAIN, application_type="test type", application_version=3
|
||||
)
|
||||
|
||||
models.user.set_remote_server(self.user.id)
|
||||
|
@ -91,26 +100,24 @@ class User(TestCase):
|
|||
def test_get_or_create_remote_server(self):
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://%s/.well-known/nodeinfo' % DOMAIN,
|
||||
json={'links': [{'href': 'http://www.example.com'}, {}]}
|
||||
"https://%s/.well-known/nodeinfo" % DOMAIN,
|
||||
json={"links": [{"href": "http://www.example.com"}, {}]},
|
||||
)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'http://www.example.com',
|
||||
json={'software': {'name': 'hi', 'version': '2'}},
|
||||
"http://www.example.com",
|
||||
json={"software": {"name": "hi", "version": "2"}},
|
||||
)
|
||||
|
||||
server = models.user.get_or_create_remote_server(DOMAIN)
|
||||
self.assertEqual(server.server_name, DOMAIN)
|
||||
self.assertEqual(server.application_type, 'hi')
|
||||
self.assertEqual(server.application_version, '2')
|
||||
self.assertEqual(server.application_type, "hi")
|
||||
self.assertEqual(server.application_version, "2")
|
||||
|
||||
@responses.activate
|
||||
def test_get_or_create_remote_server_no_wellknown(self):
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://%s/.well-known/nodeinfo' % DOMAIN,
|
||||
status=404
|
||||
responses.GET, "https://%s/.well-known/nodeinfo" % DOMAIN, status=404
|
||||
)
|
||||
|
||||
server = models.user.get_or_create_remote_server(DOMAIN)
|
||||
|
@ -122,14 +129,10 @@ class User(TestCase):
|
|||
def test_get_or_create_remote_server_no_links(self):
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://%s/.well-known/nodeinfo' % DOMAIN,
|
||||
json={'links': [{'href': 'http://www.example.com'}, {}]}
|
||||
)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'http://www.example.com',
|
||||
status=404
|
||||
"https://%s/.well-known/nodeinfo" % DOMAIN,
|
||||
json={"links": [{"href": "http://www.example.com"}, {}]},
|
||||
)
|
||||
responses.add(responses.GET, "http://www.example.com", status=404)
|
||||
|
||||
server = models.user.get_or_create_remote_server(DOMAIN)
|
||||
self.assertEqual(server.server_name, DOMAIN)
|
||||
|
@ -140,14 +143,10 @@ class User(TestCase):
|
|||
def test_get_or_create_remote_server_unknown_format(self):
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://%s/.well-known/nodeinfo' % DOMAIN,
|
||||
json={'links': [{'href': 'http://www.example.com'}, {}]}
|
||||
)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'http://www.example.com',
|
||||
json={'fish': 'salmon'}
|
||||
"https://%s/.well-known/nodeinfo" % DOMAIN,
|
||||
json={"links": [{"href": "http://www.example.com"}, {}]},
|
||||
)
|
||||
responses.add(responses.GET, "http://www.example.com", json={"fish": "salmon"})
|
||||
|
||||
server = models.user.get_or_create_remote_server(DOMAIN)
|
||||
self.assertEqual(server.server_name, DOMAIN)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue