1
0
Fork 0

Merge branch 'main' into remove-tags

This commit is contained in:
Mouse Reeve 2021-04-22 18:18:24 -07:00
commit 563623616c
158 changed files with 5668 additions and 2066 deletions

View file

@ -0,0 +1,39 @@
{
"@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"
}
],
"id": "https://example.com/users/rat",
"type": "Person",
"preferredUsername": "rat",
"name": "RAT???",
"inbox": "https://example.com/users/rat/inbox",
"outbox": "https://example.com/users/rat/outbox",
"followers": "https://example.com/users/rat/followers",
"following": "https://example.com/users/rat/following",
"summary": "",
"publicKey": {
"id": "https://example.com/users/rat/#main-key",
"owner": "https://example.com/users/rat",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6QisDrjOQvkRo/MqNmSYPwqtt\nCxg/8rCW+9jKbFUKvqjTeKVotEE85122v/DCvobCCdfQuYIFdVMk+dB1xJ0iPGPg\nyU79QHY22NdV9mFKA2qtXVVxb5cxpA4PlwOHM6PM/k8B+H09OUrop2aPUAYwy+vg\n+MXyz8bAXrIS1kq6fQIDAQAB\n-----END PUBLIC KEY-----"
},
"endpoints": {
"sharedInbox": "https://example.com/inbox"
},
"bookwyrmUser": true,
"manuallyApprovesFollowers": false,
"discoverable": true,
"devices": "https://friend.camp/users/tripofmice/collections/devices",
"tag": [],
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/images/avatars/AL-2-crop-50.png"
}
}

View file

@ -1,5 +1,6 @@
{
"id": "https://bookwyrm.social/book/5989",
"lastEditedBy": "https://example.com/users/rat",
"type": "Edition",
"authors": [
"https://bookwyrm.social/author/417"

View file

@ -0,0 +1 @@
from . import *

View file

@ -0,0 +1,44 @@
""" test populating user streams """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models
from bookwyrm.management.commands.populate_streams import populate_streams
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
class Activitystreams(TestCase):
""" using redis to build activity streams """
def setUp(self):
""" we need some stuff """
self.local_user = models.User.objects.create_user(
"mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)
self.another_user = models.User.objects.create_user(
"nutria", "nutria@nutria.nutria", "password", local=True, localname="nutria"
)
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.book = models.Edition.objects.create(title="test book")
def test_populate_streams(self, _):
""" make sure the function on the redis manager gets called """
with patch("bookwyrm.activitystreams.ActivityStream.add_status"):
models.Comment.objects.create(
user=self.local_user, content="hi", book=self.book
)
with patch(
"bookwyrm.activitystreams.ActivityStream.populate_store"
) as redis_mock:
populate_streams()
self.assertEqual(redis_mock.call_count, 6) # 2 users x 3 streams

View file

@ -155,8 +155,8 @@ class ActivitypubMixins(TestCase):
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)
self.assertTrue(another_remote_user.inbox in recipients)
self.assertTrue(self.remote_user.inbox in recipients)
def test_get_recipients_direct(self, _):
""" determines the recipients for a user's object broadcast """

View file

@ -1,4 +1,5 @@
""" testing models """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models
@ -9,6 +10,22 @@ from bookwyrm.settings import DOMAIN
class BaseModel(TestCase):
""" functionality shared across models """
def setUp(self):
""" shared data """
self.local_user = models.User.objects.create_user(
"mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
)
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",
)
def test_remote_id(self):
""" these should be generated """
instance = base_model.BookWyrmModel()
@ -18,11 +35,8 @@ class BaseModel(TestCase):
def test_remote_id_with_user(self):
""" 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"
)
instance = base_model.BookWyrmModel()
instance.user = user
instance.user = self.local_user
instance.id = 1
expected = instance.get_remote_id()
self.assertEqual(expected, "https://%s/user/mouse/bookwyrmmodel/1" % DOMAIN)
@ -42,3 +56,66 @@ class BaseModel(TestCase):
instance.remote_id = None
base_model.set_remote_id(None, instance, False)
self.assertIsNone(instance.remote_id)
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_object_visible_to_user(self, _):
""" does a user have permission to view an object """
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="public"
)
self.assertTrue(obj.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))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="followers"
)
self.assertFalse(obj.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))
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))
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_object_visible_to_user_follower(self, _):
""" what you can see if you follow a user """
self.remote_user.followers.add(self.local_user)
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="followers"
)
self.assertTrue(obj.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))
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))
@patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_object_visible_to_user_blocked(self, _):
""" you can't see it if they block you """
self.remote_user.blocks.add(self.local_user)
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="public"
)
self.assertFalse(obj.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))

View file

