Merge pull request #384 from mouse-reeve/cleanup

Cleans up template tags
This commit is contained in:
Mouse Reeve 2020-12-12 20:07:44 -08:00 committed by GitHub
commit d4f8f2e276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 288 additions and 60 deletions

View File

@ -1,7 +1,7 @@
''' customize the info available in context for rendering templates ''' ''' customize the info available in context for rendering templates '''
from bookwyrm import models from bookwyrm import models
def site_settings(request): def site_settings(request):# pylint: disable=unused-argument
''' include the custom info about the site ''' ''' include the custom info about the site '''
return { return {
'site': models.SiteSettings.objects.get() 'site': models.SiteSettings.objects.get()

View File

@ -30,7 +30,7 @@ class CustomForm(ModelForm):
visible.field.widget.attrs['rows'] = None visible.field.widget.attrs['rows'] = None
visible.field.widget.attrs['class'] = css_classes[input_type] visible.field.widget.attrs['class'] = css_classes[input_type]
# pylint: disable=missing-class-docstring
class LoginForm(CustomForm): class LoginForm(CustomForm):
class Meta: class Meta:
model = models.User model = models.User
@ -131,6 +131,7 @@ class ImportForm(forms.Form):
class ExpiryWidget(widgets.Select): class ExpiryWidget(widgets.Select):
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
''' human-readable exiration time buckets '''
selected_string = super().value_from_datadict(data, files, name) selected_string = super().value_from_datadict(data, files, name)
if selected_string == 'day': if selected_string == 'day':

View File

@ -53,7 +53,7 @@ def import_data(job_id):
for item in job.items.all(): for item in job.items.all():
try: try:
item.resolve() item.resolve()
except Exception as e: except Exception as e:# pylint: disable=broad-except
logger.exception(e) logger.exception(e)
item.fail_reason = 'Error loading book' item.fail_reason = 'Error loading book'
item.save() item.save()

View File

@ -17,9 +17,6 @@ from bookwyrm.signatures import Signature
@csrf_exempt @csrf_exempt
def inbox(request, username): def inbox(request, username):
''' incoming activitypub events ''' ''' incoming activitypub events '''
# TODO: should do some kind of checking if the user accepts
# this action from the sender probably? idk
# but this will just throw a 404 if the user doesn't exist
try: try:
models.User.objects.get(localname=username) models.User.objects.get(localname=username)
except models.User.DoesNotExist: except models.User.DoesNotExist:

View File

@ -16,7 +16,8 @@ class Author(ActivitypubMixin, BookWyrmModel):
max_length=255, blank=True, null=True, deduplication_field=True) max_length=255, blank=True, null=True, deduplication_field=True)
sync = models.BooleanField(default=True) sync = models.BooleanField(default=True)
last_sync_date = models.DateTimeField(default=timezone.now) last_sync_date = models.DateTimeField(default=timezone.now)
wikipedia_link = fields.CharField(max_length=255, blank=True, null=True, deduplication_field=True) wikipedia_link = fields.CharField(
max_length=255, blank=True, null=True, deduplication_field=True)
# idk probably other keys would be useful here? # idk probably other keys would be useful here?
born = fields.DateTimeField(blank=True, null=True) born = fields.DateTimeField(blank=True, null=True)
died = fields.DateTimeField(blank=True, null=True) died = fields.DateTimeField(blank=True, null=True)

View File

@ -44,6 +44,7 @@ class BookWyrmModel(models.Model):
@receiver(models.signals.post_save) @receiver(models.signals.post_save)
#pylint: disable=unused-argument
def execute_after_save(sender, instance, created, *args, **kwargs): def execute_after_save(sender, instance, created, *args, **kwargs):
''' set the remote_id after save (when the id is available) ''' ''' set the remote_id after save (when the id is available) '''
if not created or not hasattr(instance, 'get_remote_id'): if not created or not hasattr(instance, 'get_remote_id'):

View File

@ -6,7 +6,6 @@ from django.db import models
from django.utils import timezone from django.utils import timezone
from bookwyrm import books_manager from bookwyrm import books_manager
from bookwyrm.connectors import ConnectorException
from bookwyrm.models import ReadThrough, User, Book from bookwyrm.models import ReadThrough, User, Book
from bookwyrm.utils.fields import JSONField from bookwyrm.utils.fields import JSONField
from .base_model import PrivacyLevels from .base_model import PrivacyLevels

