1
0
Fork 0

Merge branch 'main' into outgoing-tests

This commit is contained in:
Mouse Reeve 2020-12-21 14:39:39 -08:00
commit 98aa946519
63 changed files with 1482 additions and 700 deletions

View file

@ -103,7 +103,7 @@ class BaseActivity(TestCase):
def test_to_model_simple_fields(self):
''' test setting simple fields '''
self.assertEqual(self.user.name, '')
self.assertIsNone(self.user.name)
activity = activitypub.Person(
id=self.user.remote_id,

View file

@ -30,10 +30,10 @@ class AbstractConnector(TestCase):
'series': ['one', 'two'],
}
self.connector.key_mappings = [
Mapping('isbn_10', model=models.Edition),
Mapping('isbn_10'),
Mapping('isbn_13'),
Mapping('lccn', model=models.Work),
Mapping('asin', remote_field='ASIN'),
Mapping('lccn'),
Mapping('asin'),
]
@ -41,7 +41,6 @@ class AbstractConnector(TestCase):
mapping = Mapping('isbn')
self.assertEqual(mapping.local_field, 'isbn')
self.assertEqual(mapping.remote_field, 'isbn')
self.assertEqual(mapping.model, None)
self.assertEqual(mapping.formatter('bb'), 'bb')
@ -49,7 +48,6 @@ class AbstractConnector(TestCase):
mapping = Mapping('isbn', remote_field='isbn13')
self.assertEqual(mapping.local_field, 'isbn')
self.assertEqual(mapping.remote_field, 'isbn13')
self.assertEqual(mapping.model, None)
self.assertEqual(mapping.formatter('bb'), 'bb')
@ -59,40 +57,4 @@ class AbstractConnector(TestCase):
self.assertEqual(mapping.local_field, 'isbn')
self.assertEqual(mapping.remote_field, 'isbn')
self.assertEqual(mapping.formatter, formatter)
self.assertEqual(mapping.model, None)
self.assertEqual(mapping.formatter('bb'), 'aabb')
def test_match_from_mappings(self):
edition = models.Edition.objects.create(
title='Blah',
isbn_13='blahhh',
)
match = self.connector.match_from_mappings(self.data, models.Edition)
self.assertEqual(match, edition)
def test_match_from_mappings_with_model(self):
edition = models.Edition.objects.create(
title='Blah',
isbn_10='1234567890',
)
match = self.connector.match_from_mappings(self.data, models.Edition)
self.assertEqual(match, edition)
def test_match_from_mappings_with_remote(self):
edition = models.Edition.objects.create(
title='Blah',
asin='A00BLAH',
)
match = self.connector.match_from_mappings(self.data, models.Edition)
self.assertEqual(match, edition)
def test_match_from_mappings_no_match(self):
edition = models.Edition.objects.create(
title='Blah',
)
match = self.connector.match_from_mappings(self.data, models.Edition)
self.assertEqual(match, None)

View file

@ -1,15 +1,16 @@
''' testing book data connectors '''
from dateutil import parser
from django.test import TestCase
import json
import pathlib
from dateutil import parser
from django.test import TestCase
import pytz
from bookwyrm import models
from bookwyrm.connectors.openlibrary import Connector
from bookwyrm.connectors.openlibrary import get_languages, get_description
from bookwyrm.connectors.openlibrary import pick_default_edition, get_openlibrary_key
from bookwyrm.connectors.abstract_connector import SearchResult, get_date
from bookwyrm.connectors.openlibrary import pick_default_edition, \
get_openlibrary_key
from bookwyrm.connectors.abstract_connector import SearchResult
class Openlibrary(TestCase):
@ -43,7 +44,7 @@ class Openlibrary(TestCase):
def test_pick_default_edition(self):
edition = pick_default_edition(self.edition_list_data['entries'])
self.assertEqual(edition['key'], '/books/OL9952943M')
self.assertEqual(edition['key'], '/books/OL9788823M')
def test_format_search_result(self):
@ -67,12 +68,6 @@ class Openlibrary(TestCase):
self.assertEqual(description, expected)
def test_get_date(self):
date = get_date(self.work_data['first_publish_date'])
expected = pytz.utc.localize(parser.parse('1995'))
self.assertEqual(date, expected)
def test_get_languages(self):
languages = get_languages(self.edition_data['languages'])
self.assertEqual(languages, ['English'])
@ -81,4 +76,3 @@ class Openlibrary(TestCase):
def test_get_ol_key(self):
key = get_openlibrary_key('/books/OL27320736M')
self.assertEqual(key, 'OL27320736M')