@ -0,0 +1,67 @@
""" testing models """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models
class FederatedServer(TestCase):
""" federate server management """
def setUp(self):
""" we'll need a user """
self.server = models.FederatedServer.objects.create(server_name="test.server")
with patch("bookwyrm.models.user.set_remote_server.delay"):
self.remote_user = models.User.objects.create_user(
"rat",
"rat@rat.com",
"ratword",
federated_server=self.server,
local=False,
remote_id="https://example.com/users/rat",
inbox="https://example.com/users/rat/inbox",
outbox="https://example.com/users/rat/outbox",
)
self.inactive_remote_user = models.User.objects.create_user(
"nutria",
"nutria@nutria.com",
"nutriaword",
federated_server=self.server,
local=False,
remote_id="https://example.com/users/nutria",
inbox="https://example.com/users/nutria/inbox",
outbox="https://example.com/users/nutria/outbox",
is_active=False,
deactivation_reason="self_deletion",
)
def test_block_unblock(self):
""" block a server and all users on it """
self.assertEqual(self.server.status, "federated")
self.assertTrue(self.remote_user.is_active)
self.assertFalse(self.inactive_remote_user.is_active)
self.server.block()
self.assertEqual(self.server.status, "blocked")
self.remote_user.refresh_from_db()
self.assertFalse(self.remote_user.is_active)
self.assertEqual(self.remote_user.deactivation_reason, "domain_block")
self.inactive_remote_user.refresh_from_db()
self.assertFalse(self.inactive_remote_user.is_active)
self.assertEqual(self.inactive_remote_user.deactivation_reason, "self_deletion")
# UNBLOCK
self.server.unblock()
self.assertEqual(self.server.status, "federated")
# user blocked in deactivation is reactivated
self.remote_user.refresh_from_db()
self.assertTrue(self.remote_user.is_active)
self.assertIsNone(self.remote_user.deactivation_reason)
# deleted user remains deleted
self.inactive_remote_user.refresh_from_db()
self.assertFalse(self.inactive_remote_user.is_active)
self.assertEqual(self.inactive_remote_user.deactivation_reason, "self_deletion")

View file

@ -51,11 +51,12 @@ class List(TestCase):
book_list=book_list,
book=self.book,
user=self.local_user,
order=1,
)
self.assertTrue(item.approved)
self.assertEqual(item.privacy, "unlisted")
self.assertEqual(item.recipients, [self.local_user])
self.assertEqual(item.recipients, [])
def test_list_item_pending(self, _):
""" a list entry """
@ -65,10 +66,14 @@ class List(TestCase):
)
item = models.ListItem.objects.create(
book_list=book_list, book=self.book, user=self.local_user, approved=False
book_list=book_list,
book=self.book,
user=self.local_user,
approved=False,
order=1,
)
self.assertFalse(item.approved)
self.assertEqual(item.book_list.privacy, "public")
self.assertEqual(item.privacy, "direct")
self.assertEqual(item.recipients, [self.local_user])
self.assertEqual(item.recipients, [])

View file