View File

@ -37,7 +37,7 @@ class UserRelationship(ActivitypubMixin, BookWyrmModel):
activity_serializer = activitypub.Follow activity_serializer = activitypub.Follow
def get_remote_id(self, status=None): def get_remote_id(self, status=None):# pylint: disable=arguments-differ
''' use shelf identifier in remote_id ''' ''' use shelf identifier in remote_id '''
status = status or 'follows' status = status or 'follows'
base_path = self.user_subject.remote_id base_path = self.user_subject.remote_id

View File

@ -1,7 +1,7 @@
''' Handle user activity ''' ''' Handle user activity '''
from django.utils import timezone from django.utils import timezone
from bookwyrm import activitypub, books_manager, models from bookwyrm import models
from bookwyrm.sanitize_html import InputHtmlParser from bookwyrm.sanitize_html import InputHtmlParser

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title">{{ author.name }}</h1> <h1 class="title">{{ author.name }}</h1>

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% load humanize %} {% load humanize %}
{% block content %} {% block content %}

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title">Editions of <a href="/book/{{ work.id }}">"{{ work.title }}"</a></h1> <h1 class="title">Editions of <a href="/book/{{ work.id }}">"{{ work.title }}"</a></h1>

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="columns"> <div class="columns">

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title"> <h1 class="title">

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title"> <h1 class="title">

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% load humanize %} {% load humanize %}
{% block content %} {% block content %}
<div class="block"> <div class="block">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>

View File

@ -1,6 +1,6 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load humanize %} {% load humanize %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">
<h1 class="title">Notifications</h1> <h1 class="title">Notifications</h1>

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="columns"> <div class="columns">

View File

@ -1,3 +1,3 @@
{% load fr_display %} {% load bookwyrm_tags %}
<img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" alt="avatar for {{ user|username }}"> <img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" alt="avatar for {{ user|username }}">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div class="cover-container is-{{ size }}"> <div class="cover-container is-{{ size }}">
{% if book.cover %} {% if book.cover %}
<img class="book-cover" src="/images/{{ book.cover }}" alt="{% include 'snippets/cover_alt.html' with book=book %}"> <img class="book-cover" src="/images/{{ book.cover }}" alt="{% include 'snippets/cover_alt.html' with book=book %}">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div class="columns"> <div class="columns">
<div class="column is-narrow"> <div class="column is-narrow">
<div> <div>

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% with status.id|uuid as uuid %} {% with status.id|uuid as uuid %}
<form name="boost" action="/boost/{{ status.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }}-{{ uuid }} {% if request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}"> <form name="boost" action="/boost/{{ status.id }}" method="post" onsubmit="return interact(event)" class="boost-{{ status.id }}-{{ uuid }} {% if request.user|boosted:status %}hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
{% csrf_token %} {% csrf_token %}

View File

@ -1,2 +1,2 @@
{% load fr_display %} {% load bookwyrm_tags %}
'{{ book.title }}' Cover ({{ book|edition_info }}) '{{ book.title }}' Cover ({{ book|edition_info }})

View File

