1
0
Fork 0

Runs black

This commit is contained in:
Mouse Reeve 2021-03-08 08:49:10 -08:00
parent a07f955781
commit 70296e760b
198 changed files with 10239 additions and 8572 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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>"
)

View file

@ -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")

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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)