Merge branch 'main' into search-refactor
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
""" testing models """
|
||||
from unittest.mock import patch
|
||||
from django.http import Http404
|
||||
from django.test import TestCase
|
||||
|
||||
from bookwyrm import models
|
||||
@ -39,14 +40,14 @@ class BaseModel(TestCase):
|
||||
"""these should be generated"""
|
||||
self.test_model.id = 1
|
||||
expected = self.test_model.get_remote_id()
|
||||
self.assertEqual(expected, "https://%s/bookwyrmtestmodel/1" % DOMAIN)
|
||||
self.assertEqual(expected, f"https://{DOMAIN}/bookwyrmtestmodel/1")
|
||||
|
||||
def test_remote_id_with_user(self):
|
||||
"""format of remote id when there's a user object"""
|
||||
self.test_model.user = self.local_user
|
||||
self.test_model.id = 1
|
||||
expected = self.test_model.get_remote_id()
|
||||
self.assertEqual(expected, "https://%s/user/mouse/bookwyrmtestmodel/1" % DOMAIN)
|
||||
self.assertEqual(expected, f"https://{DOMAIN}/user/mouse/bookwyrmtestmodel/1")
|
||||
|
||||
def test_set_remote_id(self):
|
||||
"""this function sets remote ids after creation"""
|
||||
@ -55,9 +56,7 @@ class BaseModel(TestCase):
|
||||
instance = models.Work.objects.create(title="work title")
|
||||
instance.remote_id = None
|
||||
base_model.set_remote_id(None, instance, True)
|
||||
self.assertEqual(
|
||||
instance.remote_id, "https://%s/book/%d" % (DOMAIN, instance.id)
|
||||
)
|
||||
self.assertEqual(instance.remote_id, f"https://{DOMAIN}/book/{instance.id}")
|
||||
|
||||
# shouldn't set remote_id if it's not created
|
||||
instance.remote_id = None
|
||||
@ -70,28 +69,30 @@ class BaseModel(TestCase):
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="public"
|
||||
)
|
||||
self.assertTrue(obj.visible_to_user(self.local_user))
|
||||
self.assertIsNone(obj.raise_visible_to_user(self.local_user))
|
||||
|
||||
obj = models.Shelf.objects.create(
|
||||
name="test", user=self.remote_user, privacy="unlisted"
|
||||
)
|
||||
self.assertTrue(obj.visible_to_user(self.local_user))
|
||||
self.assertIsNone(obj.raise_visible_to_user(self.local_user))
|
||||
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="followers"
|
||||
)
|
||||
self.assertFalse(obj.visible_to_user(self.local_user))
|
||||
with self.assertRaises(Http404):
|
||||
obj.raise_visible_to_user(self.local_user)
|
||||
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="direct"
|
||||
)
|
||||
self.assertFalse(obj.visible_to_user(self.local_user))
|
||||
with self.assertRaises(Http404):
|
||||
obj.raise_visible_to_user(self.local_user)
|
||||
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="direct"
|
||||
)
|
||||
obj.mention_users.add(self.local_user)
|
||||
self.assertTrue(obj.visible_to_user(self.local_user))
|
||||
self.assertIsNone(obj.raise_visible_to_user(self.local_user))
|
||||
|
||||
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||
def test_object_visible_to_user_follower(self, _):
|
||||
@ -100,18 +101,19 @@ class BaseModel(TestCase):
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="followers"
|
||||
)
|
||||
self.assertTrue(obj.visible_to_user(self.local_user))
|
||||
self.assertIsNone(obj.raise_visible_to_user(self.local_user))
|
||||
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="direct"
|
||||
)
|
||||
self.assertFalse(obj.visible_to_user(self.local_user))
|
||||
with self.assertRaises(Http404):
|
||||
obj.raise_visible_to_user(self.local_user)
|
||||
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="direct"
|
||||
)
|
||||
obj.mention_users.add(self.local_user)
|
||||
self.assertTrue(obj.visible_to_user(self.local_user))
|
||||
self.assertIsNone(obj.raise_visible_to_user(self.local_user))
|
||||
|
||||
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||
def test_object_visible_to_user_blocked(self, _):
|
||||
@ -120,9 +122,11 @@ class BaseModel(TestCase):
|
||||
obj = models.Status.objects.create(
|
||||
content="hi", user=self.remote_user, privacy="public"
|
||||
)
|
||||
self.assertFalse(obj.visible_to_user(self.local_user))
|
||||
with self.assertRaises(Http404):
|
||||
obj.raise_visible_to_user(self.local_user)
|
||||
|
||||
obj = models.Shelf.objects.create(
|
||||
name="test", user=self.remote_user, privacy="unlisted"
|
||||
)
|
||||
self.assertFalse(obj.visible_to_user(self.local_user))
|
||||
with self.assertRaises(Http404):
|
||||
obj.raise_visible_to_user(self.local_user)
|
||||
|
95
bookwyrm/tests/models/test_site.py
Normal file
95
bookwyrm/tests/models/test_site.py
Normal file
@ -0,0 +1,95 @@
|
||||
""" testing models """
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.db import IntegrityError
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from bookwyrm import models, settings
|
||||
|
||||
|
||||
class SiteModels(TestCase):
|
||||
"""tests for site models"""
|
||||
|
||||
def setUp(self):
|
||||
"""we need basic test data and mocks"""
|
||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||
):
|
||||
self.local_user = models.User.objects.create_user(
|
||||
"mouse@local.com",
|
||||
"mouse@mouse.com",
|
||||
"mouseword",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
remote_id="https://example.com/users/mouse",
|
||||
)
|
||||
|
||||
def test_site_settings_absent(self):
|
||||
"""create and load site settings"""
|
||||
self.assertFalse(models.SiteSettings.objects.exists())
|
||||
result = models.SiteSettings.get()
|
||||
self.assertTrue(models.SiteSettings.objects.exists())
|
||||
self.assertEqual(result.id, 1)
|
||||
self.assertEqual(result.name, "BookWyrm")
|
||||
|
||||
def test_site_settings_present(self):
|
||||
"""load site settings"""
|
||||
models.SiteSettings.objects.create(id=1, name="Fish Town")
|
||||
result = models.SiteSettings.get()
|
||||
self.assertEqual(result.id, 1)
|
||||
self.assertEqual(result.name, "Fish Town")
|
||||
self.assertEqual(models.SiteSettings.objects.all().count(), 1)
|
||||
|
||||
def test_site_invite(self):
|
||||
"""default invite"""
|
||||
invite = models.SiteInvite.objects.create(
|
||||
user=self.local_user,
|
||||
)
|
||||
self.assertTrue(invite.valid())
|
||||
|
||||
def test_site_invite_with_limit(self):
|
||||
"""with use limit"""
|
||||
# valid
|
||||
invite = models.SiteInvite.objects.create(user=self.local_user, use_limit=1)
|
||||
self.assertTrue(invite.valid())
|
||||
|
||||
# invalid
|
||||
invite = models.SiteInvite.objects.create(user=self.local_user, use_limit=0)
|
||||
self.assertFalse(invite.valid())
|
||||
invite = models.SiteInvite.objects.create(
|
||||
user=self.local_user, use_limit=1, times_used=1
|
||||
)
|
||||
self.assertFalse(invite.valid())
|
||||
|
||||
def test_site_invite_with_expiry(self):
|
||||
"""with expiration date"""
|
||||
date = timezone.now() + timedelta(days=1)
|
||||
invite = models.SiteInvite.objects.create(user=self.local_user, expiry=date)
|
||||
self.assertTrue(invite.valid())
|
||||
|
||||
date = timezone.now() - timedelta(days=1)
|
||||
invite = models.SiteInvite.objects.create(user=self.local_user, expiry=date)
|
||||
self.assertFalse(invite.valid())
|
||||
|
||||
def test_site_invite_link(self):
|
||||
"""invite link generator"""
|
||||
invite = models.SiteInvite.objects.create(user=self.local_user, code="hello")
|
||||
self.assertEqual(invite.link, f"https://{settings.DOMAIN}/invite/hello")
|
||||
|
||||
def test_invite_request(self):
|
||||
"""someone wants an invite"""
|
||||
# normal and good
|
||||
request = models.InviteRequest.objects.create(email="mouse.reeve@gmail.com")
|
||||
self.assertIsNone(request.invite)
|
||||
|
||||
# already in use
|
||||
with self.assertRaises(IntegrityError):
|
||||
request = models.InviteRequest.objects.create(email="mouse@mouse.com")
|
||||
|
||||
def test_password_reset(self):
|
||||
"""password reset token"""
|
||||
token = models.PasswordReset.objects.create(user=self.local_user, code="hello")
|
||||
self.assertTrue(token.valid())
|
||||
self.assertEqual(token.link, f"https://{settings.DOMAIN}/password-reset/hello")
|
@ -20,6 +20,7 @@ from bookwyrm.preview_images import (
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=consider-using-with
|
||||
class PreviewImages(TestCase):
|
||||
"""every response to a get request, html or json"""
|
||||
|
||||
@ -120,3 +121,11 @@ class PreviewImages(TestCase):
|
||||
self.assertEqual(
|
||||
self.local_user.preview_image.height, settings.PREVIEW_IMG_HEIGHT
|
||||
)
|
||||
|
||||
def test_generate_user_preview_images_task(self, *args, **kwargs):
|
||||
"""test task's external calls"""
|
||||
with patch("bookwyrm.preview_images.generate_preview_image") as generate_mock:
|
||||
generate_user_preview_image_task(self.local_user.id)
|
||||
args = generate_mock.call_args.kwargs
|
||||
self.assertEqual(args["texts"]["text_one"], "possum")
|
||||
self.assertEqual(args["texts"]["text_three"], f"@possum@{settings.DOMAIN}")
|
||||
|
1
bookwyrm/tests/views/admin/__init__.py
Normal file
1
bookwyrm/tests/views/admin/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import *
|
@ -1,5 +1,6 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -34,5 +35,8 @@ class DashboardViews(TestCase):
|
||||
request.user.is_superuser = True
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
@ -1,5 +1,7 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -36,7 +38,10 @@ class EmailBlocklistViews(TestCase):
|
||||
result = view(request)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_blocklist_page_post(self):
|
||||
@ -49,7 +54,10 @@ class EmailBlocklistViews(TestCase):
|
||||
result = view(request)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
self.assertTrue(
|
@ -1,6 +1,8 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
@ -46,10 +48,19 @@ class FederationViews(TestCase):
|
||||
request.user.is_superuser = True
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_server_page(self):
|
||||
def test_instance_page(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
server = models.FederatedServer.objects.create(server_name="hi.there.com")
|
||||
view = views.FederatedServer.as_view()
|
||||
@ -59,7 +70,10 @@ class FederationViews(TestCase):
|
||||
|
||||
result = view(request, server.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_server_page_block(self):
|
||||
@ -148,7 +162,10 @@ class FederationViews(TestCase):
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_add_view_post_create(self):
|
||||
@ -169,6 +186,7 @@ class FederationViews(TestCase):
|
||||
self.assertEqual(server.application_type, "coolsoft")
|
||||
self.assertEqual(server.status, "blocked")
|
||||
|
||||
# pylint: disable=consider-using-with
|
||||
def test_import_blocklist(self):
|
||||
"""load a json file with a list of servers to block"""
|
||||
server = models.FederatedServer.objects.create(server_name="hi.there.com")
|
||||
@ -180,7 +198,7 @@ class FederationViews(TestCase):
|
||||
{"instance": "hi.there.com", "url": "https://explanation.url"}, # existing
|
||||
{"a": "b"}, # invalid
|
||||
]
|
||||
json.dump(data, open("file.json", "w"))
|
||||
json.dump(data, open("file.json", "w")) # pylint: disable=unspecified-encoding
|
||||
|
||||
view = views.ImportServerBlocklist.as_view()
|
||||
request = self.factory.post(
|
44
bookwyrm/tests/views/admin/test_ip_blocklist.py
Normal file
44
bookwyrm/tests/views/admin/test_ip_blocklist.py
Normal file
@ -0,0 +1,44 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import models, views
|
||||
|
||||
|
||||
class IPBlocklistViews(TestCase):
|
||||
"""every response to a get request, html or json"""
|
||||
|
||||
def setUp(self):
|
||||
"""we need basic test data and mocks"""
|
||||
self.factory = RequestFactory()
|
||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||
):
|
||||
self.local_user = models.User.objects.create_user(
|
||||
"mouse@local.com",
|
||||
"mouse@mouse.mouse",
|
||||
"password",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
)
|
||||
|
||||
models.SiteSettings.objects.create()
|
||||
|
||||
def test_blocklist_page_get(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.IPBlocklist.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
request.user.is_superuser = True
|
||||
|
||||
result = view(request)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
@ -1,6 +1,8 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -42,7 +44,16 @@ class ReportViews(TestCase):
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_reports_page_with_data(self):
|
||||
@ -55,7 +66,16 @@ class ReportViews(TestCase):
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_report_page(self):
|
||||
@ -69,7 +89,10 @@ class ReportViews(TestCase):
|
||||
result = view(request, report.id)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_report_comment(self):
|
@ -1,5 +1,7 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
@ -34,7 +36,10 @@ class UserAdminViews(TestCase):
|
||||
request.user.is_superuser = True
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_user_admin_page(self):
|
||||
@ -47,7 +52,10 @@ class UserAdminViews(TestCase):
|
||||
result = view(request, self.local_user.id)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
|
||||
@ -69,7 +77,10 @@ class UserAdminViews(TestCase):
|
||||
result = view(request, self.local_user.id)
|
||||
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
|
||||
self.assertEqual(
|
||||
list(self.local_user.groups.values_list("name", flat=True)), ["editor"]
|
@ -3,6 +3,7 @@ import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpResponseNotAllowed, HttpResponseNotFound
|
||||
from django.test import TestCase, Client
|
||||
from django.test.client import RequestFactory
|
||||
@ -130,22 +131,24 @@ class Inbox(TestCase):
|
||||
"",
|
||||
HTTP_USER_AGENT="http.rb/4.4.1 (Mastodon/3.3.0; +https://mastodon.social/)",
|
||||
)
|
||||
self.assertFalse(views.inbox.is_blocked_user_agent(request))
|
||||
self.assertIsNone(views.inbox.raise_is_blocked_user_agent(request))
|
||||
|
||||
models.FederatedServer.objects.create(
|
||||
server_name="mastodon.social", status="blocked"
|
||||
)
|
||||
self.assertTrue(views.inbox.is_blocked_user_agent(request))
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.inbox.raise_is_blocked_user_agent(request)
|
||||
|
||||
def test_is_blocked_activity(self):
|
||||
"""check for blocked servers"""
|
||||
activity = {"actor": "https://mastodon.social/user/whaatever/else"}
|
||||
self.assertFalse(views.inbox.is_blocked_activity(activity))
|
||||
self.assertIsNone(views.inbox.raise_is_blocked_activity(activity))
|
||||
|
||||
models.FederatedServer.objects.create(
|
||||
server_name="mastodon.social", status="blocked"
|
||||
)
|
||||
self.assertTrue(views.inbox.is_blocked_activity(activity))
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.inbox.raise_is_blocked_activity(activity)
|
||||
|
||||
@patch("bookwyrm.suggested_users.remove_user_task.delay")
|
||||
def test_create_by_deactivated_user(self, _):
|
||||
@ -157,11 +160,11 @@ class Inbox(TestCase):
|
||||
activity = self.create_json
|
||||
activity["actor"] = self.remote_user.remote_id
|
||||
activity["object"] = status_data
|
||||
activity["type"] = "Create"
|
||||
|
||||
with patch("bookwyrm.views.inbox.has_valid_signature") as mock_valid:
|
||||
mock_valid.return_value = True
|
||||
|
||||
result = self.client.post(
|
||||
"/inbox", json.dumps(activity), content_type="application/json"
|
||||
)
|
||||
self.assertEqual(result.status_code, 403)
|
||||
response = self.client.post(
|
||||
"/inbox",
|
||||
json.dumps(activity),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
1
bookwyrm/tests/views/preferences/__init__.py
Normal file
1
bookwyrm/tests/views/preferences/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import *
|
@ -1,5 +1,7 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -44,7 +46,10 @@ class BlockViews(TestCase):
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_block_post(self, _):
|
||||
@ -75,6 +80,6 @@ class BlockViews(TestCase):
|
||||
request.user = self.local_user
|
||||
|
||||
with patch("bookwyrm.activitystreams.add_user_statuses_task.delay"):
|
||||
views.block.unblock(request, self.remote_user.id)
|
||||
views.unblock(request, self.remote_user.id)
|
||||
|
||||
self.assertFalse(models.UserBlocks.objects.exists())
|
61
bookwyrm/tests/views/preferences/test_change_password.py
Normal file
61
bookwyrm/tests/views/preferences/test_change_password.py
Normal file
@ -0,0 +1,61 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import models, views
|
||||
|
||||
|
||||
class ChangePasswordViews(TestCase):
|
||||
"""view user and edit profile"""
|
||||
|
||||
def setUp(self):
|
||||
"""we need basic test data and mocks"""
|
||||
self.factory = RequestFactory()
|
||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||
):
|
||||
self.local_user = models.User.objects.create_user(
|
||||
"mouse@local.com",
|
||||
"mouse@mouse.com",
|
||||
"password",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
)
|
||||
models.SiteSettings.objects.create(id=1)
|
||||
|
||||
def test_password_change_get(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.ChangePassword.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_password_change(self):
|
||||
"""change password"""
|
||||
view = views.ChangePassword.as_view()
|
||||
password_hash = self.local_user.password
|
||||
request = self.factory.post("", {"password": "hi", "confirm-password": "hi"})
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.views.preferences.change_password.login"):
|
||||
view(request)
|
||||
self.assertNotEqual(self.local_user.password, password_hash)
|
||||
|
||||
def test_password_change_mismatch(self):
|
||||
"""change password"""
|
||||
view = views.ChangePassword.as_view()
|
||||
password_hash = self.local_user.password
|
||||
request = self.factory.post("", {"password": "hi", "confirm-password": "hihi"})
|
||||
request.user = self.local_user
|
||||
view(request)
|
||||
self.assertEqual(self.local_user.password, password_hash)
|
89
bookwyrm/tests/views/preferences/test_delete_user.py
Normal file
89
bookwyrm/tests/views/preferences/test_delete_user.py
Normal file
@ -0,0 +1,89 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import forms, models, views
|
||||
|
||||
|
||||
@patch("bookwyrm.suggested_users.remove_user_task.delay")
|
||||
class DeleteUserViews(TestCase):
|
||||
"""view user and edit profile"""
|
||||
|
||||
def setUp(self):
|
||||
"""we need basic test data and mocks"""
|
||||
self.factory = RequestFactory()
|
||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||
):
|
||||
self.local_user = models.User.objects.create_user(
|
||||
"mouse@local.com",
|
||||
"mouse@mouse.mouse",
|
||||
"password",
|
||||
local=True,
|
||||
localname="mouse",
|
||||
)
|
||||
self.rat = models.User.objects.create_user(
|
||||
"rat@local.com", "rat@rat.rat", "password", local=True, localname="rat"
|
||||
)
|
||||
|
||||
self.book = models.Edition.objects.create(
|
||||
title="test", parent_work=models.Work.objects.create(title="test work")
|
||||
)
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.add_book_statuses_task.delay"
|
||||
):
|
||||
models.ShelfBook.objects.create(
|
||||
book=self.book,
|
||||
user=self.local_user,
|
||||
shelf=self.local_user.shelf_set.first(),
|
||||
)
|
||||
|
||||
models.SiteSettings.objects.create()
|
||||
|
||||
def test_delete_user_page(self, _):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.DeleteUser.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
@patch("bookwyrm.suggested_users.rerank_suggestions_task")
|
||||
def test_delete_user(self, *_):
|
||||
"""use a form to update a user"""
|
||||
view = views.DeleteUser.as_view()
|
||||
form = forms.DeleteUserForm()
|
||||
form.data["password"] = "password"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
middleware = SessionMiddleware()
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
|
||||
self.assertIsNone(self.local_user.name)
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
activity = json.loads(delay_mock.call_args[0][1])
|
||||
self.assertEqual(activity["type"], "Delete")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(
|
||||
activity["cc"][0], "https://www.w3.org/ns/activitystreams#Public"
|
||||
)
|
||||
|
||||
self.local_user.refresh_from_db()
|
||||
self.assertFalse(self.local_user.is_active)
|
||||
self.assertEqual(self.local_user.deactivation_reason, "self_deletion")
|
@ -1,11 +1,10 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
from PIL import Image
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.template.response import TemplateResponse
|
||||
@ -59,7 +58,10 @@ class EditUserViews(TestCase):
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_edit_user(self, _):
|
||||
@ -91,8 +93,9 @@ class EditUserViews(TestCase):
|
||||
form.data["default_post_privacy"] = "public"
|
||||
form.data["preferred_timezone"] = "UTC"
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
"../../../static/images/no_cover.jpg"
|
||||
)
|
||||
# pylint: disable=consider-using-with
|
||||
form.data["avatar"] = SimpleUploadedFile(
|
||||
image_file, open(image_file, "rb").read(), content_type="image/jpeg"
|
||||
)
|
||||
@ -113,50 +116,11 @@ class EditUserViews(TestCase):
|
||||
def test_crop_avatar(self, _):
|
||||
"""reduce that image size"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/no_cover.jpg"
|
||||
"../../../static/images/no_cover.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
|
||||
result = views.edit_user.crop_avatar(image)
|
||||
result = views.preferences.edit_user.crop_avatar(image)
|
||||
self.assertIsInstance(result, ContentFile)
|
||||
image_result = Image.open(result)
|
||||
self.assertEqual(image_result.size, (120, 120))
|
||||
|
||||
def test_delete_user_page(self, _):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.DeleteUser.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
@patch("bookwyrm.suggested_users.rerank_suggestions_task")
|
||||
def test_delete_user(self, *_):
|
||||
"""use a form to update a user"""
|
||||
view = views.DeleteUser.as_view()
|
||||
form = forms.DeleteUserForm()
|
||||
form.data["password"] = "password"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
middleware = SessionMiddleware()
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
|
||||
self.assertIsNone(self.local_user.name)
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
view(request)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
activity = json.loads(delay_mock.call_args[0][1])
|
||||
self.assertEqual(activity["type"], "Delete")
|
||||
self.assertEqual(activity["actor"], self.local_user.remote_id)
|
||||
self.assertEqual(
|
||||
activity["cc"][0], "https://www.w3.org/ns/activitystreams#Public"
|
||||
)
|
||||
|
||||
self.local_user.refresh_from_db()
|
||||
self.assertFalse(self.local_user.is_active)
|
||||
self.assertEqual(self.local_user.deactivation_reason, "self_deletion")
|
@ -9,6 +9,7 @@ import responses
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http import Http404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -133,8 +134,8 @@ class BookViews(TestCase):
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.views.books.is_api_request") as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, 0)
|
||||
self.assertEqual(result.status_code, 404)
|
||||
with self.assertRaises(Http404):
|
||||
view(request, 0)
|
||||
|
||||
def test_book_page_work_id(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
@ -282,6 +283,46 @@ class BookViews(TestCase):
|
||||
self.assertEqual(book.authors.first().name, "Sappho")
|
||||
self.assertEqual(book.authors.first(), book.parent_work.authors.first())
|
||||
|
||||
def _setup_cover_url(self):
|
||||
cover_url = "http://example.com"
|
||||
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)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
cover_url,
|
||||
body=output.getvalue(),
|
||||
status=200,
|
||||
)
|
||||
return cover_url
|
||||
|
||||
@responses.activate
|
||||
def test_create_book_upload_cover_url(self):
|
||||
"""create an entirely new book and work with cover url"""
|
||||
self.assertFalse(self.book.cover)
|
||||
view = views.ConfirmEditBook.as_view()
|
||||
self.local_user.groups.add(self.group)
|
||||
cover_url = self._setup_cover_url()
|
||||
|
||||
form = forms.EditionForm()
|
||||
form.data["title"] = "New Title"
|
||||
form.data["last_edited_by"] = self.local_user.id
|
||||
form.data["cover-url"] = cover_url
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
with patch(
|
||||
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
|
||||
) as delay_mock:
|
||||
views.upload_cover(request, self.book.id)
|
||||
self.assertEqual(delay_mock.call_count, 1)
|
||||
|
||||
self.book.refresh_from_db()
|
||||
self.assertTrue(self.book.cover)
|
||||
|
||||
def test_upload_cover_file(self):
|
||||
"""add a cover via file upload"""
|
||||
self.assertFalse(self.book.cover)
|
||||
@ -310,21 +351,8 @@ class BookViews(TestCase):
|
||||
def test_upload_cover_url(self):
|
||||
"""add a cover via url"""
|
||||
self.assertFalse(self.book.cover)
|
||||
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)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://example.com",
|
||||
body=output.getvalue(),
|
||||
status=200,
|
||||
)
|
||||
|
||||
form = forms.CoverForm(instance=self.book)
|
||||
form.data["cover-url"] = "http://example.com"
|
||||
form.data["cover-url"] = self._setup_cover_url()
|
||||
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
@ -1,5 +1,6 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.template.response import TemplateResponse
|
||||
@ -51,7 +52,16 @@ class DirectoryViews(TestCase):
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_directory_page_empty(self):
|
||||
@ -62,7 +72,10 @@ class DirectoryViews(TestCase):
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(html.content, options={"drop-empty-elements": False})
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_directory_page_logged_out(self):
|
||||
|
@ -5,6 +5,7 @@ import pathlib
|
||||
|
||||
from PIL import Image
|
||||
from django.core.files.base import ContentFile
|
||||
from django.http import Http404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
@ -81,9 +82,8 @@ class FeedViews(TestCase):
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.views.feed.is_api_request") as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse", 12345)
|
||||
|
||||
self.assertEqual(result.status_code, 404)
|
||||
with self.assertRaises(Http404):
|
||||
view(request, "mouse", 12345)
|
||||
|
||||
def test_status_page_not_found_wrong_user(self, *_):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
@ -102,9 +102,8 @@ class FeedViews(TestCase):
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.views.feed.is_api_request") as is_api:
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse", status.id)
|
||||
|
||||
self.assertEqual(result.status_code, 404)
|
||||
with self.assertRaises(Http404):
|
||||
view(request, "mouse", status.id)
|
||||
|
||||
def test_status_page_with_image(self, *_):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
|
@ -1,11 +1,13 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from django.utils import timezone
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import Http404
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.utils import timezone
|
||||
|
||||
from bookwyrm import models, views
|
||||
|
||||
@ -60,7 +62,16 @@ class GoalViews(TestCase):
|
||||
request.user = self.local_user
|
||||
|
||||
result = view(request, self.local_user.localname, self.year)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
|
||||
def test_goal_page_anonymous(self):
|
||||
@ -91,7 +102,16 @@ class GoalViews(TestCase):
|
||||
request.user = self.rat
|
||||
|
||||
result = view(request, self.local_user.localname, timezone.now().year)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
|
||||
def test_goal_page_private(self):
|
||||
@ -103,8 +123,8 @@ class GoalViews(TestCase):
|
||||
request = self.factory.get("")
|
||||
request.user = self.rat
|
||||
|
||||
result = view(request, self.local_user.localname, self.year)
|
||||
self.assertEqual(result.status_code, 404)
|
||||
with self.assertRaises(Http404):
|
||||
view(request, self.local_user.localname, self.year)
|
||||
|
||||
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||
def test_create_goal(self, _):
|
||||
|
@ -568,5 +568,6 @@ class ListActionViews(TestCase):
|
||||
)
|
||||
request.user = self.rat
|
||||
|
||||
views.list.remove_book(request, self.list.id)
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.list.remove_book(request, self.list.id)
|
||||
self.assertTrue(self.list.listitem_set.exists())
|
||||
|
@ -43,12 +43,14 @@ class PasswordViews(TestCase):
|
||||
def test_password_reset_request_post(self):
|
||||
"""send 'em an email"""
|
||||
request = self.factory.post("", {"email": "aa@bb.ccc"})
|
||||
request.user = self.anonymous_user
|
||||
view = views.PasswordResetRequest.as_view()
|
||||
resp = view(request)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
resp.render()
|
||||
|
||||
request = self.factory.post("", {"email": "mouse@mouse.com"})
|
||||
request.user = self.anonymous_user
|
||||
with patch("bookwyrm.emailing.send_email.delay"):
|
||||
resp = view(request)
|
||||
resp.render()
|
||||
@ -93,33 +95,3 @@ class PasswordViews(TestCase):
|
||||
resp = view(request, code.code)
|
||||
resp.render()
|
||||
self.assertTrue(models.PasswordReset.objects.exists())
|
||||
|
||||
def test_password_change_get(self):
|
||||
"""there are so many views, this just makes sure it LOADS"""
|
||||
view = views.ChangePassword.as_view()
|
||||
request = self.factory.get("")
|
||||
request.user = self.local_user
|
||||
|
||||
result = view(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
def test_password_change(self):
|
||||
"""change password"""
|
||||
view = views.ChangePassword.as_view()
|
||||
password_hash = self.local_user.password
|
||||
request = self.factory.post("", {"password": "hi", "confirm-password": "hi"})
|
||||
request.user = self.local_user
|
||||
with patch("bookwyrm.views.password.login"):
|
||||
view(request)
|
||||
self.assertNotEqual(self.local_user.password, password_hash)
|
||||
|
||||
def test_password_change_mismatch(self):
|
||||
"""change password"""
|
||||
view = views.ChangePassword.as_view()
|
||||
password_hash = self.local_user.password
|
||||
request = self.factory.post("", {"password": "hi", "confirm-password": "hihi"})
|
||||
request.user = self.local_user
|
||||
view(request)
|
||||
self.assertEqual(self.local_user.password, password_hash)
|
||||
|
@ -113,6 +113,7 @@ class ReadingViews(TestCase):
|
||||
{
|
||||
"post-status": True,
|
||||
"privacy": "followers",
|
||||
"start_date": readthrough.start_date,
|
||||
"finish_date": timezone.now().isoformat(),
|
||||
"id": readthrough.id,
|
||||
},
|
||||
|
@ -1,11 +1,14 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import models, views
|
||||
from bookwyrm import forms, models, views
|
||||
from bookwyrm.activitypub import ActivitypubResponse
|
||||
|
||||
|
||||
@ -53,7 +56,16 @@ class ShelfViews(TestCase):
|
||||
is_api.return_value = False
|
||||
result = view(request, self.local_user.username, shelf.identifier)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch("bookwyrm.views.shelf.is_api_request") as is_api:
|
||||
@ -105,7 +117,7 @@ class ShelfViews(TestCase):
|
||||
shelf.refresh_from_db()
|
||||
|
||||
self.assertEqual(shelf.name, "cool name")
|
||||
self.assertEqual(shelf.identifier, "testshelf-%d" % shelf.id)
|
||||
self.assertEqual(shelf.identifier, f"testshelf-{shelf.id}")
|
||||
|
||||
def test_edit_shelf_name_not_editable(self, *_):
|
||||
"""can't change the name of an non-editable shelf"""
|
||||
@ -122,7 +134,7 @@ class ShelfViews(TestCase):
|
||||
|
||||
self.assertEqual(shelf.name, "To Read")
|
||||
|
||||
def test_handle_shelve(self, *_):
|
||||
def test_shelve(self, *_):
|
||||
"""shelve a book"""
|
||||
request = self.factory.post(
|
||||
"", {"book": self.book.id, "shelf": self.shelf.identifier}
|
||||
@ -140,7 +152,7 @@ class ShelfViews(TestCase):
|
||||
# make sure the book is on the shelf
|
||||
self.assertEqual(self.shelf.books.get(), self.book)
|
||||
|
||||
def test_handle_shelve_to_read(self, *_):
|
||||
def test_shelve_to_read(self, *_):
|
||||
"""special behavior for the to-read shelf"""
|
||||
shelf = models.Shelf.objects.get(identifier="to-read")
|
||||
request = self.factory.post(
|
||||
@ -153,7 +165,7 @@ class ShelfViews(TestCase):
|
||||
# make sure the book is on the shelf
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
||||
def test_handle_shelve_reading(self, *_):
|
||||
def test_shelve_reading(self, *_):
|
||||
"""special behavior for the reading shelf"""
|
||||
shelf = models.Shelf.objects.get(identifier="reading")
|
||||
request = self.factory.post(
|
||||
@ -166,7 +178,7 @@ class ShelfViews(TestCase):
|
||||
# make sure the book is on the shelf
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
||||
def test_handle_shelve_read(self, *_):
|
||||
def test_shelve_read(self, *_):
|
||||
"""special behavior for the read shelf"""
|
||||
shelf = models.Shelf.objects.get(identifier="read")
|
||||
request = self.factory.post(
|
||||
@ -179,7 +191,7 @@ class ShelfViews(TestCase):
|
||||
# make sure the book is on the shelf
|
||||
self.assertEqual(shelf.books.get(), self.book)
|
||||
|
||||
def test_handle_unshelve(self, *_):
|
||||
def test_unshelve(self, *_):
|
||||
"""remove a book from a shelf"""
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
models.ShelfBook.objects.create(
|
||||
@ -197,3 +209,76 @@ class ShelfViews(TestCase):
|
||||
self.assertEqual(activity["type"], "Remove")
|
||||
self.assertEqual(activity["object"]["id"], item.remote_id)
|
||||
self.assertEqual(self.shelf.books.count(), 0)
|
||||
|
||||
def test_create_shelf(self, *_):
|
||||
"""a brand new custom shelf"""
|
||||
form = forms.ShelfForm()
|
||||
form.data["user"] = self.local_user.id
|
||||
form.data["name"] = "new shelf name"
|
||||
form.data["description"] = "desc"
|
||||
form.data["privacy"] = "unlisted"
|
||||
request = self.factory.post("", form.data)
|
||||
request.user = self.local_user
|
||||
|
||||
views.create_shelf(request)
|
||||
|
||||
shelf = models.Shelf.objects.get(name="new shelf name")
|
||||
self.assertEqual(shelf.privacy, "unlisted")
|
||||
self.assertEqual(shelf.description, "desc")
|
||||
self.assertEqual(shelf.user, self.local_user)
|
||||
|
||||
def test_delete_shelf(self, *_):
|
||||
"""delete a brand new custom shelf"""
|
||||
request = self.factory.post("")
|
||||
request.user = self.local_user
|
||||
shelf_id = self.shelf.id
|
||||
|
||||
views.delete_shelf(request, shelf_id)
|
||||
|
||||
self.assertFalse(models.Shelf.objects.filter(id=shelf_id).exists())
|
||||
|
||||
def test_delete_shelf_unauthorized(self, *_):
|
||||
"""delete a brand new custom shelf"""
|
||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||
):
|
||||
rat = models.User.objects.create_user(
|
||||
"rat@local.com",
|
||||
"rat@mouse.mouse",
|
||||
"password",
|
||||
local=True,
|
||||
localname="rat",
|
||||
)
|
||||
request = self.factory.post("")
|
||||
request.user = rat
|
||||
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.delete_shelf(request, self.shelf.id)
|
||||
|
||||
self.assertTrue(models.Shelf.objects.filter(id=self.shelf.id).exists())
|
||||
|
||||
def test_delete_shelf_has_book(self, *_):
|
||||
"""delete a brand new custom shelf"""
|
||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||
models.ShelfBook.objects.create(
|
||||
book=self.book, user=self.local_user, shelf=self.shelf
|
||||
)
|
||||
request = self.factory.post("")
|
||||
request.user = self.local_user
|
||||
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.delete_shelf(request, self.shelf.id)
|
||||
|
||||
self.assertTrue(models.Shelf.objects.filter(id=self.shelf.id).exists())
|
||||
|
||||
def test_delete_shelf_not_editable(self, *_):
|
||||
"""delete a brand new custom shelf"""
|
||||
shelf = self.local_user.shelf_set.first()
|
||||
self.assertFalse(shelf.editable)
|
||||
request = self.factory.post("")
|
||||
request.user = self.local_user
|
||||
|
||||
with self.assertRaises(PermissionDenied):
|
||||
views.delete_shelf(request, shelf.id)
|
||||
|
||||
self.assertTrue(models.Shelf.objects.filter(id=shelf.id).exists())
|
||||
|
@ -1,6 +1,7 @@
|
||||
""" test for app action functionality """
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
@ -101,7 +102,7 @@ class StatusViews(TestCase):
|
||||
"""@mention a user in a post"""
|
||||
view = views.CreateStatus.as_view()
|
||||
user = models.User.objects.create_user(
|
||||
"rat@%s" % DOMAIN,
|
||||
f"rat@{DOMAIN}",
|
||||
"rat@rat.com",
|
||||
"password",
|
||||
local=True,
|
||||
@ -124,7 +125,7 @@ class StatusViews(TestCase):
|
||||
self.assertEqual(list(status.mention_users.all()), [user])
|
||||
self.assertEqual(models.Notification.objects.get().user, user)
|
||||
self.assertEqual(
|
||||
status.content, '<p>hi <a href="%s">@rat</a></p>' % user.remote_id
|
||||
status.content, f'<p>hi <a href="{user.remote_id}">@rat</a></p>'
|
||||
)
|
||||
|
||||
def test_handle_status_reply_with_mentions(self, *_):
|
||||
@ -196,9 +197,9 @@ class StatusViews(TestCase):
|
||||
)
|
||||
|
||||
with patch("bookwyrm.activitystreams.remove_status_task.delay") as mock:
|
||||
result = view(request, status.id)
|
||||
with self.assertRaises(PermissionDenied):
|
||||
view(request, status.id)
|
||||
self.assertFalse(mock.called)
|
||||
self.assertEqual(result.status_code, 400)
|
||||
|
||||
status.refresh_from_db()
|
||||
self.assertFalse(status.deleted)
|
||||
@ -214,9 +215,9 @@ class StatusViews(TestCase):
|
||||
)
|
||||
|
||||
with patch("bookwyrm.activitystreams.remove_status_task.delay") as mock:
|
||||
result = view(request, status.id)
|
||||
with self.assertRaises(PermissionDenied):
|
||||
view(request, status.id)
|
||||
self.assertFalse(mock.called)
|
||||
self.assertEqual(result.status_code, 400)
|
||||
|
||||
status.refresh_from_db()
|
||||
self.assertFalse(status.deleted)
|
||||
@ -224,13 +225,13 @@ class StatusViews(TestCase):
|
||||
def test_find_mentions(self, *_):
|
||||
"""detect and look up @ mentions of users"""
|
||||
user = models.User.objects.create_user(
|
||||
"nutria@%s" % DOMAIN,
|
||||
f"nutria@{DOMAIN}",
|
||||
"nutria@nutria.com",
|
||||
"password",
|
||||
local=True,
|
||||
localname="nutria",
|
||||
)
|
||||
self.assertEqual(user.username, "nutria@%s" % DOMAIN)
|
||||
self.assertEqual(user.username, f"nutria@{DOMAIN}")
|
||||
|
||||
self.assertEqual(
|
||||
list(views.status.find_mentions("@nutria"))[0], ("@nutria", user)
|
||||
@ -263,19 +264,19 @@ class StatusViews(TestCase):
|
||||
self.assertEqual(list(views.status.find_mentions("@beep@beep.com")), [])
|
||||
|
||||
self.assertEqual(
|
||||
list(views.status.find_mentions("@nutria@%s" % DOMAIN))[0],
|
||||
("@nutria@%s" % DOMAIN, user),
|
||||
list(views.status.find_mentions(f"@nutria@{DOMAIN}"))[0],
|
||||
(f"@nutria@{DOMAIN}", user),
|
||||
)
|
||||
|
||||
def test_format_links_simple_url(self, *_):
|
||||
"""find and format urls into a tags"""
|
||||
url = "http://www.fish.com/"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url), '<a href="%s">www.fish.com/</a>' % url
|
||||
views.status.format_links(url), f'<a href="{url}">www.fish.com/</a>'
|
||||
)
|
||||
self.assertEqual(
|
||||
views.status.format_links("(%s)" % url),
|
||||
'(<a href="%s">www.fish.com/</a>)' % url,
|
||||
views.status.format_links(f"({url})"),
|
||||
f'(<a href="{url}">www.fish.com/</a>)',
|
||||
)
|
||||
|
||||
def test_format_links_paragraph_break(self, *_):
|
||||
@ -292,8 +293,8 @@ http://www.fish.com/"""
|
||||
"""find and format urls into a tags"""
|
||||
url = "http://www.fish.com/"
|
||||
self.assertEqual(
|
||||
views.status.format_links("(%s)" % url),
|
||||
'(<a href="%s">www.fish.com/</a>)' % url,
|
||||
views.status.format_links(f"({url})"),
|
||||
f'(<a href="{url}">www.fish.com/</a>)',
|
||||
)
|
||||
|
||||
def test_format_links_special_chars(self, *_):
|
||||
@ -301,27 +302,27 @@ http://www.fish.com/"""
|
||||
url = "https://archive.org/details/dli.granth.72113/page/n25/mode/2up"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url),
|
||||
'<a href="%s">'
|
||||
"archive.org/details/dli.granth.72113/page/n25/mode/2up</a>" % url,
|
||||
f'<a href="{url}">'
|
||||
"archive.org/details/dli.granth.72113/page/n25/mode/2up</a>",
|
||||
)
|
||||
url = "https://openlibrary.org/search?q=arkady+strugatsky&mode=everything"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url),
|
||||
'<a href="%s">openlibrary.org/search'
|
||||
"?q=arkady+strugatsky&mode=everything</a>" % url,
|
||||
f'<a href="{url}">openlibrary.org/search'
|
||||
"?q=arkady+strugatsky&mode=everything</a>",
|
||||
)
|
||||
url = "https://tech.lgbt/@bookwyrm"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url), '<a href="%s">tech.lgbt/@bookwyrm</a>' % url
|
||||
views.status.format_links(url), f'<a href="{url}">tech.lgbt/@bookwyrm</a>'
|
||||
)
|
||||
url = "https://users.speakeasy.net/~lion/nb/book.pdf"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url),
|
||||
'<a href="%s">users.speakeasy.net/~lion/nb/book.pdf</a>' % url,
|
||||
f'<a href="{url}">users.speakeasy.net/~lion/nb/book.pdf</a>',
|
||||
)
|
||||
url = "https://pkm.one/#/page/The%20Book%20which%20launched%20a%201000%20Note%20taking%20apps"
|
||||
url = "https://pkm.one/#/page/The%20Book%20launched%20a%201000%20Note%20apps"
|
||||
self.assertEqual(
|
||||
views.status.format_links(url), '<a href="%s">%s</a>' % (url, url[8:])
|
||||
views.status.format_links(url), f'<a href="{url}">{url[8:]}</a>'
|
||||
)
|
||||
|
||||
def test_to_markdown(self, *_):
|
||||
@ -375,7 +376,8 @@ http://www.fish.com/"""
|
||||
request = self.factory.post("")
|
||||
request.user = self.remote_user
|
||||
|
||||
view(request, status.id)
|
||||
with self.assertRaises(PermissionDenied):
|
||||
view(request, status.id)
|
||||
|
||||
status.refresh_from_db()
|
||||
self.assertFalse(status.deleted)
|
||||
|
@ -1,5 +1,6 @@
|
||||
""" test for app action functionality """
|
||||
from unittest.mock import patch
|
||||
from tidylib import tidy_document
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http.response import Http404
|
||||
@ -55,7 +56,16 @@ class UserViews(TestCase):
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse")
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request.user = self.anonymous_user
|
||||
@ -63,7 +73,16 @@ class UserViews(TestCase):
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse")
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch("bookwyrm.views.user.is_api_request") as is_api:
|
||||
@ -92,7 +111,16 @@ class UserViews(TestCase):
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse")
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch("bookwyrm.views.user.is_api_request") as is_api:
|
||||
@ -123,7 +151,16 @@ class UserViews(TestCase):
|
||||
is_api.return_value = False
|
||||
result = view(request, "mouse")
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
result.render()
|
||||
html = result.render()
|
||||
_, errors = tidy_document(
|
||||
html.content,
|
||||
options={
|
||||
"drop-empty-elements": False,
|
||||
"warn-proprietary-attributes": False,
|
||||
},
|
||||
)
|
||||
if errors:
|
||||
raise Exception(errors)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch("bookwyrm.views.user.is_api_request") as is_api:
|
||||
|
Reference in New Issue
Block a user