@ -1,4 +1,6 @@
""" testing models """
import json
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models, settings
@ -18,30 +20,19 @@ class Shelf(TestCase):
def test_remote_id(self):
""" shelves use custom remote ids """
real_broadcast = models.Shelf.broadcast
def broadcast_mock(_, activity, user, **kwargs):
""" nah """
models.Shelf.broadcast = broadcast_mock
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
expected_id = "https://%s/user/mouse/books/test-shelf" % settings.DOMAIN
self.assertEqual(shelf.get_remote_id(), expected_id)
models.Shelf.broadcast = real_broadcast
def test_to_activity(self):
""" jsonify it """
real_broadcast = models.Shelf.broadcast
def empty_mock(_, activity, user, **kwargs):
""" nah """
models.Shelf.broadcast = empty_mock
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
shelf = models.Shelf.objects.create(
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)
@ -49,77 +40,53 @@ class Shelf(TestCase):
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 """
real_broadcast = models.Shelf.broadcast
def create_mock(_, activity, user, **kwargs):
""" 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")
models.Shelf.broadcast = create_mock
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
def update_mock(_, activity, user, **kwargs):
""" 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")
models.Shelf.broadcast = update_mock
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
activity = json.loads(mock.call_args[0][1])
self.assertEqual(activity["type"], "Create")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["name"], "Test Shelf")
shelf.name = "arthur russel"
shelf.save()
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
shelf.save()
activity = json.loads(mock.call_args[0][1])
self.assertEqual(activity["type"], "Update")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["name"], "arthur russel")
self.assertEqual(shelf.name, "arthur russel")
models.Shelf.broadcast = real_broadcast
def test_shelve(self):
""" create and broadcast shelf creation """
real_broadcast = models.Shelf.broadcast
real_shelfbook_broadcast = models.ShelfBook.broadcast
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
def add_mock(_, activity, user, **kwargs):
""" 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)
def remove_mock(_, activity, user, **kwargs):
""" 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)
def empty_mock(_, activity, user, **kwargs):
""" nah """
models.Shelf.broadcast = empty_mock
shelf = models.Shelf.objects.create(
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
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
shelf_book = models.ShelfBook.objects.create(
shelf=shelf, user=self.local_user, book=self.book
)
self.assertEqual(mock.call_count, 1)
activity = json.loads(mock.call_args[0][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], shelf_book.remote_id)
self.assertEqual(activity["target"], shelf.remote_id)
self.assertEqual(shelf.books.first(), self.book)
models.ShelfBook.broadcast = remove_mock
shelf_book.delete()
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
shelf_book.delete()
self.assertEqual(mock.call_count, 1)
activity = json.loads(mock.call_args[0][1])
self.assertEqual(activity["type"], "Remove")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], shelf_book.remote_id)
self.assertEqual(activity["target"], shelf.remote_id)
self.assertFalse(shelf.books.exists())
models.ShelfBook.broadcast = real_shelfbook_broadcast
models.Shelf.broadcast = real_broadcast

View file

@ -1,4 +1,5 @@
""" testing models """
import json
from unittest.mock import patch
from django.test import TestCase
import responses
@ -152,3 +153,17 @@ class User(TestCase):
self.assertEqual(server.server_name, DOMAIN)
self.assertIsNone(server.application_type)
self.assertIsNone(server.application_version)
def test_delete_user(self):
""" deactivate a user """
self.assertTrue(self.user.is_active)
with patch(
"bookwyrm.models.activitypub_mixin.broadcast_task.delay"
) as broadcast_mock:
self.user.delete()
self.assertEqual(broadcast_mock.call_count, 1)
activity = json.loads(broadcast_mock.call_args[0][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"], self.user.remote_id)
self.assertFalse(self.user.is_active)

View file

@ -181,36 +181,6 @@ class TemplateTags(TestCase):
uuid = bookwyrm_tags.get_uuid("hi")
self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
def test_time_since(self, _):
""" ultraconcise timestamps """
self.assertEqual(bookwyrm_tags.time_since("bleh"), "")
now = timezone.now()
self.assertEqual(bookwyrm_tags.time_since(now), "0s")
seconds_ago = now - relativedelta(seconds=4)
self.assertEqual(bookwyrm_tags.time_since(seconds_ago), "4s")
minutes_ago = now - relativedelta(minutes=8)
self.assertEqual(bookwyrm_tags.time_since(minutes_ago), "8m")
hours_ago = now - relativedelta(hours=9)
self.assertEqual(bookwyrm_tags.time_since(hours_ago), "9h")
days_ago = now - relativedelta(days=3)
self.assertEqual(bookwyrm_tags.time_since(days_ago), "3d")
# I am not going to figure out how to mock dates tonight.
months_ago = now - relativedelta(months=5)
self.assertTrue(
re.match(r"[A-Z][a-z]{2} \d?\d", bookwyrm_tags.time_since(months_ago))
)
years_ago = now - relativedelta(years=10)
self.assertTrue(
re.match(r"[A-Z][a-z]{2} \d?\d \d{4}", bookwyrm_tags.time_since(years_ago))
)
def test_get_markdown(self, _):
""" mardown format data """
result = bookwyrm_tags.get_markdown("_hi_")

View file

@ -1,11 +1,13 @@
""" tests incoming activities"""
import json
import pathlib
from unittest.mock import patch
from django.http import HttpResponseNotAllowed, HttpResponseNotFound
from django.test import TestCase, Client
from django.test.client import RequestFactory
from bookwyrm import models
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
@ -15,6 +17,7 @@ class Inbox(TestCase):
def setUp(self):
""" basic user and book data """
self.client = Client()
self.factory = RequestFactory()
local_user = models.User.objects.create_user(
"mouse@example.com",
"mouse@mouse.com",
@ -24,6 +27,16 @@ class Inbox(TestCase):
)
local_user.remote_id = "https://example.com/user/mouse"
local_user.save(broadcast=False)
with patch("bookwyrm.models.user.set_remote_server.delay"):
self.remote_user = models.User.objects.create_user(
"rat",
"rat@rat.com",
"ratword",
local=False,
remote_id="https://example.com/users/rat",
inbox="https://example.com/users/rat/inbox",
outbox="https://example.com/users/rat/outbox",
)
self.create_json = {
"id": "hi",
"type": "Create",
@ -106,3 +119,44 @@ class Inbox(TestCase):
"/inbox", json.dumps(activity), content_type="application/json"
)
self.assertEqual(result.status_code, 200)
def test_is_blocked_user_agent(self):
""" check for blocked servers """
request = self.factory.post(
"",
HTTP_USER_AGENT="http.rb/4.4.1 (Mastodon/3.3.0; +https://mastodon.social/)",
)
self.assertFalse(views.inbox.is_blocked_user_agent(request))
models.FederatedServer.objects.create(
server_name="mastodon.social", status="blocked"
)
self.assertTrue(views.inbox.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))
models.FederatedServer.objects.create(
server_name="mastodon.social", status="blocked"
)
self.assertTrue(views.inbox.is_blocked_activity(activity))
def test_create_by_deactivated_user(self):
""" don't let deactivated users post """
self.remote_user.delete(broadcast=False)
self.assertTrue(self.remote_user.deleted)
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_note.json")
status_data = json.loads(datafile.read_bytes())
activity = self.create_json
activity["actor"] = self.remote_user.remote_id
activity["object"] = status_data
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)

View file

@ -94,6 +94,7 @@ class InboxAdd(TestCase):
"type": "ListItem",
"book": self.book.remote_id,
"id": "https://bookwyrm.social/listbook/6189",
"order": 1,
},
"target": "https://bookwyrm.social/user/mouse/list/to-read",
"@context": "https://www.w3.org/ns/activitystreams",

View file

@ -136,6 +136,9 @@ class InboxActivities(TestCase):
"id": "http://www.faraway.com/boost/12",
"actor": self.remote_user.remote_id,
"object": status.remote_id,
"to": ["https://www.w3.org/ns/activitystreams#public"],
"cc": ["https://example.com/user/mouse/followers"],
"published": "Mon, 25 May 2020 19:31:20 GMT",
}
responses.add(
responses.GET, status.remote_id, json=status.to_activity(), status=200
@ -185,6 +188,7 @@ class InboxActivities(TestCase):
"id": "http://fake.com/unknown/boost",
"actor": self.remote_user.remote_id,
"object": self.status.remote_id,
"published": "Mon, 25 May 2020 19:31:20 GMT",
},
}
views.inbox.activity_task(activity)

View file

