bookwyrm/bookwyrm/tests/models/test_bookwyrm_export_job.py
2024-03-29 14:25:08 +01:00

257 lines
9.7 KiB
Python

"""test bookwyrm user export functions"""
import datetime
import json
import pathlib
from unittest.mock import patch
from django.utils import timezone
from django.test import TestCase
from bookwyrm import models
from bookwyrm.utils.tar import BookwyrmTarFile
class BookwyrmExportJob(TestCase):
"""testing user export functions"""
def setUp(self):
"""lots of stuff to set up for a user export"""
with (
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"),
patch("bookwyrm.lists_stream.remove_list_task.delay"),
patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"),
patch("bookwyrm.activitystreams.add_book_statuses_task"),
):
self.local_user = models.User.objects.create_user(
"mouse",
"mouse@mouse.mouse",
"password",
local=True,
localname="mouse",
name="Mouse",
summary="I'm a real bookmouse",
manually_approves_followers=False,
hide_follows=False,
show_goal=False,
show_suggested_users=False,
discoverable=True,
preferred_timezone="America/Los Angeles",
default_post_privacy="followers",
)
avatar_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg"
)
with open(avatar_path, "rb") as avatar_file:
self.local_user.avatar.save("mouse-avatar.jpg", avatar_file)
self.rat_user = models.User.objects.create_user(
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
)
self.badger_user = models.User.objects.create_user(
"badger",
"badger@badger.badger",
"badgerword",
local=True,
localname="badger",
)
models.AnnualGoal.objects.create(
user=self.local_user,
year=timezone.now().year,
goal=128937123,
privacy="followers",
)
self.list = models.List.objects.create(
name="My excellent list",
user=self.local_user,
remote_id="https://local.lists/1111",
)
self.saved_list = models.List.objects.create(
name="My cool list",
user=self.rat_user,
remote_id="https://local.lists/9999",
)
self.local_user.saved_lists.add(self.saved_list)
self.local_user.blocks.add(self.badger_user)
self.rat_user.followers.add(self.local_user)
# book, edition, author
self.author = models.Author.objects.create(name="Sam Zhu")
self.work = models.Work.objects.create(
title="Example Work", remote_id="https://example.com/book/1"
)
self.edition = models.Edition.objects.create(
title="Example Edition", parent_work=self.work
)
# edition cover
cover_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg"
)
with open(cover_path, "rb") as cover_file:
self.edition.cover.save("tèst.jpg", cover_file)
self.edition.authors.add(self.author)
# readthrough
self.readthrough_start = timezone.now()
finish = self.readthrough_start + datetime.timedelta(days=1)
models.ReadThrough.objects.create(
user=self.local_user,
book=self.edition,
start_date=self.readthrough_start,
finish_date=finish,
)
# shelve
read_shelf = models.Shelf.objects.get(
user=self.local_user, identifier="read"
)
models.ShelfBook.objects.create(
book=self.edition, shelf=read_shelf, user=self.local_user
)
# add to list
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
book=self.edition,
approved=True,
order=1,
)
# review
models.Review.objects.create(
content="awesome",
name="my review",
rating=5,
user=self.local_user,
book=self.edition,
)
# comment
models.Comment.objects.create(
content="ok so far",
user=self.local_user,
book=self.edition,
progress=15,
)
# quote
models.Quotation.objects.create(
content="check this out",
quote="A rose by any other name",
user=self.local_user,
book=self.edition,
)
self.job = models.BookwyrmExportJob.objects.create(user=self.local_user)
# run the first stage of the export
with patch("bookwyrm.models.bookwyrm_export_job.create_archive_task.delay"):
models.bookwyrm_export_job.create_export_json_task(job_id=self.job.id)
self.job.refresh_from_db()
def test_add_book_to_user_export_job(self):
"""does AddBookToUserExportJob ...add the book to the export?"""
self.assertIsNotNone(self.job.export_json["books"])
self.assertEqual(len(self.job.export_json["books"]), 1)
book = self.job.export_json["books"][0]
self.assertEqual(book["work"]["id"], self.work.remote_id)
self.assertEqual(len(book["authors"]), 1)
self.assertEqual(len(book["shelves"]), 1)
self.assertEqual(len(book["lists"]), 1)
self.assertEqual(len(book["comments"]), 1)
self.assertEqual(len(book["reviews"]), 1)
self.assertEqual(len(book["quotations"]), 1)
self.assertEqual(len(book["readthroughs"]), 1)
self.assertEqual(book["edition"]["id"], self.edition.remote_id)
self.assertEqual(
book["edition"]["cover"]["url"], f"images/{self.edition.cover.name}"
)
def test_start_export_task(self):
"""test saved list task saves initial json and data"""
self.assertIsNotNone(self.job.export_data)
self.assertIsNotNone(self.job.export_json)
self.assertEqual(self.job.export_json["name"], self.local_user.name)
def test_export_saved_lists_task(self):
"""test export_saved_lists_task adds the saved lists"""
self.assertIsNotNone(self.job.export_json["saved_lists"])
self.assertEqual(
self.job.export_json["saved_lists"][0], self.saved_list.remote_id
)
def test_export_follows_task(self):
"""test export_follows_task adds the follows"""
self.assertIsNotNone(self.job.export_json["follows"])
self.assertEqual(self.job.export_json["follows"][0], self.rat_user.remote_id)
def test_export_blocks_task(self):
"""test export_blocks_task adds the blocks"""
self.assertIsNotNone(self.job.export_json["blocks"])
self.assertEqual(self.job.export_json["blocks"][0], self.badger_user.remote_id)
def test_export_reading_goals_task(self):
"""test export_reading_goals_task adds the goals"""
self.assertIsNotNone(self.job.export_json["goals"])
self.assertEqual(self.job.export_json["goals"][0]["goal"], 128937123)
def test_json_export(self):
"""test json_export job adds settings"""
self.assertIsNotNone(self.job.export_json["settings"])
self.assertFalse(self.job.export_json["settings"]["show_goal"])
self.assertEqual(
self.job.export_json["settings"]["preferred_timezone"],
"America/Los Angeles",
)
self.assertEqual(
self.job.export_json["settings"]["default_post_privacy"], "followers"
)
self.assertFalse(self.job.export_json["settings"]["show_suggested_users"])
def test_get_books_for_user(self):
"""does get_books_for_user get all the books"""
data = models.bookwyrm_export_job.get_books_for_user(self.local_user)
self.assertEqual(len(data), 1)
self.assertEqual(data[0].title, "Example Edition")
def test_archive(self):
"""actually create the TAR file"""
models.bookwyrm_export_job.create_archive_task(job_id=self.job.id)
self.job.refresh_from_db()
with (
self.job.export_data.open("rb") as tar_file,
BookwyrmTarFile.open(mode="r", fileobj=tar_file) as tar,
):
archive_json_file = tar.extractfile("archive.json")
data = json.load(archive_json_file)
# JSON from the archive should be what we want it to be
self.assertEqual(data, self.job.export_json)
# User avatar should be present in archive
with self.local_user.avatar.open() as expected_avatar:
archive_avatar = tar.extractfile(data["icon"]["url"])
self.assertEqual(expected_avatar.read(), archive_avatar.read())
# Edition cover should be present in archive
with self.edition.cover.open() as expected_cover:
archive_cover = tar.extractfile(
data["books"][0]["edition"]["cover"]["url"]
)
self.assertEqual(expected_cover.read(), archive_cover.read())