View file

@ -25,12 +25,13 @@ class SelfConnector(TestCase):
self.work = models.Work.objects.create(
title='Example Work',
)
author = models.Author.objects.create(name='Anonymous')
self.edition = models.Edition.objects.create(
title='Edition of Example Work',
author_text='Anonymous',
published_date=datetime.datetime(1980, 5, 10, tzinfo=timezone.utc),
parent_work=self.work,
)
self.edition.authors.add(author)
models.Edition.objects.create(
title='Another Edition',
parent_work=self.work,
@ -41,11 +42,12 @@ class SelfConnector(TestCase):
subtitle='The Anonymous Edition',
parent_work=self.work,
)
models.Edition.objects.create(
edition = models.Edition.objects.create(
title='An Edition',
author_text='Fish',
parent_work=self.work
)
edition.authors.add(models.Author.objects.create(name='Fish'))
def test_format_search_result(self):

View file

@ -1,5 +1,7 @@
''' testing models '''
from dateutil.parser import parse
from django.test import TestCase
from django.utils import timezone
from bookwyrm import models, settings
from bookwyrm.models.book import isbn_10_to_13, isbn_13_to_10
@ -56,3 +58,27 @@ class Book(TestCase):
isbn_13 = '978-1788-16167-1'
isbn_10 = isbn_13_to_10(isbn_13)
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, '')
book.physical_format = 'worm'
book.save()
self.assertEqual(book.edition_info, 'worm')
book.languages = ['English']
book.save()
self.assertEqual(book.edition_info, 'worm')
book.languages = ['Glorbish', 'English']
book.save()
self.assertEqual(book.edition_info, 'worm, Glorbish language')
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 cover (worm, Glorbish language, 2020)')

View file