@ -6,6 +6,7 @@ from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models, views
from bookwyrm.activitypub import ActivitySerializerError
# pylint: disable=too-many-public-methods
@ -31,7 +32,7 @@ class InboxCreate(TestCase):
remote_id="https://example.com/status/1",
)
with patch("bookwyrm.models.user.set_remote_server.delay"):
models.User.objects.create_user(
self.remote_user = models.User.objects.create_user(
"rat",
"rat@rat.com",
"ratword",
@ -51,7 +52,7 @@ class InboxCreate(TestCase):
}
models.SiteSettings.objects.create()
def test_handle_create_status(self):
def test_create_status(self):
""" the "it justs works" mode """
self.assertEqual(models.Status.objects.count(), 1)
@ -82,7 +83,7 @@ class InboxCreate(TestCase):
views.inbox.activity_task(activity)
self.assertEqual(models.Status.objects.count(), 2)
def test_handle_create_status_remote_note_with_mention(self):
def test_create_status_remote_note_with_mention(self):
""" should only create it under the right circumstances """
self.assertEqual(models.Status.objects.count(), 1)
self.assertFalse(
@ -105,7 +106,7 @@ class InboxCreate(TestCase):
)
self.assertEqual(models.Notification.objects.get().notification_type, "MENTION")
def test_handle_create_status_remote_note_with_reply(self):
def test_create_status_remote_note_with_reply(self):
""" should only create it under the right circumstances """
self.assertEqual(models.Status.objects.count(), 1)
self.assertFalse(models.Notification.objects.filter(user=self.local_user))
@ -126,7 +127,7 @@ class InboxCreate(TestCase):
self.assertTrue(models.Notification.objects.filter(user=self.local_user))
self.assertEqual(models.Notification.objects.get().notification_type, "REPLY")
def test_handle_create_list(self):
def test_create_list(self):
""" a new list """
activity = self.create_json
activity["object"] = {
@ -149,3 +150,23 @@ class InboxCreate(TestCase):
self.assertEqual(book_list.curation, "curated")
self.assertEqual(book_list.description, "summary text")
self.assertEqual(book_list.remote_id, "https://example.com/list/22")
def test_create_unsupported_type(self):
""" ignore activities we know we can't handle """
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Question",
}
# just observer how it doesn't throw an error
views.inbox.activity_task(activity)
def test_create_unknown_type(self):
""" ignore activities we know we've never heard of """
activity = self.create_json
activity["object"] = {
"id": "https://example.com/status/887",
"type": "Threnody",
}
with self.assertRaises(ActivitySerializerError):
views.inbox.activity_task(activity)

View file

@ -49,7 +49,7 @@ class InboxActivities(TestCase):
}
models.SiteSettings.objects.create()
def test_handle_delete_status(self):
def test_delete_status(self):
""" remove a status """
self.assertFalse(self.status.deleted)
activity = {
@ -70,7 +70,7 @@ class InboxActivities(TestCase):
self.assertTrue(status.deleted)
self.assertIsInstance(status.deleted_date, datetime)
def test_handle_delete_status_notifications(self):
def test_delete_status_notifications(self):
""" remove a status with related notifications """
models.Notification.objects.create(
related_status=self.status,
@ -104,3 +104,34 @@ class InboxActivities(TestCase):
# notifications should be truly deleted
self.assertEqual(models.Notification.objects.count(), 1)
self.assertEqual(models.Notification.objects.get(), notif)
def test_delete_user(self):
""" delete a user """
self.assertTrue(models.User.objects.get(username="rat@example.com").is_active)
activity = {
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/users/test-user#delete",
"type": "Delete",
"actor": "https://example.com/users/test-user",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"object": self.remote_user.remote_id,
}
views.inbox.activity_task(activity)
self.assertFalse(models.User.objects.get(username="rat@example.com").is_active)
def test_delete_user_unknown(self):
""" don't worry about it if we don't know the user """
self.assertEqual(models.User.objects.filter(is_active=True).count(), 2)
activity = {
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/users/test-user#delete",
"type": "Delete",
"actor": "https://example.com/users/test-user",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"object": "https://example.com/users/test-user",
}
# nothing happens.
views.inbox.activity_task(activity)
self.assertEqual(models.User.objects.filter(is_active=True).count(), 2)

View file

@ -1,4 +1,5 @@
""" tests incoming activities"""
import json
from unittest.mock import patch
from django.test import TestCase
@ -34,7 +35,7 @@ class InboxRelationships(TestCase):
models.SiteSettings.objects.create()
def test_handle_follow(self):
def test_follow(self):
""" remote user wants to follow local user """
activity = {
"@context": "https://www.w3.org/ns/activitystreams",
@ -48,6 +49,8 @@ class InboxRelationships(TestCase):
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
views.inbox.activity_task(activity)
self.assertEqual(mock.call_count, 1)
response_activity = json.loads(mock.call_args[0][1])
self.assertEqual(response_activity["type"], "Accept")
# notification created
notification = models.Notification.objects.get()
@ -61,7 +64,34 @@ class InboxRelationships(TestCase):
follow = models.UserFollows.objects.get(user_object=self.local_user)
self.assertEqual(follow.user_subject, self.remote_user)
def test_handle_follow_manually_approved(self):
def test_follow_duplicate(self):
""" remote user wants to follow local user twice """
activity = {
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/users/rat/follows/123",
"type": "Follow",
"actor": "https://example.com/users/rat",
"object": "https://example.com/user/mouse",
}
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.inbox.activity_task(activity)
# the follow relationship should exist
follow = models.UserFollows.objects.get(user_object=self.local_user)
self.assertEqual(follow.user_subject, self.remote_user)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
views.inbox.activity_task(activity)
self.assertEqual(mock.call_count, 1)
response_activity = json.loads(mock.call_args[0][1])
self.assertEqual(response_activity["type"], "Accept")
# the follow relationship should STILL exist
follow = models.UserFollows.objects.get(user_object=self.local_user)
self.assertEqual(follow.user_subject, self.remote_user)
def test_follow_manually_approved(self):
""" needs approval before following """
activity = {
"@context": "https://www.w3.org/ns/activitystreams",
@ -91,7 +121,7 @@ class InboxRelationships(TestCase):
follow = models.UserFollows.objects.all()
self.assertEqual(list(follow), [])
def test_handle_undo_follow_request(self):
def test_undo_follow_request(self):
""" the requester cancels a follow request """
self.local_user.manually_approves_followers = True
self.local_user.save(broadcast=False)
@ -121,7 +151,7 @@ class InboxRelationships(TestCase):
self.assertFalse(self.local_user.follower_requests.exists())
def test_handle_unfollow(self):
def test_unfollow(self):
""" remove a relationship """
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
rel = models.UserFollows.objects.create(
@ -146,7 +176,7 @@ class InboxRelationships(TestCase):
views.inbox.activity_task(activity)
self.assertIsNone(self.local_user.followers.first())
def test_handle_follow_accept(self):
def test_follow_accept(self):
""" a remote user approved a follow request from local """
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
rel = models.UserFollowRequest.objects.create(
@ -177,7 +207,7 @@ class InboxRelationships(TestCase):
self.assertEqual(follows.count(), 1)
self.assertEqual(follows.first(), self.local_user)
def test_handle_follow_reject(self):
def test_follow_reject(self):
""" turn down a follow request """
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
rel = models.UserFollowRequest.objects.create(

View file

@ -80,6 +80,7 @@ class InboxRemove(TestCase):
user=self.local_user,
book=self.book,
book_list=booklist,
order=1,
)
self.assertEqual(booklist.books.count(), 1)

View file

@ -23,6 +23,16 @@ class InboxUpdate(TestCase):
)
self.local_user.remote_id = "https://example.com/user/mouse"
self.local_user.save(broadcast=False)
with patch("bookwyrm.models.user.set_remote_server.delay"):
self.remote_user = models.User.objects.create_user(
"rat",
"rat@rat.com",
"ratword",
local=False,
remote_id="https://example.com/users/rat",
inbox="https://example.com/users/rat/inbox",
outbox="https://example.com/users/rat/outbox",
)
self.create_json = {
"id": "hi",
@ -34,7 +44,7 @@ class InboxUpdate(TestCase):
}
models.SiteSettings.objects.create()
def test_handle_update_list(self):
def test_update_list(self):
""" a new list """
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
book_list = models.List.objects.create(
@ -68,16 +78,24 @@ class InboxUpdate(TestCase):
self.assertEqual(book_list.description, "summary text")
self.assertEqual(book_list.remote_id, "https://example.com/list/22")
def test_handle_update_user(self):
def test_update_user(self):
""" update an existing user """
# we only do this with remote users
self.local_user.local = False
self.local_user.save()
models.UserFollows.objects.create(
user_subject=self.local_user,
user_object=self.remote_user,
)
models.UserFollows.objects.create(
user_subject=self.remote_user,
user_object=self.local_user,
)
self.assertTrue(self.remote_user in self.local_user.followers.all())
self.assertTrue(self.local_user in self.remote_user.followers.all())
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_user.json")
datafile = pathlib.Path(__file__).parent.joinpath("../../data/ap_user_rat.json")
userdata = json.loads(datafile.read_bytes())
del userdata["icon"]
self.assertIsNone(self.local_user.name)
self.assertIsNone(self.remote_user.name)
self.assertFalse(self.remote_user.discoverable)
views.inbox.activity_task(
{
"type": "Update",
@ -88,13 +106,16 @@ class InboxUpdate(TestCase):
"object": userdata,
}
)
user = models.User.objects.get(id=self.local_user.id)
self.assertEqual(user.name, "MOUSE?? MOUSE!!")
self.assertEqual(user.username, "mouse@example.com")
self.assertEqual(user.localname, "mouse")
user = models.User.objects.get(id=self.remote_user.id)
self.assertEqual(user.name, "RAT???")
self.assertEqual(user.username, "rat@example.com")
self.assertTrue(user.discoverable)
def test_handle_update_edition(self):
# make sure relationships aren't disrupted
self.assertTrue(self.remote_user in self.local_user.followers.all())
self.assertTrue(self.local_user in self.remote_user.followers.all())
def test_update_edition(self):
""" update an existing edition """
datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_edition.json")
bookdata = json.loads(datafile.read_bytes())
@ -122,8 +143,9 @@ class InboxUpdate(TestCase):
)
book = models.Edition.objects.get(id=book.id)
self.assertEqual(book.title, "Piranesi")
self.assertEqual(book.last_edited_by, self.remote_user)
def test_handle_update_work(self):
def test_update_work(self):
""" update an existing edition """
datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_work.json")
bookdata = json.loads(datafile.read_bytes())

View file

@ -47,6 +47,39 @@ class BookViews(TestCase):
)
models.SiteSettings.objects.create()
def test_date_regression(self):
"""ensure that creating a new book actually saves the published date fields
this was initially a regression due to using a custom date picker tag
"""
first_published_date = "2021-04-20"
published_date = "2022-04-20"
self.local_user.groups.add(self.group)
view = views.EditBook.as_view()
form = forms.EditionForm(
{
"title": "New Title",
"last_edited_by": self.local_user.id,
"first_published_date": first_published_date,
"published_date": published_date,
}
)
request = self.factory.post("", form.data)
request.user = self.local_user
with patch("bookwyrm.connectors.connector_manager.local_search"):
result = view(request)
result.render()
self.assertContains(
result,
f'<input type="date" name="first_published_date" class="input" id="id_first_published_date" value="{first_published_date}">',
)
self.assertContains(
result,
f'<input type="date" name="published_date" class="input" id="id_published_date" value="{published_date}">',
)
def test_book_page(self):
""" there are so many views, this just makes sure it LOADS """
view = views.Book.as_view()

View file

@ -1,9 +1,12 @@
""" test for app action functionality """
import json
from unittest.mock import patch
from django.core.files.uploadedfile import SimpleUploadedFile
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
class FederationViews(TestCase):
@ -19,6 +22,16 @@ class FederationViews(TestCase):
local=True,
localname="mouse",
)
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",
)
models.SiteSettings.objects.create()
def test_federation_page(self):
@ -44,3 +57,111 @@ class FederationViews(TestCase):
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
def test_server_page_block(self):
""" block a server """
server = models.FederatedServer.objects.create(server_name="hi.there.com")
self.remote_user.federated_server = server
self.remote_user.save()
self.assertEqual(server.status, "federated")
view = views.federation.block_server
request = self.factory.post("")
request.user = self.local_user
request.user.is_superuser = True
view(request, server.id)
server.refresh_from_db()
self.remote_user.refresh_from_db()
self.assertEqual(server.status, "blocked")
# and the user was deactivated
self.assertFalse(self.remote_user.is_active)
def test_server_page_unblock(self):
""" unblock a server """
server = models.FederatedServer.objects.create(
server_name="hi.there.com", status="blocked"
)
self.remote_user.federated_server = server
self.remote_user.is_active = False
self.remote_user.deactivation_reason = "domain_block"
self.remote_user.save()
request = self.factory.post("")
request.user = self.local_user
request.user.is_superuser = True
views.federation.unblock_server(request, server.id)
server.refresh_from_db()
self.remote_user.refresh_from_db()
self.assertEqual(server.status, "federated")
# and the user was re-activated
self.assertTrue(self.remote_user.is_active)
def test_add_view_get(self):
""" there are so many views, this just makes sure it LOADS """
# create mode
view = views.AddFederatedServer.as_view()
request = self.factory.get("")
request.user = self.local_user
request.user.is_superuser = True
result = view(request)
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
def test_add_view_post_create(self):
""" create a server entry """
form = forms.ServerForm()
form.data["server_name"] = "remote.server"
form.data["application_type"] = "coolsoft"
form.data["status"] = "blocked"
view = views.AddFederatedServer.as_view()
request = self.factory.post("", form.data)
request.user = self.local_user
request.user.is_superuser = True
view(request)
server = models.FederatedServer.objects.get()
self.assertEqual(server.server_name, "remote.server")
self.assertEqual(server.application_type, "coolsoft")
self.assertEqual(server.status, "blocked")
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")
self.remote_user.federated_server = server
self.remote_user.save()
data = [
{"instance": "server.name", "url": "https://explanation.url"}, # new server
{"instance": "hi.there.com", "url": "https://explanation.url"}, # existing
{"a": "b"}, # invalid
]
json.dump(data, open("file.json", "w"))
view = views.ImportServerBlocklist.as_view()
request = self.factory.post(
"",
{
"json_file": SimpleUploadedFile(
"file.json", open("file.json", "rb").read()
)
},
)
request.user = self.local_user
request.user.is_superuser = True
view(request)
server.refresh_from_db()
self.remote_user.refresh_from_db()
self.assertEqual(models.FederatedServer.objects.count(), 2)
self.assertEqual(server.status, "blocked")
self.assertFalse(self.remote_user.is_active)
created = models.FederatedServer.objects.get(server_name="server.name")
self.assertEqual(created.status, "blocked")
self.assertEqual(created.notes, "https://explanation.url")

View file

@ -146,6 +146,15 @@ class ViewsHelpers(TestCase):
self.assertIsInstance(result, models.User)
self.assertEqual(result.username, "mouse@example.com")
def test_user_on_blocked_server(self, _):
""" find a remote user using webfinger """
models.FederatedServer.objects.create(
server_name="example.com", status="blocked"
)
result = views.helpers.handle_remote_webfinger("@mouse@example.com")
self.assertIsNone(result)
def test_handle_reading_status_to_read(self, _):
""" posts shelve activities """
shelf = self.local_user.shelf_set.get(identifier="to-read")
@ -190,66 +199,6 @@ class ViewsHelpers(TestCase):
)
self.assertFalse(models.GeneratedNote.objects.exists())
def test_object_visible_to_user(self, _):
""" does a user have permission to view an object """
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="public"
)
self.assertTrue(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Shelf.objects.create(
name="test", user=self.remote_user, privacy="unlisted"
)
self.assertTrue(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="followers"
)
self.assertFalse(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="direct"
)
self.assertFalse(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="direct"
)
obj.mention_users.add(self.local_user)
self.assertTrue(views.helpers.object_visible_to_user(self.local_user, obj))
def test_object_visible_to_user_follower(self, _):
""" what you can see if you follow a user """
self.remote_user.followers.add(self.local_user)
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="followers"
)
self.assertTrue(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="direct"
)
self.assertFalse(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="direct"
)
obj.mention_users.add(self.local_user)
self.assertTrue(views.helpers.object_visible_to_user(self.local_user, obj))
def test_object_visible_to_user_blocked(self, _):
""" you can't see it if they block you """
self.remote_user.blocks.add(self.local_user)
obj = models.Status.objects.create(
content="hi", user=self.remote_user, privacy="public"
)
self.assertFalse(views.helpers.object_visible_to_user(self.local_user, obj))
obj = models.Shelf.objects.create(
name="test", user=self.remote_user, privacy="unlisted"
)
self.assertFalse(views.helpers.object_visible_to_user(self.local_user, obj))
def test_get_annotated_users(self, _):
""" list of people you might know """
user_1 = models.User.objects.create_user(

View file

@ -39,6 +39,25 @@ class ListViews(TestCase):
remote_id="https://example.com/book/1",
parent_work=work,
)
work_two = models.Work.objects.create(title="Labori")
self.book_two = models.Edition.objects.create(
title="Example Edition 2",
remote_id="https://example.com/book/2",
parent_work=work_two,
)
work_three = models.Work.objects.create(title="Trabajar")
self.book_three = models.Edition.objects.create(
title="Example Edition 3",
remote_id="https://example.com/book/3",
parent_work=work_three,
)
work_four = models.Work.objects.create(title="Travailler")
self.book_four = models.Edition.objects.create(
title="Example Edition 4",
remote_id="https://example.com/book/4",
parent_work=work_four,
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
self.list = models.List.objects.create(
name="Test List", user=self.local_user
@ -194,6 +213,7 @@ class ListViews(TestCase):
user=self.local_user,
book=self.book,
approved=False,
order=1,
)
request = self.factory.post(
@ -208,7 +228,7 @@ class ListViews(TestCase):
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
view(request, self.list.id)
self.assertEqual(mock.call_count, 1)
self.assertEqual(mock.call_count, 2)
activity = json.loads(mock.call_args[0][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
@ -228,6 +248,7 @@ class ListViews(TestCase):
user=self.local_user,
book=self.book,
approved=False,
order=1,
)
request = self.factory.post(
@ -268,6 +289,261 @@ class ListViews(TestCase):
self.assertEqual(item.user, self.local_user)
self.assertTrue(item.approved)
def test_add_two_books(self):
"""
Putting two books on the list. The first should have an order value of
1 and the second should have an order value of 2.
"""
request_one = self.factory.post(
"",
{
"book": self.book.id,
"list": self.list.id,
},
)
request_one.user = self.local_user
request_two = self.factory.post(
"",
{
"book": self.book_two.id,
"list": self.list.id,
},
)
request_two.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.add_book(request_one)
views.list.add_book(request_two)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[1].book, self.book_two)
self.assertEqual(items[0].order, 1)
self.assertEqual(items[1].order, 2)
def test_add_three_books_and_remove_second(self):
"""
Put three books on a list and then remove the one in the middle. The
ordering of the list should adjust to not have a gap.
"""
request_one = self.factory.post(
"",
{
"book": self.book.id,
"list": self.list.id,
},
)
request_one.user = self.local_user
request_two = self.factory.post(
"",
{
"book": self.book_two.id,
"list": self.list.id,
},
)
request_two.user = self.local_user
request_three = self.factory.post(
"",
{
"book": self.book_three.id,
"list": self.list.id,
},
)
request_three.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.add_book(request_one)
views.list.add_book(request_two)
views.list.add_book(request_three)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[1].book, self.book_two)
self.assertEqual(items[2].book, self.book_three)
self.assertEqual(items[0].order, 1)
self.assertEqual(items[1].order, 2)
self.assertEqual(items[2].order, 3)
remove_request = self.factory.post("", {"item": items[1].id})
remove_request.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.remove_book(remove_request, self.list.id)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[1].book, self.book_three)
self.assertEqual(items[0].order, 1)
self.assertEqual(items[1].order, 2)
def test_adding_book_with_a_pending_book(self):
"""
When a list contains any pending books, the pending books should have
be at the end of the list by order. If a book is added while a book is
pending, its order should precede the pending books.
"""
request = self.factory.post(
"",
{
"book": self.book_three.id,
"list": self.list.id,
},
)
request.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
book=self.book,
approved=True,
order=1,
)
models.ListItem.objects.create(
book_list=self.list,
user=self.rat,
book=self.book_two,
approved=False,
order=2,
)
views.list.add_book(request)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[0].order, 1)
self.assertTrue(items[0].approved)
self.assertEqual(items[1].book, self.book_three)
self.assertEqual(items[1].order, 2)
self.assertTrue(items[1].approved)
self.assertEqual(items[2].book, self.book_two)
self.assertEqual(items[2].order, 3)
self.assertFalse(items[2].approved)
def test_approving_one_pending_book_from_multiple(self):
"""
When a list contains any pending books, the pending books should have
be at the end of the list by order. If a pending book is approved, then
its order should be at the end of the approved books and before the
remaining pending books.
"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
book=self.book,
approved=True,
order=1,
)
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
book=self.book_two,
approved=True,
order=2,
)
models.ListItem.objects.create(
book_list=self.list,
user=self.rat,
book=self.book_three,
approved=False,
order=3,
)
to_be_approved = models.ListItem.objects.create(
book_list=self.list,
user=self.rat,
book=self.book_four,
approved=False,
order=4,
)
view = views.Curate.as_view()
request = self.factory.post(
"",
{
"item": to_be_approved.id,
"approved": "true",
},
)
request.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
view(request, self.list.id)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[0].order, 1)
self.assertTrue(items[0].approved)
self.assertEqual(items[1].book, self.book_two)
self.assertEqual(items[1].order, 2)
self.assertTrue(items[1].approved)
self.assertEqual(items[2].book, self.book_four)
self.assertEqual(items[2].order, 3)
self.assertTrue(items[2].approved)
self.assertEqual(items[3].book, self.book_three)
self.assertEqual(items[3].order, 4)
self.assertFalse(items[3].approved)
def test_add_three_books_and_move_last_to_first(self):
"""
Put three books on the list and move the last book to the first
position.
"""
request_one = self.factory.post(
"",
{
"book": self.book.id,
"list": self.list.id,
},
)
request_one.user = self.local_user
request_two = self.factory.post(
"",
{
"book": self.book_two.id,
"list": self.list.id,
},
)
request_two.user = self.local_user
request_three = self.factory.post(
"",
{
"book": self.book_three.id,
"list": self.list.id,
},
)
request_three.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.add_book(request_one)
views.list.add_book(request_two)
views.list.add_book(request_three)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
self.assertEqual(items[1].book, self.book_two)
self.assertEqual(items[2].book, self.book_three)
self.assertEqual(items[0].order, 1)
self.assertEqual(items[1].order, 2)
self.assertEqual(items[2].order, 3)
set_position_request = self.factory.post("", {"position": 1})
set_position_request.user = self.local_user
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.set_book_position(set_position_request, items[2].id)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book_three)
self.assertEqual(items[1].book, self.book)
self.assertEqual(items[2].book, self.book_two)
self.assertEqual(items[0].order, 1)
self.assertEqual(items[1].order, 2)
self.assertEqual(items[2].order, 3)
def test_add_book_outsider(self):
""" put a book on a list """
self.list.curation = "open"
@ -358,6 +634,7 @@ class ListViews(TestCase):
book_list=self.list,
user=self.local_user,
book=self.book,
order=1,
)
self.assertTrue(self.list.listitem_set.exists())
@ -369,16 +646,15 @@ class ListViews(TestCase):
)
request.user = self.local_user
views.list.remove_book(request, self.list.id)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.list.remove_book(request, self.list.id)
self.assertFalse(self.list.listitem_set.exists())
def test_remove_book_unauthorized(self):
""" take an item off a list """
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
item = models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
book=self.book,
book_list=self.list, user=self.local_user, book=self.book, order=1
)
self.assertTrue(self.list.listitem_set.exists())
request = self.factory.post(

View file

@ -1,5 +1,4 @@
""" test for app action functionality """
from unittest.mock import patch
from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
@ -115,22 +114,19 @@ class ReportViews(TestCase):
report.refresh_from_db()
self.assertFalse(report.resolved)
def test_deactivate_user(self):
def test_suspend_user(self):
""" toggle whether a user is able to log in """
self.assertTrue(self.rat.is_active)
report = models.Report.objects.create(reporter=self.local_user, user=self.rat)
request = self.factory.post("")
request.user = self.local_user
request.user.is_superuser = True
# de-activate
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.deactivate_user(request, report.id)
views.suspend_user(request, self.rat.id)
self.rat.refresh_from_db()
self.assertFalse(self.rat.is_active)
# re-activate
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
views.deactivate_user(request, report.id)
views.suspend_user(request, self.rat.id)
self.rat.refresh_from_db()
self.assertTrue(self.rat.is_active)

View file

@ -30,6 +30,14 @@ class UserViews(TestCase):
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")
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
models.ShelfBook.objects.create(
book=self.book,
user=self.local_user,
shelf=self.local_user.shelf_set.first(),
)
models.SiteSettings.objects.create()
self.anonymous_user = AnonymousUser
self.anonymous_user.is_authenticated = False

View file

@ -1,4 +1,6 @@
""" test for app action functionality """
from unittest.mock import patch
from django.contrib.auth.models import Group
from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
@ -21,9 +23,9 @@ class UserAdminViews(TestCase):
)
models.SiteSettings.objects.create()
def test_user_admin_page(self):
def test_user_admin_list_page(self):
""" there are so many views, this just makes sure it LOADS """
view = views.UserAdmin.as_view()
view = views.UserAdminList.as_view()
request = self.factory.get("")
request.user = self.local_user
request.user.is_superuser = True
@ -31,3 +33,38 @@ class UserAdminViews(TestCase):
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
def test_user_admin_page(self):
""" there are so many views, this just makes sure it LOADS """
view = views.UserAdmin.as_view()
request = self.factory.get("")
request.user = self.local_user
request.user.is_superuser = True
result = view(request, self.local_user.id)
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(result.status_code, 200)
def test_user_admin_page_post(self):
""" set the user's group """
group = Group.objects.create(name="editor")
self.assertEqual(
list(self.local_user.groups.values_list("name", flat=True)), []
)
view = views.UserAdmin.as_view()
request = self.factory.post("", {"groups": [group.id]})
request.user = self.local_user
request.user.is_superuser = True
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
result = view(request, self.local_user.id)
self.assertIsInstance(result, TemplateResponse)
result.render()
self.assertEqual(
list(self.local_user.groups.values_list("name", flat=True)), ["editor"]
)