Merge branch 'main' into new-languages

This commit is contained in:
Mouse Reeve 2022-01-08 16:54:31 -08:00
commit ac1787ce6b
127 changed files with 1450 additions and 354 deletions

View file

@ -1,85 +0,0 @@
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY="7(2w1sedok=aznpq)ta1mc4i%4h=xx@hxwx*o57ctsuml0x%fr"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG=true
USE_HTTPS=false
DOMAIN=your.domain.here
#EMAIL=your@email.here
# Used for deciding which editions to prefer
DEFAULT_LANGUAGE="English"
## Leave unset to allow all hosts
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
MEDIA_ROOT=images/
# Database configuration
PGPORT=5432
POSTGRES_PASSWORD=securedbypassword123
POSTGRES_USER=fedireads
POSTGRES_DB=fedireads
POSTGRES_HOST=db
# Redis activity stream manager
MAX_STREAM_LENGTH=200
REDIS_ACTIVITY_HOST=redis_activity
REDIS_ACTIVITY_PORT=6379
REDIS_ACTIVITY_PASSWORD=redispassword345
# Redis as celery broker
REDIS_BROKER_PORT=6379
REDIS_BROKER_PASSWORD=redispassword123
# Monitoring for celery
FLOWER_PORT=8888
FLOWER_USER=mouse
FLOWER_PASSWORD=changeme
# Email config
EMAIL_HOST=smtp.mailgun.org
EMAIL_PORT=587
EMAIL_HOST_USER=mail@your.domain.here
EMAIL_HOST_PASSWORD=emailpassword123
EMAIL_USE_TLS=true
EMAIL_USE_SSL=false
EMAIL_SENDER_NAME=admin
# defaults to DOMAIN
EMAIL_SENDER_DOMAIN=
# Query timeouts
SEARCH_TIMEOUT=15
QUERY_TIMEOUT=5
# Thumbnails Generation
ENABLE_THUMBNAIL_GENERATION=false
# S3 configuration
USE_S3=false
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
# Commented are example values if you use a non-AWS, S3-compatible service
# AWS S3 should work with only AWS_STORAGE_BUCKET_NAME and AWS_S3_REGION_NAME
# non-AWS S3-compatible services will need AWS_STORAGE_BUCKET_NAME,
# along with both AWS_S3_CUSTOM_DOMAIN and AWS_S3_ENDPOINT_URL
# AWS_STORAGE_BUCKET_NAME= # "example-bucket-name"
# AWS_S3_CUSTOM_DOMAIN=None # "example-bucket-name.s3.fr-par.scw.cloud"
# AWS_S3_REGION_NAME=None # "fr-par"
# AWS_S3_ENDPOINT_URL=None # "https://s3.fr-par.scw.cloud"
# Preview image generation can be computing and storage intensive
# ENABLE_PREVIEW_IMAGES=True
# Specify RGB tuple or RGB hex strings,
# or use_dominant_color_light / use_dominant_color_dark
PREVIEW_BG_COLOR=use_dominant_color_light
# Change to #FFF if you use use_dominant_color_dark
PREVIEW_TEXT_COLOR=#363636
PREVIEW_IMG_WIDTH=1200
PREVIEW_IMG_HEIGHT=630
PREVIEW_DEFAULT_COVER_COLOR=#002549

View file

@ -397,9 +397,15 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg
"""build a user's feeds when they join"""
if not created or not instance.local:
return
transaction.on_commit(
lambda: populate_streams_on_account_create_command(instance.id)
)
def populate_streams_on_account_create_command(instance_id):
"""wait for the transaction to complete"""
for stream in streams:
populate_stream_task.delay(stream, instance.id)
populate_stream_task.delay(stream, instance_id)
@receiver(signals.pre_save, sender=models.ShelfBook)

251
bookwyrm/lists_stream.py Normal file
View file

@ -0,0 +1,251 @@
""" access the list streams stored in redis """
from django.dispatch import receiver
from django.db import transaction
from django.db.models import signals, Count, Q
from bookwyrm import models
from bookwyrm.redis_store import RedisStore
from bookwyrm.tasks import app, MEDIUM, HIGH
class ListsStream(RedisStore):
"""all the lists you can see"""
def stream_id(self, user): # pylint: disable=no-self-use
"""the redis key for this user's instance of this stream"""
if isinstance(user, int):
# allows the function to take an int or an obj
return f"{user}-lists"
return f"{user.id}-lists"
def get_rank(self, obj): # pylint: disable=no-self-use
"""lists are sorted by updated date"""
return obj.updated_date.timestamp()
def add_list(self, book_list):
"""add a list to users' feeds"""
# the pipeline contains all the add-to-stream activities
self.add_object_to_related_stores(book_list)
def add_user_lists(self, viewer, user):
"""add a user's lists to another user's feed"""
# only add the lists that the viewer should be able to see
lists = models.List.privacy_filter(viewer).filter(user=user)
self.bulk_add_objects_to_store(lists, self.stream_id(viewer))
def remove_user_lists(self, viewer, user, exclude_privacy=None):
"""remove a user's list from another user's feed"""
# remove all so that followers only lists are removed
lists = user.list_set
if exclude_privacy:
lists = lists.exclude(privacy=exclude_privacy)
self.bulk_remove_objects_from_store(lists.all(), self.stream_id(viewer))
def get_list_stream(self, user):
"""load the lists to be displayed"""
lists = self.get_store(self.stream_id(user))
return (
models.List.objects.filter(id__in=lists)
.annotate(item_count=Count("listitem", filter=Q(listitem__approved=True)))
# hide lists with no approved books
.filter(item_count__gt=0)
.select_related("user")
.prefetch_related("listitem_set")
.order_by("-updated_date")
.distinct()
)
def populate_lists(self, user):
"""go from zero to a timeline"""
self.populate_store(self.stream_id(user))
def get_audience(self, book_list): # pylint: disable=no-self-use
"""given a list, what users should see it"""
# everybody who could plausibly see this list
audience = models.User.objects.filter(
is_active=True,
local=True, # we only create feeds for users of this instance
).exclude( # not blocked
Q(id__in=book_list.user.blocks.all()) | Q(blocks=book_list.user)
)
group = book_list.group
# only visible to the poster and mentioned users
if book_list.privacy == "direct":
if group:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the post's author
| ~Q(groups=group.memberships) # if the user is in the group
)
else:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the post's author
)
# only visible to the poster's followers and tagged users
elif book_list.privacy == "followers":
if group:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the list's owner
| Q(following=book_list.user) # if the user is following the pwmer
# if a user is in the group
| Q(memberships__group__id=book_list.group.id)
)
else:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the list's owner
| Q(following=book_list.user) # if the user is following the pwmer
)
return audience.distinct()
def get_stores_for_object(self, obj):
return [self.stream_id(u) for u in self.get_audience(obj)]
def get_lists_for_user(self, user): # pylint: disable=no-self-use
"""given a user, what lists should they see on this stream"""
return models.List.privacy_filter(
user,
privacy_levels=["public", "followers"],
)
def get_objects_for_store(self, store):
user = models.User.objects.get(id=store.split("-")[0])
return self.get_lists_for_user(user)
@receiver(signals.post_save, sender=models.List)
# pylint: disable=unused-argument
def add_list_on_create(sender, instance, created, *args, **kwargs):
"""add newly created lists streamsstreams"""
if not created:
return
# when creating new things, gotta wait on the transaction
transaction.on_commit(lambda: add_list_on_create_command(instance.id))
@receiver(signals.post_delete, sender=models.List)
# pylint: disable=unused-argument
def remove_list_on_delete(sender, instance, *args, **kwargs):
"""remove deleted lists to streams"""
remove_list_task.delay(instance.id)
def add_list_on_create_command(instance_id):
"""runs this code only after the database commit completes"""
add_list_task.delay(instance_id)
@receiver(signals.post_save, sender=models.UserFollows)
# pylint: disable=unused-argument
def add_lists_on_follow(sender, instance, created, *args, **kwargs):
"""add a newly followed user's lists to feeds"""
if not created or not instance.user_subject.local:
return
add_user_lists_task.delay(instance.user_subject.id, instance.user_object.id)
@receiver(signals.post_delete, sender=models.UserFollows)
# pylint: disable=unused-argument
def remove_lists_on_unfollow(sender, instance, *args, **kwargs):
"""remove lists from a feed on unfollow"""
if not instance.user_subject.local:
return
# remove all but public lists
remove_user_lists_task.delay(
instance.user_subject.id, instance.user_object.id, exclude_privacy="public"
)
@receiver(signals.post_save, sender=models.UserBlocks)
# pylint: disable=unused-argument
def remove_lists_on_block(sender, instance, *args, **kwargs):
"""remove lists from all feeds on block"""
# blocks apply ot all feeds
if instance.user_subject.local:
remove_user_lists_task.delay(instance.user_subject.id, instance.user_object.id)
# and in both directions
if instance.user_object.local:
remove_user_lists_task.delay(instance.user_object.id, instance.user_subject.id)
@receiver(signals.post_delete, sender=models.UserBlocks)
# pylint: disable=unused-argument
def add_lists_on_unblock(sender, instance, *args, **kwargs):
"""add lists back to all feeds on unblock"""
# make sure there isn't a block in the other direction
if models.UserBlocks.objects.filter(
user_subject=instance.user_object,
user_object=instance.user_subject,
).exists():
return
# add lists back to streams with lists from anyone
if instance.user_subject.local:
add_user_lists_task.delay(
instance.user_subject.id,
instance.user_object.id,
)
# add lists back to streams with lists from anyone
if instance.user_object.local:
add_user_lists_task.delay(
instance.user_object.id,
instance.user_subject.id,
)
@receiver(signals.post_save, sender=models.User)
# pylint: disable=unused-argument
def populate_lists_on_account_create(sender, instance, created, *args, **kwargs):
"""build a user's feeds when they join"""
if not created or not instance.local:
return
transaction.on_commit(lambda: add_list_on_account_create_command(instance.id))
def add_list_on_account_create_command(user_id):
"""wait for the transaction to complete"""
populate_lists_task.delay(user_id)
# ---- TASKS
@app.task(queue=MEDIUM)
def populate_lists_task(user_id):
"""background task for populating an empty list stream"""
user = models.User.objects.get(id=user_id)
ListsStream().populate_lists(user)
@app.task(queue=MEDIUM)
def remove_list_task(list_id):
"""remove a list from any stream it might be in"""
stores = models.User.objects.filter(local=True, is_active=True).values_list(
"id", flat=True
)
# delete for every store
stores = [ListsStream().stream_id(idx) for idx in stores]
ListsStream().remove_object_from_related_stores(list_id, stores=stores)
@app.task(queue=HIGH)
def add_list_task(list_id):
"""add a list to any stream it should be in"""
book_list = models.List.objects.get(id=list_id)
ListsStream().add_list(book_list)
@app.task(queue=MEDIUM)
def remove_user_lists_task(viewer_id, user_id, exclude_privacy=None):
"""remove all lists by a user from a viewer's stream"""
viewer = models.User.objects.get(id=viewer_id)
user = models.User.objects.get(id=user_id)
ListsStream().remove_user_lists(viewer, user, exclude_privacy=exclude_privacy)
@app.task(queue=MEDIUM)
def add_user_lists_task(viewer_id, user_id):
"""add all lists by a user to a viewer's stream"""
viewer = models.User.objects.get(id=viewer_id)
user = models.User.objects.get(id=user_id)
ListsStream().add_user_lists(viewer, user)