@ -21,31 +21,23 @@ from bookwyrm.activitypub.base_activity import ActivityObject
from bookwyrm.models import fields, User, Status
from bookwyrm.models.base_model import ActivitypubMixin, BookWyrmModel
#pylint: disable=too-many-public-methods
class ActivitypubFields(TestCase):
''' 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://example.com/dlfjg-23/x'
))
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'
)
'http:/example.com/dlfjg-23/x')
self.assertRaises(
ValidationError, fields.validate_remote_id,
'www.example.com/dlfjg-23/x'
)
'www.example.com/dlfjg-23/x')
self.assertRaises(
ValidationError, fields.validate_remote_id,
'http://www.example.com/dlfjg 23/x'
)
'http://www.example.com/dlfjg 23/x')
def test_activitypub_field_mixin(self):
''' generic mixin with super basic to and from functionality '''
@ -71,6 +63,38 @@ class ActivitypubFields(TestCase):
instance.name = 'snake_case_name'
self.assertEqual(instance.get_activitypub_field(), 'snakeCaseName')
def test_set_field_from_activity(self):
''' setter from entire json blob '''
@dataclass
class TestModel:
''' real simple mock '''
field_name: str
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.set_field_from_activity(mock_model, data)
self.assertEqual(mock_model.field_name, 'hi')
def test_set_activity_from_field(self):
''' set json field given entire model '''
@dataclass
class TestModel:
''' real simple mock '''
field_name: str
unrelated: str
mock_model = TestModel(field_name='bip', unrelated='field')
instance = fields.ActivitypubFieldMixin()
instance.name = 'field_name'
data = {}
instance.set_activity_from_field(data, mock_model)
self.assertEqual(data['fieldName'], 'bip')
def test_remote_id_field(self):
''' just sets some defaults on charfield '''
instance = fields.RemoteIdField()
@ -369,17 +393,19 @@ class ActivitypubFields(TestCase):
ContentFile(output.getvalue())
)
output = fields.image_serializer(user.avatar)
output = fields.image_serializer(user.avatar, alt='alt text')
self.assertIsNotNone(
re.match(
r'.*\.jpg',
output.url,
)
)
self.assertEqual(output.name, 'alt text')
self.assertEqual(output.type, 'Image')
instance = fields.ImageField()
output = fields.image_serializer(user.avatar, alt=None)
self.assertEqual(instance.field_to_activity(user.avatar), output)
responses.add(
@ -408,3 +434,12 @@ class ActivitypubFields(TestCase):
''' 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'])
def test_html_field(self):
''' 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>'
)

View file

@ -1,42 +1,274 @@
''' testing models '''
from io import BytesIO
import pathlib
from PIL import Image
from django.core.files.base import ContentFile
from django.db import IntegrityError
from django.test import TestCase
from django.utils import timezone
from bookwyrm import models, settings
class Status(TestCase):
''' lotta types of statuses '''
def setUp(self):
user = models.User.objects.create_user(
''' useful things for creating a status '''
self.user = models.User.objects.create_user(
'mouse', 'mouse@mouse.mouse', 'mouseword', local=True)
book = models.Edition.objects.create(title='Example Edition')
self.book = models.Edition.objects.create(title='Test Edition')
models.Status.objects.create(user=user, content='Blah blah')
models.Comment.objects.create(user=user, content='content', book=book)
models.Quotation.objects.create(
user=user, content='content', book=book, quote='blah')
models.Review.objects.create(
user=user, content='content', book=book, rating=3)
image_file = pathlib.Path(__file__).parent.joinpath(
'../../static/images/default_avi.jpg')
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
self.book.cover.save(
'test.jpg',
ContentFile(output.getvalue())
)
def test_status(self):
status = models.Status.objects.first()
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)
self.assertEqual(status.remote_id, expected_id)
self.assertEqual(status.privacy, 'public')
def test_comment(self):
comment = models.Comment.objects.first()
expected_id = 'https://%s/user/mouse/comment/%d' % \
(settings.DOMAIN, comment.id)
self.assertEqual(comment.remote_id, expected_id)
def test_replies(self):
''' 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)
models.Review.objects.create(
content='hey', reply_parent=parent, user=self.user, book=self.book)
models.Status.objects.create(
content='hi hello', reply_parent=child, user=self.user)
def test_quotation(self):
quotation = models.Quotation.objects.first()
expected_id = 'https://%s/user/mouse/quotation/%d' % \
(settings.DOMAIN, quotation.id)
self.assertEqual(quotation.remote_id, expected_id)
replies = models.Status.replies(parent)
self.assertEqual(replies.count(), 2)
self.assertEqual(replies.first(), child)
# should select subclasses
self.assertIsInstance(replies.last(), models.Review)
def test_review(self):
review = models.Review.objects.first()
expected_id = 'https://%s/user/mouse/review/%d' % \
(settings.DOMAIN, review.id)
self.assertEqual(review.remote_id, expected_id)
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, 'Boost')
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)
def test_to_replies(self):
''' 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)
models.Review.objects.create(
content='hey', reply_parent=parent, user=self.user, book=self.book)
models.Status.objects.create(
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)
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)
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)
def test_status_to_activity_tombstone(self):
''' 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())
activity = status.to_activity()
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)
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'], [])
def test_generated_note_to_activity(self):
''' subclass of the base model version with a "pure" serializer '''
status = models.GeneratedNote.objects.create(
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)
def test_generated_note_to_pure_activity(self):
''' subclass of the base model version with a "pure" serializer '''
status = models.GeneratedNote.objects.create(
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['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))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
def test_comment_to_activity(self):
''' subclass of the base model version with a "pure" serializer '''
status = models.Comment.objects.create(
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)
def test_comment_to_pure_activity(self):
''' subclass of the base model version with a "pure" serializer '''
status = models.Comment.objects.create(
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['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))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
def test_quotation_to_activity(self):
''' 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)
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)
def test_quotation_to_pure_activity(self):
''' 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)
activity = status.to_activity(pure=True)
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))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
def test_review_to_activity(self):
''' 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)
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)
def test_review_to_pure_activity(self):
''' 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)
activity = status.to_activity(pure=True)
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))
self.assertEqual(
activity['attachment'][0].name, 'Test Edition cover')
def test_favorite(self):
''' fav a status '''
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
with self.assertRaises(IntegrityError):
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)
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)
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, boost.to_activity(pure=True))
def test_notification(self):
''' a simple model '''
notification = models.Notification.objects.create(
user=self.user, notification_type='FAVORITE')
self.assertFalse(notification.read)
with self.assertRaises(IntegrityError):
models.Notification.objects.create(
user=self.user, notification_type='GLORB')