@ -1,5 +1,5 @@
{% load humanize %} {% load humanize %}
{% load fr_display %} {% load bookwyrm_tags %}
<div class="tabs is-boxed"> <div class="tabs is-boxed">
<ul role="tablist"> <ul role="tablist">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% with status.id|uuid as uuid %} {% with status.id|uuid as uuid %}
<form name="favorite" action="/favorite/{{ status.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }}-{{ uuid }} {% if request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}"> <form name="favorite" action="/favorite/{{ status.id }}" method="POST" onsubmit="return interact(event)" class="fav-{{ status.id }}-{{ uuid }} {% if request.user|liked:status %}hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %} {% csrf_token %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div> <div>
<input class="toggle-control" type="checkbox" name="finish-reading-{{ uuid }}" id="finish-reading-{{ uuid }}"> <input class="toggle-control" type="checkbox" name="finish-reading-{{ uuid }}" id="finish-reading-{{ uuid }}">
<div class="modal toggle-content hidden"> <div class="modal toggle-content hidden">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% if request.user|follow_request_exists:user %} {% if request.user|follow_request_exists:user %}
<form action="/accept-follow-request/" method="POST"> <form action="/accept-follow-request/" method="POST">
{% csrf_token %} {% csrf_token %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div class="select"> <div class="select">
{% with 0|uuid as uuid %} {% with 0|uuid as uuid %}
{% if not no_label %} {% if not no_label %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<span class="is-sr-only">Leave a rating</span> <span class="is-sr-only">Leave a rating</span>
<div class="field is-grouped stars rate-stars"> <div class="field is-grouped stars rate-stars">
{% for i in '12345'|make_list %} {% for i in '12345'|make_list %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% with activity.id|uuid as uuid %} {% with activity.id|uuid as uuid %}
<form class="is-flex-grow-1" name="reply" action="/reply" method="post" onsubmit="return reply(event)"> <form class="is-flex-grow-1" name="reply" action="/reply" method="post" onsubmit="return reply(event)">
<div class="columns"> <div class="columns">

View File

@ -1,5 +1,5 @@
{% load humanize %} {% load humanize %}
{% load fr_display %} {% load bookwyrm_tags %}
{% if shelf.books.all|length > 0 %} {% if shelf.books.all|length > 0 %}
<table class="table is-striped is-fullwidth"> <table class="table is-striped is-fullwidth">

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
{% with book.id|uuid as uuid %} {% with book.id|uuid as uuid %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% if not status.deleted %} {% if not status.deleted %}
{% if status.status_type == 'Boost' %} {% if status.status_type == 'Boost' %}
{% include 'snippets/avatar.html' with user=status.user %} {% include 'snippets/avatar.html' with user=status.user %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% load humanize %} {% load humanize %}
{% if not status.deleted %} {% if not status.deleted %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div class="block"> <div class="block">
{% if status.status_type == 'Review' %} {% if status.status_type == 'Review' %}
<h3> <h3>

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% include 'snippets/avatar.html' with user=status.user %} {% include 'snippets/avatar.html' with user=status.user %}
{% include 'snippets/username.html' with user=status.user %} {% include 'snippets/username.html' with user=status.user %}

View File

@ -1,4 +1,4 @@
{% load fr_display %} {% load bookwyrm_tags %}
<div class="block"> <div class="block">
{% with depth=depth|add:1 %} {% with depth=depth|add:1 %}

View File

@ -1,8 +1,8 @@
{% load fr_display %} {% load bookwyrm_tags %}
{% with 0|uuid as uuid %} {% with 0|uuid as uuid %}
{% if full %} {% if full %}
{% with full|text_overflow as trimmed %} {% with full|truncatewords_html:60 as trimmed %}
{% if trimmed != full %} {% if trimmed != full %}
<div> <div>
<input type="radio" name="show-hide-{{ uuid }}" id="show-{{ uuid }}" class="toggle-control" checked> <input type="radio" name="show-hide-{{ uuid }}" id="show-{{ uuid }}" class="toggle-control" checked>

View File

@ -1,5 +1,5 @@
{% load humanize %} {% load humanize %}
{% load fr_display %} {% load bookwyrm_tags %}
<div class="block"> <div class="block">
<div class="columns"> <div class="columns">
<div class="column is-narrow"> <div class="column is-narrow">

View File

@ -1,2 +1,2 @@
{% load fr_display %} {% load bookwyrm_tags %}
<a href="/user/{{ user | username }}" class="user">{% if user.name %}{{ user.name }}{% else %}{{ user | username }}{% endif %}</a>{% if possessive %}'s{% endif %}{% if show_full and user.name or show_full and user.localname %} ({{ user.username }}){% endif %} <a href="/user/{{ user | username }}" class="user">{% if user.name %}{{ user.name }}{% else %}{{ user | username }}{% endif %}</a>{% if possessive %}'s{% endif %}{% if show_full and user.name or show_full and user.localname %} ({{ user.username }}){% endif %}

View File

@ -1,5 +1,5 @@
{% extends 'layout.html' %} {% extends 'layout.html' %}
{% load fr_display %} {% load bookwyrm_tags %}
{% block content %} {% block content %}
<div class="block"> <div class="block">

View File

@ -13,7 +13,7 @@ register = template.Library()
@register.filter(name='dict_key') @register.filter(name='dict_key')
def dict_key(d, k): def dict_key(d, k):
'''Returns the given key from a dictionary.''' ''' Returns the given key from a dictionary. '''
return d.get(k) or 0 return d.get(k) or 0
@ -116,20 +116,6 @@ def get_book_description(book):
''' use the work's text if the book doesn't have it ''' ''' use the work's text if the book doesn't have it '''
return book.description or book.parent_work.description return book.description or book.parent_work.description
@register.filter(name='text_overflow')
def text_overflow(text):
''' dont' let book descriptions run for ages '''
if not text:
return ''
char_max = 400
if text and len(text) < char_max:
return text
trimmed = text[:char_max]
# go back to the last space
trimmed = ' '.join(trimmed.split(' ')[:-1])
return trimmed + '...'
@register.filter(name='uuid') @register.filter(name='uuid')
def get_uuid(identifier): def get_uuid(identifier):
@ -146,6 +132,8 @@ def time_since(date):
delta = now - date delta = now - date
if date < (now - relativedelta(weeks=1)): if date < (now - relativedelta(weeks=1)):
if date.year != now.year:
return date.strftime('%b %-d %Y')
return date.strftime('%b %-d') return date.strftime('%b %-d')
delta = relativedelta(now, date) delta = relativedelta(now, date)
if delta.days: if delta.days:
@ -160,7 +148,6 @@ def time_since(date):
@register.simple_tag(takes_context=True) @register.simple_tag(takes_context=True)
def active_shelf(context, book): def active_shelf(context, book):
''' check what shelf a user has a book on, if any ''' ''' check what shelf a user has a book on, if any '''
#TODO: books can be on multiple shelves, handle that better
shelf = models.ShelfBook.objects.filter( shelf = models.ShelfBook.objects.filter(
shelf__user=context['request'].user, shelf__user=context['request'].user,
book=book book=book

View File

@ -0,0 +1,242 @@
''' style fixes and lookups for templates '''
import re
from unittest.mock import patch
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from django.test import TestCase
from django.utils import timezone
from bookwyrm import models
from bookwyrm.templatetags import bookwyrm_tags
class TemplateTags(TestCase):
''' lotta different things here '''
def setUp(self):
''' create some filler objects '''
self.user = models.User.objects.create_user(
'mouse', 'mouse@mouse.mouse', 'mouseword', local=True)
with patch('bookwyrm.models.user.set_remote_server.delay'):
self.remote_user = models.User.objects.create_user(
'rat', 'rat@rat.rat', 'ratword',
remote_id='http://example.com/rat', local=False)
self.book = models.Edition.objects.create(title='Test Book')
def test_dict_key(self):
''' just getting a value out of a dict '''
test_dict = {'a': 1, 'b': 3}
self.assertEqual(
bookwyrm_tags.dict_key(test_dict, 'a'), 1)
self.assertEqual(
bookwyrm_tags.dict_key(test_dict, 'c'), 0)
def test_get_rating(self):
''' get a user's most recent rating of a book '''
models.Review.objects.create(
user=self.user, book=self.book, rating=3)
self.assertEqual(
bookwyrm_tags.get_rating(self.book, self.user), 3)
def test_get_rating_doesnt_exist(self):
''' there is no rating available '''
self.assertEqual(
bookwyrm_tags.get_rating(self.book, self.user), 0)
def test_get_user_identifer_local(self):
''' fall back to the simplest uid available '''
self.assertNotEqual(self.user.username, self.user.localname)
self.assertEqual(
bookwyrm_tags.get_user_identifier(self.user), 'mouse')
def test_get_user_identifer_remote(self):
''' for a remote user, should be their full username '''
self.assertEqual(
bookwyrm_tags.get_user_identifier(self.remote_user),
'rat@example.com')
def test_get_notification_count(self):
''' just countin' '''
self.assertEqual(bookwyrm_tags.get_notification_count(self.user), 0)
models.Notification.objects.create(
user=self.user, notification_type='FOLLOW')
models.Notification.objects.create(
user=self.user, notification_type='FOLLOW')
models.Notification.objects.create(
user=self.remote_user, notification_type='FOLLOW')
self.assertEqual(bookwyrm_tags.get_notification_count(self.user), 2)
def test_get_replies(self):
''' direct replies to a status '''
parent = models.Review.objects.create(
user=self.user, book=self.book)
first_child = models.Status.objects.create(
reply_parent=parent, user=self.user)
second_child = models.Status.objects.create(
reply_parent=parent, user=self.user)
third_child = models.Status.objects.create(
reply_parent=parent, user=self.user, deleted=True)
replies = bookwyrm_tags.get_replies(parent)
self.assertEqual(len(replies), 2)
self.assertTrue(first_child in replies)
self.assertTrue(second_child in replies)
self.assertFalse(third_child in replies)
def test_get_parent(self):
''' get the reply parent of a status '''
parent = models.Review.objects.create(
user=self.user, book=self.book)
child = models.Status.objects.create(
reply_parent=parent, user=self.user)
result = bookwyrm_tags.get_parent(child)
self.assertEqual(result, parent)
self.assertIsInstance(result, models.Review)
def test_get_user_liked(self):
''' did a user like a status '''
status = models.Review.objects.create(
user=self.remote_user, book=self.book)
self.assertFalse(bookwyrm_tags.get_user_liked(self.user, status))
models.Favorite.objects.create(
user=self.user,
status=status
)
self.assertTrue(bookwyrm_tags.get_user_liked(self.user, status))
def test_get_user_boosted(self):
''' did a user boost a status '''
status = models.Review.objects.create(
user=self.remote_user, book=self.book)
self.assertFalse(bookwyrm_tags.get_user_boosted(self.user, status))
models.Boost.objects.create(
user=self.user,
boosted_status=status
)
self.assertTrue(bookwyrm_tags.get_user_boosted(self.user, status))
def test_follow_request_exists(self):
''' does a user want to follow '''
self.assertFalse(
bookwyrm_tags.follow_request_exists(self.user, self.remote_user))
models.UserFollowRequest.objects.create(
user_subject=self.user,
user_object=self.remote_user)
self.assertFalse(
bookwyrm_tags.follow_request_exists(self.user, self.remote_user))
self.assertTrue(
bookwyrm_tags.follow_request_exists(self.remote_user, self.user))
def test_get_boosted(self):
''' load a boosted status '''
status = models.Review.objects.create(
user=self.remote_user, book=self.book)
boost = models.Boost.objects.create(
user=self.user,
boosted_status=status
)
boosted = bookwyrm_tags.get_boosted(boost)
self.assertIsInstance(boosted, models.Review)
self.assertEqual(boosted, status)
def test_get_edition_info(self):
''' text slug about an edition '''
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), '')
self.book.physical_format = 'worm'
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), 'worm')
self.book.languages = ['English']
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book), 'worm')
self.book.languages = ['Glorbish', 'English']
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book),
'worm, Glorbish language')
self.book.published_date = timezone.make_aware(parse('2020'))
self.book.save()
self.assertEqual(
bookwyrm_tags.get_edition_info(self.book),
'worm, Glorbish language, 2020')
def test_get_book_description(self):
''' grab it from the edition or the parent '''
work = models.Work.objects.create(title='Test Work')
self.book.parent_work = work
self.book.save()
self.assertIsNone(bookwyrm_tags.get_book_description(self.book))
work.description = 'hi'
work.save()
self.assertEqual(bookwyrm_tags.get_book_description(self.book), 'hi')
self.book.description = 'hello'
self.book.save()
self.assertEqual(bookwyrm_tags.get_book_description(self.book), 'hello')
def test_get_uuid(self):
''' uuid functionality '''
uuid = bookwyrm_tags.get_uuid('hi')
self.assertTrue(re.match(r'hi[A-Za-z0-9\-]', uuid))
def test_time_since(self):
''' ultraconcise timestamps '''
self.assertEqual(bookwyrm_tags.time_since('bleh'), '')
now = timezone.now()
self.assertEqual(bookwyrm_tags.time_since(now), '0s')
seconds_ago = now - relativedelta(seconds=4)
self.assertEqual(bookwyrm_tags.time_since(seconds_ago), '4s')
minutes_ago = now - relativedelta(minutes=8)
self.assertEqual(bookwyrm_tags.time_since(minutes_ago), '8m')
hours_ago = now - relativedelta(hours=9)
self.assertEqual(bookwyrm_tags.time_since(hours_ago), '9h')
days_ago = now - relativedelta(days=3)
self.assertEqual(bookwyrm_tags.time_since(days_ago), '3d')
# I am not going to figure out how to mock dates tonight.
months_ago = now - relativedelta(months=5)
self.assertTrue(re.match(
r'[A-Z][a-z]{2} \d?\d',
bookwyrm_tags.time_since(months_ago)
))
years_ago = now - relativedelta(years=10)
self.assertTrue(re.match(
r'[A-Z][a-z]{2} \d?\d \d{4}',
bookwyrm_tags.time_since(years_ago)
))