View file

@ -0,0 +1,34 @@
""" Re-create list streams """
from django.core.management.base import BaseCommand
from bookwyrm import lists_stream, models
def populate_lists_streams():
"""build all the lists streams for all the users"""
print("Populating lists streams")
users = models.User.objects.filter(
local=True,
is_active=True,
).order_by("-last_active_date")
print("This may take a long time! Please be patient.")
for user in users:
print(".", end="")
lists_stream.populate_lists_task.delay(user.id)
class Command(BaseCommand):
"""start all over with lists streams"""
help = "Populate list streams for all users"
def add_arguments(self, parser):
parser.add_argument(
"--stream",
default=None,
help="Specifies which time of stream to populate",
)
# pylint: disable=no-self-use,unused-argument
def handle(self, *args, **options):
"""run feed builder"""
populate_lists_streams()

View file

@ -1,6 +1,6 @@
""" Re-create user streams """
from django.core.management.base import BaseCommand
from bookwyrm import activitystreams, models
from bookwyrm import activitystreams, lists_stream, models
def populate_streams(stream=None):
@ -13,6 +13,8 @@ def populate_streams(stream=None):
).order_by("-last_active_date")
print("This may take a long time! Please be patient.")
for user in users:
print(".", end="")
lists_stream.populate_lists_task.delay(user.id)
for stream_key in streams:
print(".", end="")
activitystreams.populate_stream_task.delay(stream_key, user.id)

View file

@ -0,0 +1,33 @@
# Generated by Django 3.2.10 on 2022-01-06 17:59
from django.contrib.auth.models import AbstractUser
from django.db import migrations
def get_admins(apps, schema_editor):
"""add any superusers to the "admin" group"""
db_alias = schema_editor.connection.alias
groups = apps.get_model("auth", "Group")
try:
group = groups.objects.using(db_alias).get(name="admin")
except groups.DoesNotExist:
# for tests
return
users = apps.get_model("bookwyrm", "User")
admins = users.objects.using(db_alias).filter(is_superuser=True)
for admin in admins:
admin.groups.add(group)
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0123_alter_user_preferred_language"),
]
operations = [
migrations.RunPython(get_admins, reverse_code=migrations.RunPython.noop),
]

View file

@ -30,7 +30,8 @@ class RedisStore(ABC):
# add the status to the feed
pipeline.zadd(store, value)
# trim the store
pipeline.zremrangebyrank(store, 0, -1 * self.max_length)
if self.max_length:
pipeline.zremrangebyrank(store, 0, -1 * self.max_length)
if not execute:
return pipeline
# and go!
@ -38,10 +39,15 @@ class RedisStore(ABC):
def remove_object_from_related_stores(self, obj, stores=None):
"""remove an object from all stores"""
# if the stoers are provided, the object can just be an id
if stores and isinstance(obj, int):
obj_id = obj
else:
obj_id = obj.id
stores = self.get_stores_for_object(obj) if stores is None else stores
pipeline = r.pipeline()
for store in stores:
pipeline.zrem(store, -1, obj.id)
pipeline.zrem(store, -1, obj_id)
pipeline.execute()
def bulk_add_objects_to_store(self, objs, store):
@ -49,7 +55,7 @@ class RedisStore(ABC):
pipeline = r.pipeline()
for obj in objs[: self.max_length]:
pipeline.zadd(store, self.get_value(obj))
if objs:
if objs and self.max_length:
pipeline.zremrangebyrank(store, 0, -1 * self.max_length)
pipeline.execute()
@ -73,7 +79,7 @@ class RedisStore(ABC):
pipeline.zadd(store, self.get_value(obj))
# only trim the store if objects were added
if queryset.exists():
if queryset.exists() and self.max_length:
pipeline.zremrangebyrank(store, 0, -1 * self.max_length)
pipeline.execute()

View file

@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _
env = Env()
env.read_env()
DOMAIN = env("DOMAIN")
VERSION = "0.1.0"
VERSION = "0.1.1"
PAGE_LENGTH = env("PAGE_LENGTH", 15)
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")

View file