View file

@ -410,7 +410,10 @@ class Incoming(TestCase):
'actor': self.remote_user.remote_id,
'object': self.status.to_activity(),
}
incoming.handle_boost(activity)
with patch('bookwyrm.models.status.Status.ignore_activity') \
as discarder:
discarder.return_value = False
incoming.handle_boost(activity)
boost = models.Boost.objects.get()
self.assertEqual(boost.boosted_status, self.status)
notification = models.Notification.objects.get()
@ -433,13 +436,35 @@ class Incoming(TestCase):
boosted_status=self.status, user=self.remote_user)
incoming.handle_unboost(activity)
def test_handle_add_book(self):
''' shelving a book '''
book = models.Edition.objects.create(
title='Test', remote_id='https://bookwyrm.social/book/37292')
shelf = models.Shelf.objects.create(
user=self.remote_user, name='Test Shelf')
shelf.remote_id = 'https://bookwyrm.social/user/mouse/shelf/to-read'
shelf.save()
activity = {
"id": "https://bookwyrm.social/shelfbook/6189#add",
"type": "Add",
"actor": "hhttps://example.com/users/rat",
"object": "https://bookwyrm.social/book/37292",
"target": "https://bookwyrm.social/user/mouse/shelf/to-read",
"@context": "https://www.w3.org/ns/activitystreams"
}
incoming.handle_add(activity)
self.assertEqual(shelf.books.first(), book)
def test_handle_update_user(self):
''' update an existing user '''
datafile = pathlib.Path(__file__).parent.joinpath(
'data/ap_user.json')
userdata = json.loads(datafile.read_bytes())
del userdata['icon']
self.assertEqual(self.local_user.name, '')
self.assertIsNone(self.local_user.name)
incoming.handle_update_user({'object': userdata})
user = models.User.objects.get(id=self.local_user.id)
self.assertEqual(user.name, 'MOUSE?? MOUSE!!')
@ -451,11 +476,14 @@ class Incoming(TestCase):
'data/fr_edition.json')
bookdata = json.loads(datafile.read_bytes())
models.Work.objects.create(
title='Test Work', remote_id='https://bookwyrm.social/book/5988')
book = models.Edition.objects.create(
title='Test Book', remote_id='https://bookwyrm.social/book/5989')
del bookdata['authors']
self.assertEqual(book.title, 'Test Book')
with patch(
'bookwyrm.activitypub.base_activity.set_related_field.delay'):
incoming.handle_update_edition({'object': bookdata})

View file

@ -1,34 +1,36 @@
''' make sure only valid html gets to the app '''
from django.test import TestCase
from bookwyrm.sanitize_html import InputHtmlParser
class Sanitizer(TestCase):
''' sanitizer tests '''
def test_no_html(self):
''' just text '''
input_text = 'no html '
parser = InputHtmlParser()
parser.feed(input_text)
output = parser.get_output()
self.assertEqual(input_text, output)
def test_valid_html(self):
''' leave the html untouched '''
input_text = '<b>yes </b> <i>html</i>'
parser = InputHtmlParser()
parser.feed(input_text)
output = parser.get_output()
self.assertEqual(input_text, output)
def test_valid_html_attrs(self):
''' and don't remove attributes '''
input_text = '<a href="fish.com">yes </a> <i>html</i>'
parser = InputHtmlParser()
parser.feed(input_text)
output = parser.get_output()
self.assertEqual(input_text, output)
def test_invalid_html(self):
''' remove all html when the html is malformed '''
input_text = '<b>yes <i>html</i>'
parser = InputHtmlParser()
parser.feed(input_text)
@ -41,8 +43,8 @@ class Sanitizer(TestCase):
output = parser.get_output()
self.assertEqual('yes html ', output)
def test_disallowed_html(self):
''' remove disallowed html but keep allowed html '''
input_text = '<div> yes <i>html</i></div>'
parser = InputHtmlParser()
parser.feed(input_text)

