diff --git a/bookwyrm/templates/snippets/remove_from_group_button.html b/bookwyrm/templates/snippets/remove_from_group_button.html
index 1672e0388..2e08760f3 100644
--- a/bookwyrm/templates/snippets/remove_from_group_button.html
+++ b/bookwyrm/templates/snippets/remove_from_group_button.html
@@ -1,5 +1,6 @@
{% load i18n %}
-{% load bookwyrm_group_tags %}
+{% load group_tags %}
+
{% if request.user == user or not request.user == group.user or not request.user.is_authenticated %}
{% else %}
{% if user in request.user.blocks.all %}
diff --git a/bookwyrm/templates/snippets/shelf_selector.html b/bookwyrm/templates/snippets/shelf_selector.html
index 323e04a27..ea6096668 100644
--- a/bookwyrm/templates/snippets/shelf_selector.html
+++ b/bookwyrm/templates/snippets/shelf_selector.html
@@ -1,7 +1,7 @@
{% extends 'components/dropdown.html' %}
-{% load i18n %}
-{% load bookwyrm_tags %}
+{% load shelf_tags %}
{% load utilities %}
+{% load i18n %}
{% block dropdown-trigger %}
diff --git a/bookwyrm/templates/snippets/shelve_button/shelve_button.html b/bookwyrm/templates/snippets/shelve_button/shelve_button.html
index 37c57fc23..04dc4e4b0 100644
--- a/bookwyrm/templates/snippets/shelve_button/shelve_button.html
+++ b/bookwyrm/templates/snippets/shelve_button/shelve_button.html
@@ -1,5 +1,5 @@
-{% load bookwyrm_tags %}
{% load utilities %}
+{% load shelf_tags %}
{% if request.user.is_authenticated %}
diff --git a/bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html b/bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html
index 15e2bb519..5a29f9ad7 100644
--- a/bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html
+++ b/bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html
@@ -1,5 +1,5 @@
-{% load bookwyrm_tags %}
{% load utilities %}
+{% load shelf_tags %}
{% load i18n %}
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
diff --git a/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html b/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html
index d6ca99337..04f4bdc26 100644
--- a/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html
+++ b/bookwyrm/templates/snippets/shelve_button/shelve_button_options.html
@@ -1,5 +1,5 @@
-{% load bookwyrm_tags %}
{% load utilities %}
+{% load shelf_tags %}
{% load i18n %}
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html
index 01734cc78..fed325841 100644
--- a/bookwyrm/templates/snippets/status/content_status.html
+++ b/bookwyrm/templates/snippets/status/content_status.html
@@ -1,4 +1,5 @@
-{% load bookwyrm_tags %}
+{% load book_display_tags %}
+{% load rating_tags %}
{% load markdown %}
{% load i18n %}
{% load static %}
diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html
index 1234ae7ce..f91751445 100644
--- a/bookwyrm/templates/snippets/status/generated_status.html
+++ b/bookwyrm/templates/snippets/status/generated_status.html
@@ -1,6 +1,6 @@
{% spaceless %}
-{% load bookwyrm_tags %}
+{% load book_display_tags %}
{% load markdown %}
{% load i18n %}
{% load cache %}
diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html
index 03e3dfce8..65b6a9ac9 100755
--- a/bookwyrm/templates/user/layout.html
+++ b/bookwyrm/templates/user/layout.html
@@ -4,7 +4,7 @@
{% load utilities %}
{% load markdown %}
{% load layout %}
-{% load bookwyrm_group_tags %}
+{% load group_tags %}
{% block title %}{{ user.display_name }}{% endblock %}
diff --git a/bookwyrm/templates/user/user_preview.html b/bookwyrm/templates/user/user_preview.html
index c46563e59..23dd3ab55 100755
--- a/bookwyrm/templates/user/user_preview.html
+++ b/bookwyrm/templates/user/user_preview.html
@@ -1,7 +1,7 @@
{% load i18n %}
{% load humanize %}
{% load utilities %}
-{% load bookwyrm_tags %}
+{% load user_page_tags %}
diff --git a/bookwyrm/templatetags/book_display_tags.py b/bookwyrm/templatetags/book_display_tags.py
new file mode 100644
index 000000000..9db79f8e4
--- /dev/null
+++ b/bookwyrm/templatetags/book_display_tags.py
@@ -0,0 +1,17 @@
+""" template filters """
+from django import template
+
+
+register = template.Library()
+
+
+@register.filter(name="book_description")
+def get_book_description(book):
+ """use the work's text if the book doesn't have it"""
+ return book.description or book.parent_work.description
+
+
+@register.simple_tag(takes_context=False)
+def get_book_file_links(book):
+ """links for a book"""
+ return book.file_links.filter(domain__status="approved")
diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py
deleted file mode 100644
index 4eff0d826..000000000
--- a/bookwyrm/templatetags/bookwyrm_tags.py
+++ /dev/null
@@ -1,226 +0,0 @@
-""" template filters """
-from django import template
-from django.db.models import Avg, StdDev, Count, F, Q
-
-from bookwyrm import models
-from bookwyrm.utils import cache
-from bookwyrm.views.feed import get_suggested_books
-
-
-register = template.Library()
-
-
-@register.filter(name="rating")
-def get_rating(book, user):
- """get the overall rating of a book"""
- return cache.get_or_set(
- f"book-rating-{book.parent_work.id}-{user.id}",
- lambda u, b: models.Review.privacy_filter(u)
- .filter(book__parent_work__editions=b)
- .aggregate(Avg("rating"))["rating__avg"]
- or 0,
- user,
- book,
- timeout=15552000,
- )
-
-
-@register.filter(name="user_rating")
-def get_user_rating(book, user):
- """get a user's rating of a book"""
- rating = (
- models.Review.objects.filter(
- user=user,
- book=book,
- rating__isnull=False,
- deleted=False,
- )
- .order_by("-published_date")
- .first()
- )
- if rating:
- return rating.rating
- return 0
-
-
-@register.filter(name="is_book_on_shelf")
-def get_is_book_on_shelf(book, shelf):
- """is a book on a shelf"""
- return cache.get_or_set(
- f"book-on-shelf-{book.id}-{shelf.id}",
- lambda b, s: s.books.filter(id=b.id).exists(),
- book,
- shelf,
- timeout=15552000,
- )
-
-
-@register.filter(name="book_description")
-def get_book_description(book):
- """use the work's text if the book doesn't have it"""
- return book.description or book.parent_work.description
-
-
-@register.filter(name="next_shelf")
-def get_next_shelf(current_shelf):
- """shelf you'd use to update reading progress"""
- if current_shelf == "to-read":
- return "reading"
- if current_shelf == "reading":
- return "read"
- if current_shelf == "read":
- return "complete"
- return "to-read"
-
-
-@register.filter(name="load_subclass")
-def load_subclass(status):
- """sometimes you didn't select_subclass"""
- if hasattr(status, "quotation"):
- return status.quotation
- if hasattr(status, "review"):
- return status.review
- if hasattr(status, "comment"):
- return status.comment
- if hasattr(status, "generatednote"):
- return status.generatednote
- return status
-
-
-@register.simple_tag(takes_context=False)
-def get_book_superlatives():
- """get book stats for the about page"""
- total_ratings = models.Review.objects.filter(local=True, deleted=False).count()
- data = {}
- data["top_rated"] = (
- models.Work.objects.annotate(
- rating=Avg(
- "editions__review__rating",
- filter=Q(editions__review__local=True, editions__review__deleted=False),
- ),
- rating_count=Count(
- "editions__review",
- filter=Q(editions__review__local=True, editions__review__deleted=False),
- ),
- )
- .annotate(weighted=F("rating") * F("rating_count") / total_ratings)
- .filter(rating__gt=4, weighted__gt=0)
- .order_by("-weighted")
- .first()
- )
-
- data["controversial"] = (
- models.Work.objects.annotate(
- deviation=StdDev(
- "editions__review__rating",
- filter=Q(editions__review__local=True, editions__review__deleted=False),
- ),
- rating_count=Count(
- "editions__review",
- filter=Q(editions__review__local=True, editions__review__deleted=False),
- ),
- )
- .annotate(weighted=F("deviation") * F("rating_count") / total_ratings)
- .filter(weighted__gt=0)
- .order_by("-weighted")
- .first()
- )
-
- data["wanted"] = (
- models.Work.objects.annotate(
- shelf_count=Count(
- "editions__shelves", filter=Q(editions__shelves__identifier="to-read")
- )
- )
- .order_by("-shelf_count")
- .first()
- )
- return data
-
-
-@register.simple_tag(takes_context=False)
-def related_status(notification):
- """for notifications"""
- if not notification.related_status:
- return None
- return load_subclass(notification.related_status)
-
-
-@register.simple_tag(takes_context=True)
-def active_shelf(context, book):
- """check what shelf a user has a book on, if any"""
- user = context["request"].user
- return (
- cache.get_or_set(
- f"active_shelf-{user.id}-{book.id}",
- lambda u, b: (
- models.ShelfBook.objects.filter(
- shelf__user=u,
- book__parent_work__editions=b,
- ).first()
- or False
- ),
- user,
- book,
- timeout=15552000,
- )
- or {"book": book}
- )
-
-
-@register.simple_tag(takes_context=False)
-def latest_read_through(book, user):
- """the most recent read activity"""
- return cache.get_or_set(
- f"latest_read_through-{user.id}-{book.id}",
- lambda u, b: (
- models.ReadThrough.objects.filter(user=u, book=b, is_active=True)
- .order_by("-start_date")
- .first()
- or False
- ),
- user,
- book,
- timeout=15552000,
- )
-
-
-@register.simple_tag(takes_context=False)
-def get_landing_books():
- """list of books for the landing page"""
- return list(
- set(
- models.Edition.objects.filter(
- review__published_date__isnull=False,
- review__deleted=False,
- review__user__local=True,
- review__privacy__in=["public", "unlisted"],
- )
- .exclude(cover__exact="")
- .distinct()
- .order_by("-review__published_date")[:6]
- )
- )
-
-
-@register.simple_tag(takes_context=True)
-def mutuals_count(context, user):
- """how many users that you follow, follow them"""
- viewer = context["request"].user
- if not viewer.is_authenticated:
- return None
- return user.followers.filter(followers=viewer).count()
-
-
-@register.simple_tag(takes_context=True)
-def suggested_books(context):
- """get books for suggested books panel"""
- # this happens here instead of in the view so that the template snippet can
- # be cached in the template
- return get_suggested_books(context["request"].user)
-
-
-@register.simple_tag(takes_context=False)
-def get_book_file_links(book):
- """links for a book"""
- return book.file_links.filter(domain__status="approved")
diff --git a/bookwyrm/templatetags/feed_page_tags.py b/bookwyrm/templatetags/feed_page_tags.py
new file mode 100644
index 000000000..3d346b9a2
--- /dev/null
+++ b/bookwyrm/templatetags/feed_page_tags.py
@@ -0,0 +1,28 @@
+""" tags used on the feed pages """
+from django import template
+from bookwyrm.views.feed import get_suggested_books
+
+
+register = template.Library()
+
+
+@register.filter(name="load_subclass")
+def load_subclass(status):
+ """sometimes you didn't select_subclass"""
+ if hasattr(status, "quotation"):
+ return status.quotation
+ if hasattr(status, "review"):
+ return status.review
+ if hasattr(status, "comment"):
+ return status.comment
+ if hasattr(status, "generatednote"):
+ return status.generatednote
+ return status
+
+
+@register.simple_tag(takes_context=True)
+def suggested_books(context):
+ """get books for suggested books panel"""
+ # this happens here instead of in the view so that the template snippet can
+ # be cached in the template
+ return get_suggested_books(context["request"].user)
diff --git a/bookwyrm/templatetags/bookwyrm_group_tags.py b/bookwyrm/templatetags/group_tags.py
similarity index 100%
rename from bookwyrm/templatetags/bookwyrm_group_tags.py
rename to bookwyrm/templatetags/group_tags.py
diff --git a/bookwyrm/templatetags/landing_page_tags.py b/bookwyrm/templatetags/landing_page_tags.py
new file mode 100644
index 000000000..e7d943603
--- /dev/null
+++ b/bookwyrm/templatetags/landing_page_tags.py
@@ -0,0 +1,76 @@
+""" template filters """
+from django import template
+from django.db.models import Avg, StdDev, Count, F, Q
+
+from bookwyrm import models
+
+register = template.Library()
+
+
+@register.simple_tag(takes_context=False)
+def get_book_superlatives():
+ """get book stats for the about page"""
+ total_ratings = models.Review.objects.filter(local=True, deleted=False).count()
+ data = {}
+ data["top_rated"] = (
+ models.Work.objects.annotate(
+ rating=Avg(
+ "editions__review__rating",
+ filter=Q(editions__review__local=True, editions__review__deleted=False),
+ ),
+ rating_count=Count(
+ "editions__review",
+ filter=Q(editions__review__local=True, editions__review__deleted=False),
+ ),
+ )
+ .annotate(weighted=F("rating") * F("rating_count") / total_ratings)
+ .filter(rating__gt=4, weighted__gt=0)
+ .order_by("-weighted")
+ .first()
+ )
+
+ data["controversial"] = (
+ models.Work.objects.annotate(
+ deviation=StdDev(
+ "editions__review__rating",
+ filter=Q(editions__review__local=True, editions__review__deleted=False),
+ ),
+ rating_count=Count(
+ "editions__review",
+ filter=Q(editions__review__local=True, editions__review__deleted=False),
+ ),
+ )
+ .annotate(weighted=F("deviation") * F("rating_count") / total_ratings)
+ .filter(weighted__gt=0)
+ .order_by("-weighted")
+ .first()
+ )
+
+ data["wanted"] = (
+ models.Work.objects.annotate(
+ shelf_count=Count(
+ "editions__shelves", filter=Q(editions__shelves__identifier="to-read")
+ )
+ )
+ .order_by("-shelf_count")
+ .first()
+ )
+ return data
+
+
+@register.simple_tag(takes_context=False)
+def get_landing_books():
+ """list of books for the landing page"""
+ return list(
+ set(
+ models.Edition.objects.filter(
+ review__published_date__isnull=False,
+ review__deleted=False,
+ review__user__local=True,
+ review__privacy__in=["public", "unlisted"],
+ )
+ .exclude(cover__exact="")
+ .distinct()
+ .order_by("-review__published_date")[:6]
+ )
+ )
diff --git a/bookwyrm/templatetags/notification_page_tags.py b/bookwyrm/templatetags/notification_page_tags.py
new file mode 100644
index 000000000..28fa2afb5
--- /dev/null
+++ b/bookwyrm/templatetags/notification_page_tags.py
@@ -0,0 +1,14 @@
+""" tags used on the feed pages """
+from django import template
+from bookwyrm.templatetags.feed_page_tags import load_subclass
+
+
+register = template.Library()
+
+
+@register.simple_tag(takes_context=False)
+def related_status(notification):
+ """for notifications"""
+ if not notification.related_status:
+ return None
+ return load_subclass(notification.related_status)
diff --git a/bookwyrm/templatetags/rating_tags.py b/bookwyrm/templatetags/rating_tags.py
new file mode 100644
index 000000000..670599e25
--- /dev/null
+++ b/bookwyrm/templatetags/rating_tags.py
@@ -0,0 +1,42 @@
+""" template filters """
+from django import template
+from django.db.models import Avg
+
+from bookwyrm import models
+from bookwyrm.utils import cache
+
+
+register = template.Library()
+
+
+@register.filter(name="rating")
+def get_rating(book, user):
+ """get the overall rating of a book"""
+ return cache.get_or_set(
+ f"book-rating-{book.parent_work.id}-{user.id}",
+ lambda u, b: models.Review.privacy_filter(u)
+ .filter(book__parent_work__editions=b, rating__gt=0)
+ .aggregate(Avg("rating"))["rating__avg"]
+ or 0,
+ user,
+ book,
+ timeout=15552000,
+ )
+
+
+@register.filter(name="user_rating")
+def get_user_rating(book, user):
+ """get a user's rating of a book"""
+ rating = (
+ models.Review.objects.filter(
+ user=user,
+ book=book,
+ rating__isnull=False,
+ deleted=False,
+ )
+ .order_by("-published_date")
+ .first()
+ )
+ if rating:
+ return rating.rating
+ return 0
diff --git a/bookwyrm/templatetags/shelf_tags.py b/bookwyrm/templatetags/shelf_tags.py
new file mode 100644
index 000000000..7aef638f4
--- /dev/null
+++ b/bookwyrm/templatetags/shelf_tags.py
@@ -0,0 +1,71 @@
+""" Filters and tags related to shelving books """
+from django import template
+
+from bookwyrm import models
+from bookwyrm.utils import cache
+
+
+register = template.Library()
+
+
+@register.filter(name="is_book_on_shelf")
+def get_is_book_on_shelf(book, shelf):
+ """is a book on a shelf"""
+ return cache.get_or_set(
+ f"book-on-shelf-{book.id}-{shelf.id}",
+ lambda b, s: s.books.filter(id=b.id).exists(),
+ book,
+ shelf,
+ timeout=15552000,
+ )
+
+
+@register.filter(name="next_shelf")
+def get_next_shelf(current_shelf):
+ """shelf you'd use to update reading progress"""
+ if current_shelf == "to-read":
+ return "reading"
+ if current_shelf == "reading":
+ return "read"
+ if current_shelf == "read":
+ return "complete"
+ return "to-read"
+
+
+@register.simple_tag(takes_context=True)
+def active_shelf(context, book):
+ """check what shelf a user has a book on, if any"""
+ user = context["request"].user
+ return (
+ cache.get_or_set(
+ f"active_shelf-{user.id}-{book.id}",
+ lambda u, b: (
+ models.ShelfBook.objects.filter(
+ shelf__user=u,
+ book__parent_work__editions=b,
+ ).first()
+ or False
+ ),
+ user,
+ book,
+ timeout=15552000,
+ )
+ or {"book": book}
+ )
+
+
+@register.simple_tag(takes_context=False)
+def latest_read_through(book, user):
+ """the most recent read activity"""
+ return cache.get_or_set(
+ f"latest_read_through-{user.id}-{book.id}",
+ lambda u, b: (
+ models.ReadThrough.objects.filter(user=u, book=b, is_active=True)
+ .order_by("-start_date")
+ .first()
+ or False
+ ),
+ user,
+ book,
+ timeout=15552000,
+ )
diff --git a/bookwyrm/templatetags/user_page_tags.py b/bookwyrm/templatetags/user_page_tags.py
new file mode 100644
index 000000000..b3a82597e
--- /dev/null
+++ b/bookwyrm/templatetags/user_page_tags.py
@@ -0,0 +1,14 @@
+""" template filters """
+from django import template
+
+
+register = template.Library()
+
+
+@register.simple_tag(takes_context=True)
+def mutuals_count(context, user):
+ """how many users that you follow, follow them"""
+ viewer = context["request"].user
+ if not viewer.is_authenticated:
+ return None
+ return user.followers.filter(followers=viewer).count()
diff --git a/bookwyrm/tests/templatetags/test_book_display_tags.py b/bookwyrm/tests/templatetags/test_book_display_tags.py
new file mode 100644
index 000000000..54ae8806b
--- /dev/null
+++ b/bookwyrm/tests/templatetags/test_book_display_tags.py
@@ -0,0 +1,62 @@
+""" style fixes and lookups for templates """
+from unittest.mock import patch
+
+from django.test import TestCase
+
+from bookwyrm import models
+from bookwyrm.templatetags import book_display_tags
+
+
+@patch("bookwyrm.activitystreams.add_status_task.delay")
+@patch("bookwyrm.activitystreams.remove_status_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+class BookDisplayTags(TestCase):
+ """lotta different things here"""
+
+ def setUp(self):
+ """create some filler objects"""
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.user = models.User.objects.create_user(
+ "mouse@example.com",
+ "mouse@mouse.mouse",
+ "mouseword",
+ local=True,
+ localname="mouse",
+ )
+ self.book = models.Edition.objects.create(title="Test Book")
+
+ def test_get_book_description(self, *_):
+ """grab it from the edition or the parent"""
+ work = models.Work.objects.create(title="Test Work")
+ self.book.parent_work = work
+ self.book.save()
+
+ self.assertIsNone(book_display_tags.get_book_description(self.book))
+
+ work.description = "hi"
+ work.save()
+ self.assertEqual(book_display_tags.get_book_description(self.book), "hi")
+
+ self.book.description = "hello"
+ self.book.save()
+ self.assertEqual(book_display_tags.get_book_description(self.book), "hello")
+
+ def test_get_book_file_links(self, *_):
+ """load approved links"""
+ link = models.FileLink.objects.create(
+ book=self.book,
+ url="https://web.site/hello",
+ )
+ links = book_display_tags.get_book_file_links(self.book)
+ # the link is pending
+ self.assertFalse(links.exists())
+
+ domain = link.domain
+ domain.status = "approved"
+ domain.save()
+
+ links = book_display_tags.get_book_file_links(self.book)
+ self.assertTrue(links.exists())
+ self.assertEqual(links[0], link)
diff --git a/bookwyrm/tests/templatetags/test_bookwyrm_tags.py b/bookwyrm/tests/templatetags/test_bookwyrm_tags.py
deleted file mode 100644
index 7b8d199de..000000000
--- a/bookwyrm/tests/templatetags/test_bookwyrm_tags.py
+++ /dev/null
@@ -1,101 +0,0 @@
-""" style fixes and lookups for templates """
-from unittest.mock import patch
-
-from django.test import TestCase
-
-from bookwyrm import models
-from bookwyrm.templatetags import bookwyrm_tags
-
-
-@patch("bookwyrm.activitystreams.add_status_task.delay")
-@patch("bookwyrm.activitystreams.remove_status_task.delay")
-class BookWyrmTags(TestCase):
- """lotta different things here"""
-
- def setUp(self):
- """create some filler objects"""
- with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
- "bookwyrm.activitystreams.populate_stream_task.delay"
- ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
- self.user = models.User.objects.create_user(
- "mouse@example.com",
- "mouse@mouse.mouse",
- "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.rat",
- "ratword",
- remote_id="http://example.com/rat",
- local=False,
- )
- self.book = models.Edition.objects.create(title="Test Book")
-
- def test_get_user_rating(self, *_):
- """get a user's most recent rating of a book"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
- models.Review.objects.create(user=self.user, book=self.book, rating=3)
- self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 3)
-
- def test_get_user_rating_doesnt_exist(self, *_):
- """there is no rating available"""
- self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 0)
-
- def test_get_book_description(self, *_):
- """grab it from the edition or the parent"""
- work = models.Work.objects.create(title="Test Work")
- self.book.parent_work = work
- self.book.save()
-
- self.assertIsNone(bookwyrm_tags.get_book_description(self.book))
-
- work.description = "hi"
- work.save()
- self.assertEqual(bookwyrm_tags.get_book_description(self.book), "hi")
-
- self.book.description = "hello"
- self.book.save()
- self.assertEqual(bookwyrm_tags.get_book_description(self.book), "hello")
-
- def test_get_next_shelf(self, *_):
- """self progress helper"""
- self.assertEqual(bookwyrm_tags.get_next_shelf("to-read"), "reading")
- self.assertEqual(bookwyrm_tags.get_next_shelf("reading"), "read")
- self.assertEqual(bookwyrm_tags.get_next_shelf("read"), "complete")
- self.assertEqual(bookwyrm_tags.get_next_shelf("blooooga"), "to-read")
-
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
- def test_load_subclass(self, *_):
- """get a status' real type"""
- review = models.Review.objects.create(user=self.user, book=self.book, rating=3)
- status = models.Status.objects.get(id=review.id)
- self.assertIsInstance(status, models.Status)
- self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Review)
-
- quote = models.Quotation.objects.create(
- user=self.user, book=self.book, content="hi"
- )
- status = models.Status.objects.get(id=quote.id)
- self.assertIsInstance(status, models.Status)
- self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Quotation)
-
- comment = models.Comment.objects.create(
- user=self.user, book=self.book, content="hi"
- )
- status = models.Status.objects.get(id=comment.id)
- self.assertIsInstance(status, models.Status)
- self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Comment)
-
- def test_related_status(self, *_):
- """gets the subclass model for a notification status"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
- status = models.Status.objects.create(content="hi", user=self.user)
- notification = models.Notification.objects.create(
- user=self.user, notification_type="MENTION", related_status=status
- )
-
- result = bookwyrm_tags.related_status(notification)
- self.assertIsInstance(result, models.Status)
diff --git a/bookwyrm/tests/templatetags/test_feed_page_tags.py b/bookwyrm/tests/templatetags/test_feed_page_tags.py
new file mode 100644
index 000000000..5e5dc2357
--- /dev/null
+++ b/bookwyrm/tests/templatetags/test_feed_page_tags.py
@@ -0,0 +1,49 @@
+""" style fixes and lookups for templates """
+from unittest.mock import patch
+
+from django.test import TestCase
+
+from bookwyrm import models
+from bookwyrm.templatetags import feed_page_tags
+
+
+@patch("bookwyrm.activitystreams.add_status_task.delay")
+@patch("bookwyrm.activitystreams.remove_status_task.delay")
+class FeedPageTags(TestCase):
+ """lotta different things here"""
+
+ def setUp(self):
+ """create some filler objects"""
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.user = models.User.objects.create_user(
+ "mouse@example.com",
+ "mouse@mouse.mouse",
+ "mouseword",
+ local=True,
+ localname="mouse",
+ )
+ self.book = models.Edition.objects.create(title="Test Book")
+
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+ def test_load_subclass(self, *_):
+ """get a status' real type"""
+ review = models.Review.objects.create(user=self.user, book=self.book, rating=3)
+ status = models.Status.objects.get(id=review.id)
+ self.assertIsInstance(status, models.Status)
+ self.assertIsInstance(feed_page_tags.load_subclass(status), models.Review)
+
+ quote = models.Quotation.objects.create(
+ user=self.user, book=self.book, content="hi"
+ )
+ status = models.Status.objects.get(id=quote.id)
+ self.assertIsInstance(status, models.Status)
+ self.assertIsInstance(feed_page_tags.load_subclass(status), models.Quotation)
+
+ comment = models.Comment.objects.create(
+ user=self.user, book=self.book, content="hi"
+ )
+ status = models.Status.objects.get(id=comment.id)
+ self.assertIsInstance(status, models.Status)
+ self.assertIsInstance(feed_page_tags.load_subclass(status), models.Comment)
diff --git a/bookwyrm/tests/templatetags/test_notification_page_tags.py b/bookwyrm/tests/templatetags/test_notification_page_tags.py
new file mode 100644
index 000000000..3c92181b2
--- /dev/null
+++ b/bookwyrm/tests/templatetags/test_notification_page_tags.py
@@ -0,0 +1,37 @@
+""" style fixes and lookups for templates """
+from unittest.mock import patch
+
+from django.test import TestCase
+
+from bookwyrm import models
+from bookwyrm.templatetags import notification_page_tags
+
+
+@patch("bookwyrm.activitystreams.add_status_task.delay")
+@patch("bookwyrm.activitystreams.remove_status_task.delay")
+class NotificationPageTags(TestCase):
+ """lotta different things here"""
+
+ def setUp(self):
+ """create some filler objects"""
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.user = models.User.objects.create_user(
+ "mouse@example.com",
+ "mouse@mouse.mouse",
+ "mouseword",
+ local=True,
+ localname="mouse",
+ )
+
+ def test_related_status(self, *_):
+ """gets the subclass model for a notification status"""
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ status = models.Status.objects.create(content="hi", user=self.user)
+ notification = models.Notification.objects.create(
+ user=self.user, notification_type="MENTION", related_status=status
+ )
+
+ result = notification_page_tags.related_status(notification)
+ self.assertIsInstance(result, models.Status)
diff --git a/bookwyrm/tests/templatetags/test_rating_tags.py b/bookwyrm/tests/templatetags/test_rating_tags.py
new file mode 100644
index 000000000..c00f20726
--- /dev/null
+++ b/bookwyrm/tests/templatetags/test_rating_tags.py
@@ -0,0 +1,80 @@
+""" Gettings book ratings """
+from unittest.mock import patch
+
+from django.test import TestCase
+
+from bookwyrm import models
+from bookwyrm.templatetags import rating_tags
+
+
+@patch("bookwyrm.activitystreams.add_status_task.delay")
+@patch("bookwyrm.activitystreams.remove_status_task.delay")
+class RatingTags(TestCase):
+ """lotta different things here"""
+
+ def setUp(self):
+ """create some filler objects"""
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.local_user = models.User.objects.create_user(
+ "mouse@example.com",
+ "mouse@mouse.mouse",
+ "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.rat",
+ "ratword",
+ remote_id="http://example.com/rat",
+ local=False,
+ )
+ work = models.Work.objects.create(title="Work title")
+ self.book = models.Edition.objects.create(
+ title="Test Book",
+ parent_work=work,
+ )
+
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+ def test_get_rating(self, *_):
+ """privacy filtered rating"""
+ # follows-only: not included
+ models.ReviewRating.objects.create(
+ user=self.remote_user,
+ rating=5,
+ book=self.book,
+ privacy="followers",
+ )
+ self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 0)
+
+ # public: included
+ models.ReviewRating.objects.create(
+ user=self.remote_user,
+ rating=5,
+ book=self.book,
+ privacy="public",
+ )
+ self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 5)
+
+ # rating unset: not included
+ models.Review.objects.create(
+ name="blah",
+ user=self.local_user,
+ rating=0,
+ book=self.book,
+ privacy="public",
+ )
+ self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 5)
+
+ def test_get_user_rating(self, *_):
+ """get a user's most recent rating of a book"""
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ models.Review.objects.create(user=self.local_user, book=self.book, rating=3)
+ self.assertEqual(rating_tags.get_user_rating(self.book, self.local_user), 3)
+
+ def test_get_user_rating_doesnt_exist(self, *_):
+ """there is no rating available"""
+ self.assertEqual(rating_tags.get_user_rating(self.book, self.local_user), 0)
diff --git a/bookwyrm/tests/templatetags/test_shelf_tags.py b/bookwyrm/tests/templatetags/test_shelf_tags.py
new file mode 100644
index 000000000..5a88604dd
--- /dev/null
+++ b/bookwyrm/tests/templatetags/test_shelf_tags.py
@@ -0,0 +1,70 @@
+""" style fixes and lookups for templates """
+from unittest.mock import patch
+
+from django.test import TestCase
+from django.test.client import RequestFactory
+
+from bookwyrm import models
+from bookwyrm.templatetags import shelf_tags
+
+
+@patch("bookwyrm.activitystreams.add_status_task.delay")
+@patch("bookwyrm.activitystreams.remove_status_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
+@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
+class ShelfTags(TestCase):
+ """lotta different things here"""
+
+ def setUp(self):
+ """create some filler objects"""
+ self.factory = RequestFactory()
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
+ self.local_user = models.User.objects.create_user(
+ "mouse@example.com",
+ "mouse@mouse.mouse",
+ "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.rat",
+ "ratword",
+ remote_id="http://example.com/rat",
+ local=False,
+ )
+ self.book = models.Edition.objects.create(
+ title="Test Book",
+ parent_work=models.Work.objects.create(title="Test work"),
+ )
+
+ def test_get_is_book_on_shelf(self, *_):
+ """check if a book is on a shelf"""
+ shelf = self.local_user.shelf_set.first()
+ self.assertFalse(shelf_tags.get_is_book_on_shelf(self.book, shelf))
+ models.ShelfBook.objects.create(
+ shelf=shelf, book=self.book, user=self.local_user
+ )
+ self.assertTrue(shelf_tags.get_is_book_on_shelf(self.book, shelf))
+
+ def test_get_next_shelf(self, *_):
+ """self progress helper"""
+ self.assertEqual(shelf_tags.get_next_shelf("to-read"), "reading")
+ self.assertEqual(shelf_tags.get_next_shelf("reading"), "read")
+ self.assertEqual(shelf_tags.get_next_shelf("read"), "complete")
+ self.assertEqual(shelf_tags.get_next_shelf("blooooga"), "to-read")
+
+ def test_active_shelf(self, *_):
+ """get the shelf a book is on"""
+ shelf = self.local_user.shelf_set.first()
+ request = self.factory.get("")
+ request.user = self.local_user
+ context = {"request": request}
+ self.assertIsInstance(shelf_tags.active_shelf(context, self.book), dict)
+ models.ShelfBook.objects.create(
+ shelf=shelf, book=self.book, user=self.local_user
+ )
+ self.assertEqual(shelf_tags.active_shelf(context, self.book).shelf, shelf)
diff --git a/bookwyrm/tests/templatetags/test_status_display.py b/bookwyrm/tests/templatetags/test_status_display.py
index 50c5571e2..af2fc9420 100644
--- a/bookwyrm/tests/templatetags/test_status_display.py
+++ b/bookwyrm/tests/templatetags/test_status_display.py
@@ -1,4 +1,5 @@
""" style fixes and lookups for templates """
+from datetime import datetime
from unittest.mock import patch
from django.test import TestCase
@@ -35,6 +36,12 @@ class StatusDisplayTags(TestCase):
)
self.book = models.Edition.objects.create(title="Test Book")
+ def test_get_mentions(self, *_):
+ """list of people mentioned"""
+ status = models.Status.objects.create(content="hi", user=self.remote_user)
+ result = status_display.get_mentions(status, self.user)
+ self.assertEqual(result, "@rat@example.com ")
+
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_get_replies(self, *_):
"""direct replies to a status"""
@@ -83,8 +90,16 @@ class StatusDisplayTags(TestCase):
self.assertIsInstance(boosted, models.Review)
self.assertEqual(boosted, status)
- def test_get_mentions(self, *_):
- """list of people mentioned"""
- status = models.Status.objects.create(content="hi", user=self.remote_user)
- result = status_display.get_mentions(status, self.user)
- self.assertEqual(result, "@rat@example.com ")
+ def test_get_published_date(self, *_):
+ """date formatting"""
+ date = datetime(2020, 1, 1, 0, 0, tzinfo=timezone.utc)
+ with patch("django.utils.timezone.now") as timezone_mock:
+ timezone_mock.return_value = datetime(2022, 1, 1, 0, 0, tzinfo=timezone.utc)
+ result = status_display.get_published_date(date)
+ self.assertEqual(result, "Jan. 1, 2020")
+
+ date = datetime(2022, 1, 1, 0, 0, tzinfo=timezone.utc)
+ with patch("django.utils.timezone.now") as timezone_mock:
+ timezone_mock.return_value = datetime(2022, 1, 8, 0, 0, tzinfo=timezone.utc)
+ result = status_display.get_published_date(date)
+ self.assertEqual(result, "Jan 1")
diff --git a/bookwyrm/tests/templatetags/test_utilities.py b/bookwyrm/tests/templatetags/test_utilities.py
index e41cd21ad..0136ca8cd 100644
--- a/bookwyrm/tests/templatetags/test_utilities.py
+++ b/bookwyrm/tests/templatetags/test_utilities.py
@@ -35,6 +35,15 @@ class UtilitiesTags(TestCase):
)
self.book = models.Edition.objects.create(title="Test Book")
+ def test_get_uuid(self, *_):
+ """uuid functionality"""
+ uuid = utilities.get_uuid("hi")
+ self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
+
+ def test_join(self, *_):
+ """concats things with underscores"""
+ self.assertEqual(utilities.join("hi", 5, "blah", 0.75), "hi_5_blah_0.75")
+
def test_get_user_identifer_local(self, *_):
"""fall back to the simplest uid available"""
self.assertNotEqual(self.user.username, self.user.localname)
@@ -46,11 +55,6 @@ class UtilitiesTags(TestCase):
utilities.get_user_identifier(self.remote_user), "rat@example.com"
)
- def test_get_uuid(self, *_):
- """uuid functionality"""
- uuid = utilities.get_uuid("hi")
- self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
-
def test_get_title(self, *_):
"""the title of a book"""
self.assertEqual(utilities.get_title(None), "")