@ -2,6 +2,7 @@
import math
import logging
from django.dispatch import receiver
from django.db import transaction
from django.db.models import signals, Count, Q, Case, When, IntegerField
from bookwyrm import models
@ -192,7 +193,7 @@ def update_user(sender, instance, created, update_fields=None, **kwargs):
"""an updated user, neat"""
# a new user is found, create suggestions for them
if created and instance.local:
rerank_suggestions_task.delay(instance.id)
transaction.on_commit(lambda: update_new_user_command(instance.id))
# we know what fields were updated and discoverability didn't change
if not instance.bookwyrm_user or (
@ -212,6 +213,11 @@ def update_user(sender, instance, created, update_fields=None, **kwargs):
remove_user_task.delay(instance.id)
def update_new_user_command(instance_id):
"""wait for transaction to complete"""
rerank_suggestions_task.delay(instance_id)
@receiver(signals.post_save, sender=models.FederatedServer)
def domain_level_update(sender, instance, created, update_fields=None, **kwargs):
"""remove users on a domain block"""

View file

@ -0,0 +1,141 @@
{% extends 'about/layout.html' %}
{% load humanize %}
{% load i18n %}
{% load utilities %}
{% load bookwyrm_tags %}
{% load cache %}
{% block title %}
{% trans "About" %}
{% endblock %}
{% block about_content %}
{# seven day cache #}
{% cache 604800 about_page %}
{% get_book_superlatives as superlatives %}
<section class="content pb-4">
<h2>
{% blocktrans with site_name=site.name %}Welcome to {{ site_name }}!{% endblocktrans %}
</h2>
<p class="subtitle notification has-background-primary-light">
{% blocktrans trimmed with site_name=site.name %}
{{ site_name }} is part of <em>BookWyrm</em>, a network of independent, self-directed communities for readers.
While you can interact seemlessly with users anywhere in the <a href="https://joinbookwyrm.com/instances/" target="_blank">BookWyrm network</a>, this community is unique.
{% endblocktrans %}
</p>
<div class="columns">
{% if top_rated %}
{% with book=superlatives.top_rated.default_edition rating=top_rated.rating %}
<div class="column is-one-third is-flex">
<div class="media notification">
<div class="media-left">
<a href="{{ book.local_path }}">
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m' size='medium' aria='show' %}
</a>
</div>
<div class="media-content">
{% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name rating=rating|floatformat:1 %}
<a href="{{ book_path }}"><em>{{ title }}</em></a> is {{ site_name }}'s most beloved book, with an average rating of {{ rating }} out of 5.
{% endblocktrans %}
</div>
</div>
</div>
{% endwith %}
{% endif %}
{% if wanted %}
{% with book=superlatives.wanted.default_edition %}
<div class="column is-one-third is-flex">
<div class="media notification">
<div class="media-left">
<a href="{{ book.local_path }}">
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m' size='medium' aria='show' %}
</a>
</div>
<div class="media-content">
{% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name %}
More {{ site_name }} users want to read <a href="{{ book_path }}"><em>{{ title }}</em></a> than any other book.
{% endblocktrans %}
</div>
</div>
</div>
{% endwith %}
{% endif %}
{% if controversial %}
{% with book=superlatives.controversial.default_edition %}
<div class="column is-one-third is-flex">
<div class="media notification">
<div class="media-left">
<a href="{{ book.local_path }}">
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m' size='medium' aria='show' %}
</a>
</div>
<div class="media-content">
{% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name %}
<a href="{{ book_path }}"><em>{{ title }}</em></a> has the most divisive ratings of any book on {{ site_name }}.
{% endblocktrans %}
</div>
</div>
</div>
{% endwith %}
{% endif %}
</div>
<p>
{% trans "Track your reading, talk about books, write reviews, and discover what to read next. Always ad-free, anti-corporate, and community-oriented, BookWyrm is human-scale software, designed to stay small and personal. If you have feature requests, bug reports, or grand dreams, <a href='https://joinbookwyrm.com/get-involved' target='_blank'>reach out</a> and make yourself heard." %}
</p>
</section>
<section class="block">
<header class="content">
<h2 class="title is-3">{% trans "Meet your admins" %}</h2>
<p>
{% url "conduct" as coc_path %}
{% blocktrans with site_name=site.name %}
{{ site_name }}'s moderators and administrators keep the site up and running, enforce the <a href="coc_path">code of conduct</a>, and respond when users report spam and bad behavior.
{% endblocktrans %}
</p>
</header>
<div class="columns is-multiline">
{% for user in admins %}
<div class="column">
<div class="card is-stretchable">
{% with role=user.groups.first.name %}
<div class="card-header {% if role == "moderator" %}has-background-info-light{% else %}has-background-success-light{% endif %}">
<span class="card-header-title is-size-7 pt-1 pb-1">
{% if role == "moderator" %}
{% trans "Moderator" %}
{% else %}
{% trans "Admin" %}
{% endif %}
</span>
</div>
{% endwith %}
<div class="cord-content p-5">
{% include 'user/user_preview.html' with user=user %}
</div>
{% if request.user.is_authenticated and user.id != request.user.id %}
<div class="has-background-white-bis card-footer">
<div class="card-footer-item">
{% include 'snippets/follow_button.html' with user=user minimal=True %}
</div>
<div class="card-footer-item">
<a href="{% url 'direct-messages-user' user|username %}">{% trans "Send direct message" %}</a>
</div>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</section>
{% endcache %}
{% endblock %}

View file

@ -0,0 +1,15 @@
{% extends 'about/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Code of Conduct" %}{% endblock %}
{% block about_content %}
<div class="block content">
<h2>{% trans "Code of Conduct" %}</h2>
<div class="content">
{{ site.code_of_conduct | safe }}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,57 @@
{% extends 'landing/layout.html' %}
{% load humanize %}
{% load i18n %}
{% block about_panel %}
<div class="box">
{% include "snippets/about.html" with size="m" %}
{% if active_users %}
<ul>
<li class="tag is-size-6">
<span class="mr-1">{% trans "Active users:" %}</span>
<strong>{{ active_users|intcomma }}</strong>
</li>
<li class="tag is-size-6">
<span class="mr-1">{% trans "Statuses posted:" %}</span>
<strong>{{ status_count|intcomma }}</strong>
</li>
<li class="tag is-size-6">
<span class="mr-1">{% trans "Software version:" %}</span>
<strong>{{ version }}</strong>
</li>
</ul>
{% endif %}
</div>
{% endblock %}
{% block panel %}
<div class="block columns pt-4">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">{% blocktrans with site_name=site.name %}About {{ site_name }}{% endblocktrans %}</h2>
<ul class="menu-list">
<li>
{% url 'about' as path %}
<a href="{{ path }}" {% if request.path in path %}class="is-active"{% endif %}>
{% trans "About" %}
</a>
</li>
<li>
{% url 'conduct' as path %}
<a href="{{ path }}" {% if request.path in path %}class="is-active"{% endif %}>
{% trans "Code of Conduct" %}
</a>
</li>
<li>
{% url 'privacy' as path %}
<a href="{{ path }}" {% if request.path in path %}class="is-active"{% endif %}>
{% trans "Privacy Policy" %}
</a>
</li>
</ul>
</nav>
<div class="column">
{% block about_content %}{% endblock %}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,15 @@
{% extends 'about/layout.html' %}
{% load i18n %}
{% block title %}{% trans "Privacy Policy" %}{% endblock %}
{% block about_content %}
<div class="block">
<h2 class="title">{% trans "Privacy Policy" %}</h2>
<div class="content">
{{ site.privacy_policy | safe }}
</div>
</div>
{% endblock %}

View file

@ -1,37 +0,0 @@
{% extends 'landing/layout.html' %}
{% load i18n %}
{% block panel %}
<div class="block columns mt-4">
<nav class="menu column is-one-quarter">
<h2 class="menu-label">{% blocktrans with site_name=site.name %}About {{ site_name }}{% endblocktrans %}</h2>
<ul class="menu-list">
<li>
<a href="#coc">{% trans "Code of Conduct" %}</a>
</li>
<li>
<a href="#privacy">{% trans "Privacy Policy" %}</a>
</li>
</ul>
</nav>
<div class="column content">
<div class="block" id="coc">
<h2 class="title">{% trans "Code of Conduct" %}</h2>
<div class="content">
{{ site.code_of_conduct | safe }}
</div>
</div>
<hr aria-hidden="true">
<div class="block" id="privacy">
<h2 class="title">{% trans "Privacy Policy" %}</h2>
<div class="content">
{{ site.privacy_policy | safe }}
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -31,6 +31,7 @@
</div>
</section>
{% block about_panel %}
<section class="tile is-ancestor">
<div class="tile is-7 is-parent">
<div class="tile is-child box">
@ -89,6 +90,7 @@
{% endif %}
</div>
</section>
{% endblock %}
{% block panel %}{% endblock %}

View file

@ -2,7 +2,7 @@
<div class="columns">
<div class="column is-narrow is-hidden-mobile">
<figure class="block is-w-xl">
<figure class="block is-w-{% if size %}{{ size }}{% else %}xl{% endif %}">
<img src="{% if site.logo %}{% get_media_prefix %}{{ site.logo }}{% else %}{% static "images/logo.png" %}{% endif %}" alt="BookWyrm logo">
</figure>
</div>

View file

@ -3,6 +3,7 @@
{% load i18n %}
{% load static %}
{% load humanize %}
{% load cache %}
{% with status_type=status.status_type %}
<div
@ -15,6 +16,7 @@
<div class="columns is-gapless">
{% if not hide_book %}
{% cache 259200 content_status_book status.id %}
{% with book=status.book|default:status.mention_books.first %}
{% if book %}
<div class="column is-cover">
@ -34,6 +36,7 @@
</div>
{% endif %}
{% endwith %}
{% endcache %}
{% endif %}
<article class="column ml-3-tablet my-3-mobile">

View file

@ -3,8 +3,10 @@
{% load bookwyrm_tags %}
{% load markdown %}
{% load i18n %}
{% load cache %}
{% if not hide_book %}
{% cache 259200 generated_status_book status.id %}
{% with book=status.book|default:status.mention_books.first %}
<div class="columns is-mobile is-gapless">
<a class="column is-cover is-narrow" href="{{ book.local_path }}">
@ -24,6 +26,7 @@
</div>
</div>
{% endwith %}
{% endcache %}
{% endif %}
{% endspaceless %}

View file

@ -21,23 +21,23 @@
<p><a href="{{ user.remote_id }}">{{ user.username }}</a></p>
<p>{% blocktrans with date=user.created_date|naturaltime %}Joined {{ date }}{% endblocktrans %}</p>
<p>
{% if is_self %}
{% if request.user.id == user.id %}
<a href="{% url 'user-followers' user|username %}">{% blocktrans count counter=user.followers.count %}{{ counter }} follower{% plural %}{{ counter }} followers{% endblocktrans %}</a>,
<a href="{% url 'user-following' user|username %}">{% blocktrans with counter=user.following.count %}{{ counter }} following{% endblocktrans %}</a>
<a href="{% url 'user-followers' user|username %}">{% blocktrans count counter=user.followers.count %}{{ counter }} follower{% plural %}{{ counter }} followers{% endblocktrans %}</a>,
<a href="{% url 'user-following' user|username %}">{% blocktrans with counter=user.following.count %}{{ counter }} following{% endblocktrans %}</a>
{% elif request.user.is_authenticated %}
{% mutuals_count user as mutuals %}
<a href="{% url 'user-followers' user|username %}">
{% if mutuals %}
{% blocktrans with mutuals_display=mutuals|intcomma count counter=mutuals %}{{ mutuals_display }} follower you follow{% plural %}{{ mutuals_display }} followers you follow{% endblocktrans %}
{% elif request.user in user.following.all %}
{% trans "Follows you" %}
{% else %}
{% trans "No followers you follow" %}
{% endif %}
</a>
{% mutuals_count user as mutuals %}
<a href="{% url 'user-followers' user|username %}">
{% if mutuals %}
{% blocktrans with mutuals_display=mutuals|intcomma count counter=mutuals %}{{ mutuals_display }} follower you follow{% plural %}{{ mutuals_display }} followers you follow{% endblocktrans %}
{% elif request.user in user.following.all %}
{% trans "Follows you" %}
{% else %}
{% trans "No followers you follow" %}
{% endif %}
</a>
{% endif %}
</p>

View file

@ -1,6 +1,6 @@
""" template filters """
from django import template
from django.db.models import Avg
from django.db.models import Avg, StdDev, Count, F, Q
from bookwyrm import models
from bookwyrm.views.feed import get_suggested_books
@ -68,6 +68,57 @@ def load_subclass(status):
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"""

View file

@ -31,7 +31,7 @@ class BaseActivity(TestCase):
"""we're probably going to re-use this so why copy/paste"""
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", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)

View file

@ -16,7 +16,7 @@ class Activitystreams(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)

View file

@ -16,7 +16,7 @@ class Activitystreams(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)

View file

@ -16,7 +16,7 @@ class Activitystreams(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)

View file

@ -16,7 +16,7 @@ class Activitystreams(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)

View file

@ -5,6 +5,8 @@ from bookwyrm import activitystreams, models
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
@patch("bookwyrm.lists_stream.remove_user_lists_task.delay")
class ActivitystreamsSignals(TestCase):
"""using redis to build activity streams"""
@ -12,7 +14,7 @@ class ActivitystreamsSignals(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)
@ -32,11 +34,11 @@ class ActivitystreamsSignals(TestCase):
work = models.Work.objects.create(title="test work")
self.book = models.Edition.objects.create(title="test book", parent_work=work)
def test_add_status_on_create_ignore(self, _):
def test_add_status_on_create_ignore(self, *_):
"""a new statuses has entered"""
activitystreams.add_status_on_create(models.User, self.local_user, False)
def test_add_status_on_create_deleted(self, _):
def test_add_status_on_create_deleted(self, *_):
"""a new statuses has entered"""
with patch("bookwyrm.activitystreams.remove_status_task.delay"):
status = models.Status.objects.create(
@ -48,7 +50,7 @@ class ActivitystreamsSignals(TestCase):
args = mock.call_args[0]
self.assertEqual(args[0], status.id)
def test_add_status_on_create_created(self, _):
def test_add_status_on_create_created(self, *_):
"""a new statuses has entered"""
status = models.Status.objects.create(
user=self.remote_user, content="hi", privacy="public"
@ -60,18 +62,18 @@ class ActivitystreamsSignals(TestCase):
self.assertEqual(args["args"][0], status.id)
self.assertEqual(args["queue"], "high_priority")
def test_populate_streams_on_account_create(self, _):
def test_populate_streams_on_account_create_command(self, *_):
"""create streams for a user"""
with patch("bookwyrm.activitystreams.populate_stream_task.delay") as mock:
activitystreams.populate_streams_on_account_create(
models.User, self.local_user, True
activitystreams.populate_streams_on_account_create_command(
self.local_user.id
)
self.assertEqual(mock.call_count, 3)
args = mock.call_args[0]
self.assertEqual(args[0], "books")
self.assertEqual(args[1], self.local_user.id)
def test_remove_statuses_on_block(self, _):
def test_remove_statuses_on_block(self, *_):
"""don't show statuses from blocked users"""
with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") as mock:
models.UserBlocks.objects.create(
@ -83,7 +85,7 @@ class ActivitystreamsSignals(TestCase):
self.assertEqual(args[0], self.local_user.id)
self.assertEqual(args[1], self.remote_user.id)
def test_add_statuses_on_unblock(self, _):
def test_add_statuses_on_unblock(self, *_):
"""re-add statuses on unblock"""
with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"):
block = models.UserBlocks.objects.create(
@ -100,7 +102,7 @@ class ActivitystreamsSignals(TestCase):
self.assertEqual(args[1], self.remote_user.id)
self.assertEqual(kwargs["stream_list"], ["local", "books"])
def test_add_statuses_on_unblock_reciprocal_block(self, _):
def test_add_statuses_on_unblock_reciprocal_block(self, *_):
"""re-add statuses on unblock"""
with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"):
block = models.UserBlocks.objects.create(

View file

@ -11,7 +11,7 @@ class Activitystreams(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)

View file

@ -30,7 +30,7 @@ class GoodreadsImport(TestCase):
self.csv = open(datafile, "r", encoding=self.importer.encoding)
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", "mouse@mouse.mouse", "password", local=True
)

View file

@ -33,7 +33,7 @@ class GenericImporter(TestCase):
self.csv = open(datafile, "r", encoding=self.importer.encoding)
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", "mouse@mouse.mouse", "password", local=True
)

View file

@ -32,7 +32,7 @@ class LibrarythingImport(TestCase):
self.csv = open(datafile, "r", encoding=self.importer.encoding)
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(
"mmai", "mmai@mmai.mmai", "password", local=True
)

View file

@ -30,7 +30,7 @@ class OpenLibraryImport(TestCase):
self.csv = open(datafile, "r", encoding=self.importer.encoding)
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", "mouse@mouse.mouse", "password", local=True
)

View file

@ -30,7 +30,7 @@ class StorygraphImport(TestCase):
self.csv = open(datafile, "r", encoding=self.importer.encoding)
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", "mouse@mouse.mouse", "password", local=True
)

View file

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

View file

@ -0,0 +1,109 @@
""" testing lists_stream """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import lists_stream, models
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class ListsStreamSignals(TestCase):
"""using redis to build activity streams"""
def setUp(self):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)
self.another_user = models.User.objects.create_user(
"fish", "fish@fish.fish", "password", local=True, localname="fish"
)
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_add_list_on_create_command(self, _):
"""a new lists has entered"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
with patch("bookwyrm.lists_stream.add_list_task.delay") as mock:
lists_stream.add_list_on_create_command(book_list.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], book_list.id)
def test_remove_list_on_delete(self, _):
"""delete a list"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
with patch("bookwyrm.lists_stream.remove_list_task.delay") as mock:
lists_stream.remove_list_on_delete(models.List, book_list)
args = mock.call_args[0]
self.assertEqual(args[0], book_list.id)
def test_populate_lists_on_account_create_command(self, _):
"""create streams for a user"""
with patch("bookwyrm.lists_stream.populate_lists_task.delay") as mock:
lists_stream.add_list_on_account_create_command(self.local_user.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user.id)
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
def test_remove_lists_on_block(self, *_):
"""don't show lists from blocked users"""
with patch("bookwyrm.lists_stream.remove_user_lists_task.delay") as mock:
models.UserBlocks.objects.create(
user_subject=self.local_user,
user_object=self.remote_user,
)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user.id)
self.assertEqual(args[1], self.remote_user.id)
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
def test_add_lists_on_unblock(self, *_):
"""re-add lists on unblock"""
with patch("bookwyrm.lists_stream.remove_user_lists_task.delay"):
block = models.UserBlocks.objects.create(
user_subject=self.local_user,
user_object=self.remote_user,
)
with patch("bookwyrm.lists_stream.add_user_lists_task.delay") as mock:
block.delete()
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user.id)
self.assertEqual(args[1], self.remote_user.id)
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
def test_add_lists_on_unblock_reciprocal_block(self, *_):
"""dont' re-add lists on unblock if there's a block the other way"""
with patch("bookwyrm.lists_stream.remove_user_lists_task.delay"):
block = models.UserBlocks.objects.create(
user_subject=self.local_user,
user_object=self.remote_user,
)
block = models.UserBlocks.objects.create(
user_subject=self.remote_user,
user_object=self.local_user,
)
with patch("bookwyrm.lists_stream.add_user_lists_task.delay") as mock:
block.delete()
self.assertFalse(mock.called)

View file

@ -0,0 +1,171 @@
""" testing activitystreams """
from datetime import datetime
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import lists_stream, models
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class ListsStream(TestCase):
"""using redis to build activity streams"""
def setUp(self):
"""use a test csv"""
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", "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.stream = lists_stream.ListsStream()
def test_lists_stream_ids(self, *_):
"""the abstract base class for stream objects"""
self.assertEqual(
self.stream.stream_id(self.local_user),
f"{self.local_user.id}-lists",
)
def test_get_rank(self, *_):
"""sort order for lists"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
book_list.updated_date = datetime(2020, 1, 1, 0, 0, 0)
self.assertEqual(self.stream.get_rank(book_list), 1577836800.0)
def test_add_user_lists(self, *_):
"""add all of a user's lists"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
with patch(
"bookwyrm.lists_stream.ListsStream.bulk_add_objects_to_store"
) as mock:
self.stream.add_user_lists(self.local_user, self.remote_user)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0][0], book_list)
self.assertEqual(args[1], f"{self.local_user.id}-lists")
def test_remove_user_lists(self, *_):
"""remove user's lists"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
with patch(
"bookwyrm.lists_stream.ListsStream.bulk_remove_objects_from_store"
) as mock:
self.stream.remove_user_lists(self.local_user, self.remote_user)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0][0], book_list)
self.assertEqual(args[1], f"{self.local_user.id}-lists")
def test_get_audience(self, *_):
"""get a list of users that should see a list"""
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="public"
)
users = self.stream.get_audience(book_list)
# remote users don't have feeds
self.assertFalse(self.remote_user in users)
self.assertTrue(self.local_user in users)
self.assertTrue(self.another_user in users)
def test_get_audience_direct(self, *_):
"""get a list of users that should see a list"""
book_list = models.List.objects.create(
user=self.remote_user,
name="hi",
privacy="direct",
)
users = self.stream.get_audience(book_list)
self.assertFalse(users.exists())
book_list = models.List.objects.create(
user=self.local_user,
name="hi",
privacy="direct",
)
users = self.stream.get_audience(book_list)
self.assertTrue(self.local_user in users)
self.assertFalse(self.another_user in users)
self.assertFalse(self.remote_user in users)
def test_get_audience_followers_remote_user(self, *_):
"""get a list of users that should see a list"""
book_list = models.List.objects.create(
user=self.remote_user,
name="hi",
privacy="followers",
)
users = self.stream.get_audience(book_list)
self.assertFalse(users.exists())
def test_get_audience_followers_self(self, *_):
"""get a list of users that should see a list"""
book_list = models.List.objects.create(
user=self.local_user,
name="hi",
privacy="followers",
)
users = self.stream.get_audience(book_list)
self.assertTrue(self.local_user in users)
self.assertFalse(self.another_user in users)
self.assertFalse(self.remote_user in users)
def test_get_audience_followers_with_relationship(self, *_):
"""get a list of users that should see a list"""
self.remote_user.followers.add(self.local_user)
book_list = models.List.objects.create(
user=self.remote_user,
name="hi",
privacy="followers",
)
users = self.stream.get_audience(book_list)
self.assertTrue(self.local_user in users)
self.assertFalse(self.another_user in users)
def test_get_audience_followers_with_group(self, *_):
"""get a list of users that should see a list"""
group = models.Group.objects.create(name="test group", user=self.remote_user)
models.GroupMember.objects.create(
group=group,
user=self.local_user,
)
book_list = models.List.objects.create(
user=self.remote_user, name="hi", privacy="followers", curation="group"
)
users = self.stream.get_audience(book_list)
self.assertFalse(self.local_user in users)
book_list.group = group
book_list.save(broadcast=False)
users = self.stream.get_audience(book_list)
self.assertTrue(self.local_user in users)
self.assertFalse(self.another_user in users)

View file

@ -0,0 +1,109 @@
""" testing lists_stream """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import lists_stream, models
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
class Activitystreams(TestCase):
"""using redis to build activity streams"""
def setUp(self):
"""use a test csv"""
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", "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",
)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.list = models.List.objects.create(
user=self.local_user, name="hi", privacy="public"
)
def test_populate_lists_task(self, *_):
"""populate lists cache"""
with patch("bookwyrm.lists_stream.ListsStream.populate_lists") as mock:
lists_stream.populate_lists_task(self.local_user.id)
self.assertTrue(mock.called)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
with patch("bookwyrm.lists_stream.ListsStream.populate_lists") as mock:
lists_stream.populate_lists_task(self.local_user.id)
self.assertTrue(mock.called)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
def test_remove_list_task(self, *_):
"""remove a list from all streams"""
with patch(
"bookwyrm.lists_stream.ListsStream.remove_object_from_related_stores"
) as mock:
lists_stream.remove_list_task(self.list.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.list.id)
def test_add_list_task(self, *_):
"""add a list to all streams"""
with patch("bookwyrm.lists_stream.ListsStream.add_list") as mock:
lists_stream.add_list_task(self.list.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.list)
def test_remove_user_lists_task(self, *_):
"""remove all lists by a user from another users' feeds"""
with patch("bookwyrm.lists_stream.ListsStream.remove_user_lists") as mock:
lists_stream.remove_user_lists_task(
self.local_user.id, self.another_user.id
)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
self.assertEqual(args[1], self.another_user)
with patch("bookwyrm.lists_stream.ListsStream.remove_user_lists") as mock:
lists_stream.remove_user_lists_task(
self.local_user.id, self.another_user.id
)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
self.assertEqual(args[1], self.another_user)
def test_add_user_lists_task(self, *_):
"""add a user's lists to another users feeds"""
with patch("bookwyrm.lists_stream.ListsStream.add_user_lists") as mock:
lists_stream.add_user_lists_task(self.local_user.id, self.another_user.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
self.assertEqual(args[1], self.another_user)
with patch("bookwyrm.lists_stream.ListsStream.add_user_lists") as mock:
lists_stream.add_user_lists_task(self.local_user.id, self.another_user.id)
self.assertEqual(mock.call_count, 1)
args = mock.call_args[0]
self.assertEqual(args[0], self.local_user)
self.assertEqual(args[1], self.another_user)

View file

@ -0,0 +1,54 @@
""" test populating user streams """
from unittest.mock import patch
from django.test import TestCase
from bookwyrm import models
from bookwyrm.management.commands.populate_lists_streams import populate_lists_streams
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class Activitystreams(TestCase):
"""using redis to build activity streams"""
def setUp(self):
"""we need some stuff"""
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", "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",
)
models.User.objects.create_user(
"gerbil",
"gerbil@nutria.nutria",
"password",
local=True,
localname="gerbil",
is_active=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.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.lists_stream.populate_lists_task.delay") as list_mock:
populate_lists_streams()
self.assertEqual(list_mock.call_count, 2) # 2 users

View file

@ -14,7 +14,7 @@ class Activitystreams(TestCase):
"""we need some stuff"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)
@ -25,6 +25,14 @@ class Activitystreams(TestCase):
local=True,
localname="nutria",
)
models.User.objects.create_user(
"gerbil",
"gerbil@gerbil.gerbil",
"password",
local=True,
localname="gerbil",
is_active=False,
)
with patch("bookwyrm.models.user.set_remote_server.delay"):
self.remote_user = models.User.objects.create_user(
"rat",
@ -44,6 +52,11 @@ class Activitystreams(TestCase):
user=self.local_user, content="hi", book=self.book
)
with patch("bookwyrm.activitystreams.populate_stream_task.delay") as redis_mock:
with patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
) as redis_mock, patch(
"bookwyrm.lists_stream.populate_lists_task.delay"
) as list_mock:
populate_streams()
self.assertEqual(redis_mock.call_count, 6) # 2 users x 3 streams
self.assertEqual(list_mock.call_count, 2) # 2 users

View file

@ -29,7 +29,7 @@ class ActivitypubMixins(TestCase):
"""shared data"""
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", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
)
@ -332,7 +332,7 @@ class ActivitypubMixins(TestCase):
self.assertEqual(activity["id"], "https://example.com/status/1/activity")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["to"], ["%s/followers" % self.local_user.remote_id])
self.assertEqual(activity["to"], [f"{self.local_user.remote_id}/followers"])
self.assertEqual(
activity["cc"], ["https://www.w3.org/ns/activitystreams#Public"]
)
@ -374,7 +374,7 @@ class ActivitypubMixins(TestCase):
for number in range(0, 2 * PAGE_LENGTH):
models.Status.objects.create(
user=self.local_user,
content="test status {:d}".format(number),
content=f"test status {number}",
)
page_1 = to_ordered_collection_page(
models.Status.objects.all(), "http://fish.com/", page=1
@ -400,7 +400,7 @@ class ActivitypubMixins(TestCase):
for number in range(0, 2 * PAGE_LENGTH):
models.Status.objects.create(
user=self.local_user,
content="test status {:d}".format(number),
content=f"test status {number}",
)
MockSelf = namedtuple("Self", ("remote_id"))

View file

@ -16,7 +16,7 @@ class BaseModel(TestCase):
"""shared data"""
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", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
)

View file

@ -27,6 +27,7 @@ from bookwyrm.settings import DOMAIN
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
class ModelFields(TestCase):
"""overwrites standard model feilds to work with activitypub"""

View file

@ -14,21 +14,15 @@ class Group(TestCase):
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.owner_user = models.User.objects.create_user(
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
self.rat = models.User.objects.create_user(
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
)
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
self.badger = models.User.objects.create_user(
"badger",
"badger@badger.badger",
@ -37,9 +31,6 @@ class Group(TestCase):
localname="badger",
)
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
self.capybara = models.User.objects.create_user(
"capybara",
"capybara@capybara.capybara",

View file

@ -20,7 +20,7 @@ class ImportJob(TestCase):
"""data is from a goodreads export of The Raven Tower"""
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", "mouse@mouse.mouse", "password", local=True
)

View file

@ -1,7 +1,7 @@
""" testing models """
from uuid import UUID
from unittest.mock import patch
from django.test import TestCase
from uuid import UUID
from bookwyrm import models, settings
@ -14,7 +14,7 @@ class List(TestCase):
"""look, a list"""
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", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)
@ -27,7 +27,7 @@ class List(TestCase):
book_list = models.List.objects.create(
name="Test List", user=self.local_user
)
expected_id = "https://%s/list/%d" % (settings.DOMAIN, book_list.id)
expected_id = f"https://{settings.DOMAIN}/list/{book_list.id}"
self.assertEqual(book_list.get_remote_id(), expected_id)
def test_to_activity(self, _):

View file

@ -15,7 +15,7 @@ class ReadThrough(TestCase):
"""look, a shelf"""
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", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)

View file

@ -1,12 +1,16 @@
""" testing models """
import json
from unittest.mock import patch
from django.db import IntegrityError
from django.test import TestCase
from bookwyrm import models
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
@patch("bookwyrm.lists_stream.remove_user_lists_task.delay")
class Relationship(TestCase):
"""following, blocking, stuff like that"""
@ -24,14 +28,39 @@ class Relationship(TestCase):
)
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", "mouse@mouse.com", "mouseword", local=True, localname="mouse"
)
self.local_user.remote_id = "http://local.com/user/mouse"
self.local_user.save(broadcast=False, update_fields=["remote_id"])
def test_user_follows_from_request(self, _):
def test_user_follows(self, *_):
"""basic functionality of user follows"""
relationship = models.UserFollows.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
self.assertEqual(relationship.status, "follows")
activity = relationship.to_activity()
self.assertEqual(activity.type, "Follow")
self.assertEqual(
relationship.remote_id,
f"http://local.com/user/mouse#follows/{relationship.id}",
)
def test_user_follows_blocks(self, *_):
"""can't follow if you're blocked"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.UserBlocks.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
with self.assertRaises(IntegrityError):
models.UserFollows.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
def test_user_follows_from_request(self, *_):
"""convert a follow request into a follow"""
with patch(
"bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
@ -42,19 +71,19 @@ class Relationship(TestCase):
activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Follow")
self.assertEqual(
request.remote_id, "http://local.com/user/mouse#follows/%d" % request.id
request.remote_id, f"http://local.com/user/mouse#follows/{request.id}"
)
self.assertEqual(request.status, "follow_request")
rel = models.UserFollows.from_request(request)
self.assertEqual(
rel.remote_id, "http://local.com/user/mouse#follows/%d" % request.id
rel.remote_id, f"http://local.com/user/mouse#follows/{request.id}"
)
self.assertEqual(rel.status, "follows")
self.assertEqual(rel.user_subject, self.local_user)
self.assertEqual(rel.user_object, self.remote_user)
def test_user_follows_from_request_custom_remote_id(self, _):
def test_user_follows_from_request_custom_remote_id(self, *_):
"""store a specific remote id for a relationship provided by remote"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
request = models.UserFollowRequest.objects.create(
@ -72,7 +101,7 @@ class Relationship(TestCase):
self.assertEqual(rel.user_object, self.remote_user)
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_follow_request_activity(self, broadcast_mock, _):
def test_follow_request_activity(self, broadcast_mock, *_):
"""accept a request and make it a relationship"""
models.UserFollowRequest.objects.create(
user_subject=self.local_user,
@ -84,7 +113,7 @@ class Relationship(TestCase):
self.assertEqual(activity["type"], "Follow")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_follow_request_accept(self, broadcast_mock, _):
def test_follow_request_accept(self, broadcast_mock, *_):
"""accept a request and make it a relationship"""
self.local_user.manually_approves_followers = True
self.local_user.save(
@ -110,7 +139,7 @@ class Relationship(TestCase):
self.assertEqual(rel.user_object, self.local_user)
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_follow_request_reject(self, broadcast_mock, _):
def test_follow_request_reject(self, broadcast_mock, *_):
"""accept a request and make it a relationship"""
self.local_user.manually_approves_followers = True
self.local_user.save(

View file

@ -9,6 +9,7 @@ from bookwyrm import models, settings
# pylint: disable=unused-argument
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.activitystreams.remove_book_statuses_task.delay")
class Shelf(TestCase):
@ -18,7 +19,7 @@ class Shelf(TestCase):
"""look, a shelf"""
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", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)
@ -31,7 +32,7 @@ class Shelf(TestCase):
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
expected_id = f"https://{settings.DOMAIN}/user/mouse/books/test-shelf"
self.assertEqual(shelf.get_remote_id(), expected_id)
def test_to_activity(self, *_):

View file

@ -16,7 +16,7 @@ class SiteModels(TestCase):
"""we need basic test data and mocks"""
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@local.com",
"mouse@mouse.com",

View file

@ -28,7 +28,7 @@ class Status(TestCase):
"""useful things for creating a status"""
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", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
)

View file

@ -15,7 +15,7 @@ class User(TestCase):
def setUp(self):
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@%s" % DOMAIN,
"mouse@mouse.mouse",

View file

@ -16,7 +16,7 @@ class BookWyrmTags(TestCase):
"""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",

View file

@ -16,7 +16,7 @@ class InteractionTags(TestCase):
"""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",

View file

@ -17,7 +17,7 @@ class StatusDisplayTags(TestCase):
"""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",

View file

@ -17,7 +17,7 @@ class UtilitiesTags(TestCase):
"""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",
@ -50,3 +50,10 @@ class UtilitiesTags(TestCase):
"""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), "")
self.assertEqual(utilities.get_title(self.book), "Test Book")
book = models.Edition.objects.create(title="Oh", subtitle="oh my")
self.assertEqual(utilities.get_title(book), "Oh: oh my")