View file

@ -158,34 +158,6 @@ class TemplateTags(TestCase):
self.assertEqual(boosted, status)
def test_get_edition_info(self):
''' text slug about an edition '''
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), '')
self.book.physical_format = 'worm'
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), 'worm')
self.book.languages = ['English']
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), 'worm')
self.book.languages = ['Glorbish', 'English']
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book),
'worm, Glorbish language')
self.book.published_date = timezone.make_aware(parse('2020'))
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book),
'worm, Glorbish language, 2020')
def test_get_book_description(self):
''' grab it from the edition or the parent '''
work = models.Work.objects.create(title='Test Work')

View file

@ -0,0 +1,264 @@
''' test for app action functionality '''
from unittest.mock import patch
from django.core.exceptions import PermissionDenied
from django.http.response import Http404
from django.test import TestCase
from django.test.client import RequestFactory
from bookwyrm import view_actions as actions, models
from bookwyrm.settings import DOMAIN
#pylint: disable=too-many-public-methods
class ViewActions(TestCase):
''' a lot here: all handlers for receiving activitypub requests '''
def setUp(self):
''' we need basic things, like users '''
self.local_user = models.User.objects.create_user(
'mouse', 'mouse@mouse.com', 'mouseword', local=True)
self.local_user.remote_id = 'https://example.com/user/mouse'
self.local_user.save()
with patch('bookwyrm.models.user.set_remote_server.delay'):
self.remote_user = models.User.objects.create_user(
'rat', 'rat@rat.com', 'ratword',
local=False,
remote_id='https://example.com/users/rat',
inbox='https://example.com/users/rat/inbox',
outbox='https://example.com/users/rat/outbox',
)
self.status = models.Status.objects.create(
user=self.local_user,
content='Test status',
remote_id='https://example.com/status/1',
)
self.settings = models.SiteSettings.objects.create(id=1)
self.factory = RequestFactory()
def test_register(self):
''' create a user '''
self.assertEqual(models.User.objects.count(), 2)
request = self.factory.post(
'register/',
{
'username': 'nutria-user.user_nutria',
'password': 'mouseword',
'email': 'aa@bb.cccc'
})
with patch('bookwyrm.view_actions.login'):
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 3)
self.assertEqual(response.status_code, 302)
nutria = models.User.objects.last()
self.assertEqual(nutria.username, 'nutria-user.user_nutria@%s' % DOMAIN)
self.assertEqual(nutria.localname, 'nutria-user.user_nutria')
self.assertEqual(nutria.local, True)
def test_register_trailing_space(self):
''' django handles this so weirdly '''
request = self.factory.post(
'register/',
{
'username': 'nutria ',
'password': 'mouseword',
'email': 'aa@bb.ccc'
})
with patch('bookwyrm.view_actions.login'):
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 3)
self.assertEqual(response.status_code, 302)
nutria = models.User.objects.last()
self.assertEqual(nutria.username, 'nutria@%s' % DOMAIN)
self.assertEqual(nutria.localname, 'nutria')
self.assertEqual(nutria.local, True)
def test_register_invalid_email(self):
''' gotta have an email '''
self.assertEqual(models.User.objects.count(), 2)
request = self.factory.post(
'register/',
{
'username': 'nutria',
'password': 'mouseword',
'email': 'aa'
})
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.template_name, 'login.html')
def test_register_invalid_username(self):
''' gotta have an email '''
self.assertEqual(models.User.objects.count(), 2)
request = self.factory.post(
'register/',
{
'username': 'nut@ria',
'password': 'mouseword',
'email': 'aa@bb.ccc'
})
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.template_name, 'login.html')
request = self.factory.post(
'register/',
{
'username': 'nutr ia',
'password': 'mouseword',
'email': 'aa@bb.ccc'
})
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.template_name, 'login.html')
request = self.factory.post(
'register/',
{
'username': 'nut@ria',
'password': 'mouseword',
'email': 'aa@bb.ccc'
})
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 2)
self.assertEqual(response.template_name, 'login.html')
def test_register_closed_instance(self):
''' you can't just register '''
self.settings.allow_registration = False
self.settings.save()
request = self.factory.post(
'register/',
{
'username': 'nutria ',
'password': 'mouseword',
'email': 'aa@bb.ccc'
})
with self.assertRaises(PermissionDenied):
actions.register(request)
def test_register_invite(self):
''' you can't just register '''
self.settings.allow_registration = False
self.settings.save()
models.SiteInvite.objects.create(
code='testcode', user=self.local_user, use_limit=1)
self.assertEqual(models.SiteInvite.objects.get().times_used, 0)
request = self.factory.post(
'register/',
{
'username': 'nutria',
'password': 'mouseword',
'email': 'aa@bb.ccc',
'invite_code': 'testcode'
})
with patch('bookwyrm.view_actions.login'):
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 3)
self.assertEqual(response.status_code, 302)
self.assertEqual(models.SiteInvite.objects.get().times_used, 1)
# invalid invite
request = self.factory.post(
'register/',
{
'username': 'nutria2',
'password': 'mouseword',
'email': 'aa@bb.ccc',
'invite_code': 'testcode'
})
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 3)
# bad invite code
request = self.factory.post(
'register/',
{
'username': 'nutria3',
'password': 'mouseword',
'email': 'aa@bb.ccc',
'invite_code': 'dkfkdjgdfkjgkdfj'
})
with self.assertRaises(Http404):
response = actions.register(request)
self.assertEqual(models.User.objects.count(), 3)
def test_password_reset_request(self):
''' send 'em an email '''
request = self.factory.post('', {'email': 'aa@bb.ccc'})
resp = actions.password_reset_request(request)
self.assertEqual(resp.status_code, 302)
request = self.factory.post(
'', {'email': 'mouse@mouse.com'})
with patch('bookwyrm.emailing.send_email.delay'):
resp = actions.password_reset_request(request)
self.assertEqual(resp.template_name, 'password_reset_request.html')
self.assertEqual(
models.PasswordReset.objects.get().user, self.local_user)
def test_password_reset(self):
''' reset from code '''
code = models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post('', {
'reset-code': code.code,
'password': 'hi',
'confirm-password': 'hi'
})
with patch('bookwyrm.view_actions.login'):
resp = actions.password_reset(request)
self.assertEqual(resp.status_code, 302)
self.assertFalse(models.PasswordReset.objects.exists())
def test_password_reset_wrong_code(self):
''' reset from code '''
models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post('', {
'reset-code': 'jhgdkfjgdf',
'password': 'hi',
'confirm-password': 'hi'
})
resp = actions.password_reset(request)
self.assertEqual(resp.template_name, 'password_reset.html')
self.assertTrue(models.PasswordReset.objects.exists())
def test_password_reset_mismatch(self):
''' reset from code '''
code = models.PasswordReset.objects.create(user=self.local_user)
request = self.factory.post('', {
'reset-code': code.code,
'password': 'hi',
'confirm-password': 'hihi'
})
resp = actions.password_reset(request)
self.assertEqual(resp.template_name, 'password_reset.html')
self.assertTrue(models.PasswordReset.objects.exists())
def test_switch_edition(self):
''' updates user's relationships to a book '''
work = models.Work.objects.create(title='test work')
edition1 = models.Edition.objects.create(
title='first ed', parent_work=work)
edition2 = models.Edition.objects.create(
title='second ed', parent_work=work)
shelf = models.Shelf.objects.create(
name='Test Shelf', user=self.local_user)
shelf.books.add(edition1)
models.ReadThrough.objects.create(
user=self.local_user, book=edition1)
self.assertEqual(models.ShelfBook.objects.get().book, edition1)
self.assertEqual(models.ReadThrough.objects.get().book, edition1)
request = self.factory.post('', {
'edition': edition2.id
})
request.user = self.local_user
with patch('bookwyrm.broadcast.broadcast_task.delay'):
actions.switch_edition(request)
self.assertEqual(models.ShelfBook.objects.get().book, edition2)
self.assertEqual(models.ReadThrough.objects.get().book, edition2)