View file

@ -16,7 +16,7 @@ class Emailing(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -32,7 +32,7 @@ class PreviewImages(TestCase):
)
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(
"possum@local.com",
"possum@possum.possum",

View file

@ -39,19 +39,19 @@ class Signature(TestCase):
"""create users and test data"""
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.mouse = models.User.objects.create_user(
"mouse@%s" % DOMAIN,
f"mouse@{DOMAIN}",
"mouse@example.com",
"",
local=True,
localname="mouse",
)
self.rat = models.User.objects.create_user(
"rat@%s" % DOMAIN, "rat@example.com", "", local=True, localname="rat"
f"rat@{DOMAIN}", "rat@example.com", "", local=True, localname="rat"
)
self.cat = models.User.objects.create_user(
"cat@%s" % DOMAIN, "cat@example.com", "", local=True, localname="cat"
f"cat@{DOMAIN}", "cat@example.com", "", local=True, localname="cat"
)
private_key, public_key = create_key_pair()
@ -75,7 +75,7 @@ class Signature(TestCase):
"HTTP_DIGEST": digest,
"HTTP_CONTENT_TYPE": "application/activity+json; charset=utf-8",
"HTTP_HOST": DOMAIN,
}
},
)
def send_test_request( # pylint: disable=too-many-arguments

View file

@ -13,6 +13,7 @@ from bookwyrm.suggested_users import suggested_users, get_annotated_users
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.suggested_users.rerank_user_task.delay")
@patch("bookwyrm.suggested_users.remove_user_task.delay")
@ -23,7 +24,7 @@ class SuggestedUsers(TestCase):
"""use a test csv"""
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", "mouse@mouse.mouse", "password", local=True, localname="mouse"
)
@ -235,12 +236,3 @@ class SuggestedUsers(TestCase):
)
user_1_annotated = result.get(id=user_1.id)
self.assertEqual(user_1_annotated.mutuals, 3)
def test_create_user_signal(self, *_):
"""build suggestions for new users"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") as mock:
models.User.objects.create_user(
"nutria", "nutria@nu.tria", "password", local=True, localname="nutria"
)
self.assertEqual(mock.call_count, 1)

View file

@ -16,7 +16,7 @@ class AnnouncementViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -16,7 +16,7 @@ class DashboardViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -17,7 +17,7 @@ class EmailBlocklistViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -19,7 +19,7 @@ class FederationViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -16,7 +16,7 @@ class IPBlocklistViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -18,7 +18,7 @@ class ReportViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -18,7 +18,7 @@ class UserAdminViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -28,7 +28,7 @@ class BookViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -21,7 +21,7 @@ class EditBookViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -18,7 +18,7 @@ class BookViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -19,7 +19,7 @@ class ImportViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -16,7 +16,7 @@ class ImportManualReviewViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -16,7 +16,7 @@ class ImportTroubleshootViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -22,7 +22,7 @@ class Inbox(TestCase):
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
local_user = models.User.objects.create_user(
"mouse@example.com",
"mouse@mouse.com",

View file

@ -15,7 +15,7 @@ class InboxAdd(TestCase):
"""basic user and book data"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
local_user = models.User.objects.create_user(
"mouse@example.com",
"mouse@mouse.com",

View file

@ -15,7 +15,7 @@ class InboxActivities(TestCase):
"""basic user and book data"""
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.com",

View file

@ -14,7 +14,7 @@ class InboxBlock(TestCase):
"""basic user and book data"""
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.com",
@ -57,7 +57,7 @@ class InboxBlock(TestCase):
with patch(
"bookwyrm.activitystreams.remove_user_statuses_task.delay"
) as redis_mock:
) as redis_mock, patch("bookwyrm.lists_stream.remove_user_lists_task.delay"):
views.inbox.activity_task(activity)
self.assertTrue(redis_mock.called)
views.inbox.activity_task(activity)
@ -70,7 +70,9 @@ class InboxBlock(TestCase):
self.assertFalse(models.UserFollowRequest.objects.exists())
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
def test_handle_unblock(self, _):
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
@patch("bookwyrm.lists_stream.remove_user_lists_task.delay")
def test_handle_unblock(self, *_):
"""unblock a user"""
self.remote_user.blocks.add(self.local_user)

View file

@ -19,7 +19,7 @@ class InboxCreate(TestCase):
"""basic user and book data"""
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.com",

View file

@ -15,7 +15,7 @@ class InboxActivities(TestCase):
"""basic user and book data"""
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.com",
@ -51,7 +51,7 @@ class InboxActivities(TestCase):
"type": "Delete",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/mouse/followers"],
"id": "%s/activity" % self.status.remote_id,
"id": f"{self.status.remote_id}/activity",
"actor": self.remote_user.remote_id,
"object": {"id": self.status.remote_id, "type": "Tombstone"},
}
@ -80,7 +80,7 @@ class InboxActivities(TestCase):
"type": "Delete",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": ["https://example.com/user/mouse/followers"],
"id": "%s/activity" % self.status.remote_id,
"id": f"{self.status.remote_id}/activity",
"actor": self.remote_user.remote_id,
"object": {"id": self.status.remote_id, "type": "Tombstone"},
}
@ -152,5 +152,7 @@ class InboxActivities(TestCase):
"cc": [],
},
}
views.inbox.activity_task(activity)
with patch("bookwyrm.lists_stream.remove_list_task.delay") as mock:
views.inbox.activity_task(activity)
self.assertTrue(mock.called)
self.assertFalse(models.List.objects.exists())

View file

@ -15,7 +15,7 @@ class InboxRelationships(TestCase):
"""basic user and book data"""
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.com",
@ -188,7 +188,8 @@ class InboxRelationships(TestCase):
self.assertIsNone(self.local_user.followers.first())
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
def test_follow_accept(self, _):
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
def test_follow_accept(self, *_):
"""a remote user approved a follow request from local"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
rel = models.UserFollowRequest.objects.create(

View file

@ -14,7 +14,7 @@ class InboxActivities(TestCase):
"""basic user and book data"""
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.com",

View file

@ -14,7 +14,7 @@ class InboxRemove(TestCase):
"""basic user and book data"""
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.com",

View file

@ -16,7 +16,7 @@ class InboxUpdate(TestCase):
"""basic user and book data"""
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.com",
@ -78,6 +78,7 @@ class InboxUpdate(TestCase):
@patch("bookwyrm.suggested_users.rerank_user_task.delay")
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
def test_update_user(self, *_):
"""update an existing user"""
models.UserFollows.objects.create(

View file

@ -19,7 +19,7 @@ class InviteViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -18,7 +18,7 @@ class LandingViews(TestCase):
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@local.com",
"mouse@mouse.mouse",
@ -49,7 +49,27 @@ class LandingViews(TestCase):
def test_about_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.About.as_view()
view = views.about
request = self.factory.get("")
request.user = self.local_user
result = view(request)
self.assertIsInstance(result, TemplateResponse)
validate_html(result.render())
self.assertEqual(result.status_code, 200)
def test_conduct_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.conduct
request = self.factory.get("")
request.user = self.local_user
result = view(request)
self.assertIsInstance(result, TemplateResponse)
validate_html(result.render())
self.assertEqual(result.status_code, 200)
def test_privacy_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.privacy
request = self.factory.get("")
request.user = self.local_user
result = view(request)

View file

@ -21,7 +21,7 @@ class LoginViews(TestCase):
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@your.domain.here",
"mouse@mouse.com",

View file

@ -21,7 +21,7 @@ class PasswordViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -16,6 +16,7 @@ from bookwyrm.tests.validate_html import validate_html
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
class RegisterViews(TestCase):
"""login and password management"""
@ -24,7 +25,7 @@ class RegisterViews(TestCase):
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@your.domain.here",
"mouse@mouse.com",

View file

@ -18,7 +18,7 @@ class BlockViews(TestCase):
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@local.com",
"mouse@mouse.mouse",
@ -61,7 +61,9 @@ class BlockViews(TestCase):
request = self.factory.post("")
request.user = self.local_user
with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"):
with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"), patch(
"bookwyrm.lists_stream.remove_user_lists_task.delay"
):
view(request, self.remote_user.id)
block = models.UserBlocks.objects.get()
self.assertEqual(block.user_subject, self.local_user)
@ -76,7 +78,9 @@ class BlockViews(TestCase):
request = self.factory.post("")
request.user = self.local_user
with patch("bookwyrm.activitystreams.add_user_statuses_task.delay"):
with patch("bookwyrm.activitystreams.add_user_statuses_task.delay"), patch(
"bookwyrm.lists_stream.add_user_lists_task.delay"
):
views.unblock(request, self.remote_user.id)
self.assertFalse(models.UserBlocks.objects.exists())

View file

@ -17,7 +17,7 @@ class ChangePasswordViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -20,7 +20,7 @@ class DeleteUserViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -23,7 +23,7 @@ class EditUserViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -14,6 +14,7 @@ from bookwyrm.tests.validate_html import validate_html
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.activitystreams.remove_book_statuses_task.delay")
class ShelfViews(TestCase):
@ -24,7 +25,7 @@ class ShelfViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -12,6 +12,7 @@ from bookwyrm import forms, models, views
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.activitystreams.remove_book_statuses_task.delay")
class ShelfActionViews(TestCase):
@ -22,7 +23,7 @@ class ShelfActionViews(TestCase):
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@local.com",
"mouse@mouse.com",
@ -178,7 +179,7 @@ class ShelfActionViews(TestCase):
"""delete a brand new custom shelf"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
rat = models.User.objects.create_user(
"rat@local.com",
"rat@mouse.mouse",

View file

@ -26,7 +26,7 @@ class AnnualSummary(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -21,7 +21,7 @@ class AuthorViews(TestCase):
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@local.com",
"mouse@mouse.com",

View file

@ -18,7 +18,7 @@ class DirectoryViews(TestCase):
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@local.com",
"mouse@mouse.com",
@ -34,6 +34,7 @@ class DirectoryViews(TestCase):
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.suggested_users.rerank_user_task.delay")
def test_directory_page(self, *_):
"""there are so many views, this just makes sure it LOADS"""

View file

@ -16,7 +16,7 @@ class DiscoverViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

View file

@ -10,8 +10,7 @@ from django.template.response import TemplateResponse
from django.test import TestCase
from django.test.client import RequestFactory
from bookwyrm import models
from bookwyrm import views
from bookwyrm import forms, models, views
from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.tests.validate_html import validate_html
@ -20,6 +19,7 @@ from bookwyrm.tests.validate_html import validate_html
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")
@patch("bookwyrm.suggested_users.remove_user_task.delay")
class FeedViews(TestCase):
"""activity feed, statuses, dms"""
@ -29,7 +29,7 @@ class FeedViews(TestCase):
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@local.com",
"mouse@mouse.mouse",
@ -62,6 +62,25 @@ class FeedViews(TestCase):
validate_html(result.render())
self.assertEqual(result.status_code, 200)
@patch("bookwyrm.suggested_users.SuggestedUsers.get_suggestions")
def test_save_feed_settings(self, *_):
"""update display preferences"""
self.assertEqual(
self.local_user.feed_status_types,
["review", "comment", "quotation", "everything"],
)
view = views.Feed.as_view()
form = forms.FeedStatusTypesForm(instance=self.local_user)
form.data["feed_status_types"] = "review"
request = self.factory.post("", form.data)
request.user = self.local_user
result = view(request, "home")
self.assertEqual(result.status_code, 200)
self.local_user.refresh_from_db()
self.assertEqual(self.local_user.feed_status_types, ["review"])
def test_status_page(self, *_):
"""there are so many views, this just makes sure it LOADS"""
view = views.Status.as_view()

View file

@ -13,6 +13,7 @@ from bookwyrm.tests.validate_html import validate_html
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
@patch("bookwyrm.lists_stream.add_user_lists_task.delay")
class FollowViews(TestCase):
"""follows"""
@ -22,7 +23,7 @@ class FollowViews(TestCase):
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@local.com",
"mouse@mouse.com",
@ -56,7 +57,7 @@ class FollowViews(TestCase):
parent_work=self.work,
)
def test_handle_follow_remote(self, _):
def test_handle_follow_remote(self, *_):
"""send a follow request"""
request = self.factory.post("", {"user": self.remote_user.username})
request.user = self.local_user
@ -71,11 +72,11 @@ class FollowViews(TestCase):
self.assertEqual(rel.user_object, self.remote_user)
self.assertEqual(rel.status, "follow_request")
def test_handle_follow_local_manually_approves(self, _):
def test_handle_follow_local_manually_approves(self, *_):
"""send a follow request"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
rat = models.User.objects.create_user(
"rat@local.com",
"rat@rat.com",
@ -97,11 +98,11 @@ class FollowViews(TestCase):
self.assertEqual(rel.user_object, rat)
self.assertEqual(rel.status, "follow_request")
def test_handle_follow_local(self, _):
def test_handle_follow_local(self, *_):
"""send a follow request"""
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
rat = models.User.objects.create_user(
"rat@local.com",
"rat@rat.com",
@ -124,6 +125,7 @@ class FollowViews(TestCase):
self.assertEqual(rel.status, "follows")
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
@patch("bookwyrm.lists_stream.remove_user_lists_task.delay")
def test_handle_unfollow(self, *_):
"""send an unfollow"""
request = self.factory.post("", {"user": self.remote_user.username})
@ -140,7 +142,7 @@ class FollowViews(TestCase):
self.assertEqual(self.remote_user.followers.count(), 0)
def test_handle_accept(self, _):
def test_handle_accept(self, *_):
"""accept a follow request"""
self.local_user.manually_approves_followers = True
self.local_user.save(
@ -159,7 +161,7 @@ class FollowViews(TestCase):
# follow relationship should exist
self.assertEqual(self.local_user.followers.first(), self.remote_user)
def test_handle_reject(self, _):
def test_handle_reject(self, *_):
"""reject a follow request"""
self.local_user.manually_approves_followers = True
self.local_user.save(
@ -178,7 +180,7 @@ class FollowViews(TestCase):
# follow relationship should not exist
self.assertEqual(models.UserFollows.objects.filter(id=rel.id).count(), 0)
def test_ostatus_follow_request(self, _):
def test_ostatus_follow_request(self, *_):
"""check ostatus subscribe template loads"""
request = self.factory.get(
"", {"acct": "https%3A%2F%2Fexample.com%2Fusers%2Frat"}
@ -189,7 +191,7 @@ class FollowViews(TestCase):
validate_html(result.render())
self.assertEqual(result.status_code, 200)
def test_remote_follow_page(self, _):
def test_remote_follow_page(self, *_):
"""check remote follow page loads"""
request = self.factory.get("", {"acct": "mouse@local.com"})
request.user = self.remote_user
@ -198,7 +200,7 @@ class FollowViews(TestCase):
validate_html(result.render())
self.assertEqual(result.status_code, 200)
def test_ostatus_follow_success(self, _):
def test_ostatus_follow_success(self, *_):
"""check remote follow success page loads"""
request = self.factory.get("")
request.user = self.remote_user
@ -208,7 +210,7 @@ class FollowViews(TestCase):
validate_html(result.render())
self.assertEqual(result.status_code, 200)
def test_remote_follow(self, _):
def test_remote_follow(self, *_):
"""check follow from remote page loads"""
request = self.factory.post("", {"user": self.remote_user.id})
request.user = self.remote_user

View file

@ -17,7 +17,7 @@ class GetStartedViews(TestCase):
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@local.com",
"mouse@mouse.mouse",

Some files were not shown because too many files have changed in this diff Show more