+ {% endif %}
+
+ {% if job.complete and fail_count and not job.retry and not legacy %}
+
-
{% trans "Failed to load" %}
- {% if not job.retry %}
-
-
-
-
- {% else %}
-
- {% endif %}
+{% if not legacy %}
+
+ {% include 'snippets/pagination.html' with page=items %}
{% endif %}
-
-
- {% if job.complete %}
-
{% trans "Successfully imported" %}
- {% else %}
-
{% trans "Import Progress" %}
- {% endif %}
-
-
{% endspaceless %}{% endblock %}
{% block scripts %}
diff --git a/bookwyrm/templates/import/manual_review.html b/bookwyrm/templates/import/manual_review.html
new file mode 100644
index 000000000..b6c2b6b26
--- /dev/null
+++ b/bookwyrm/templates/import/manual_review.html
@@ -0,0 +1,73 @@
+{% extends 'import/import_status.html' %}
+{% load i18n %}
+{% load utilities %}
+
+{% block title %}{% trans "Import Troubleshooting" %}{% endblock %}
+
+{% block page_title %}
+{% trans "Review items" %}
+{% endblock %}
+
+{% block breadcrumbs %}
+
+ {% trans "Review" %}
+
+{% endblock %}
+
+{% block actions %}
+
+
+
+ {% trans "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book." %}
+
+
+
+{% endblock %}
+
+{% block import_cols_headers %}
+{% endblock %}
+
+{% block index_col %}
+
+ {{ item.index }}
+ |
+{% endblock %}
+
+{% block import_cols %}
+{% endblock %}
+
+{% block action_row %}
+
+
+
+ {% with guess=item.book_guess %}
+
+
+ {% include 'snippets/book_titleby.html' with book=guess %}
+
+
+
+
+
+
+ {% endwith %}
+
+ |
+
+{% endblock %}
diff --git a/bookwyrm/templates/import/troubleshoot.html b/bookwyrm/templates/import/troubleshoot.html
new file mode 100644
index 000000000..d73be6d0c
--- /dev/null
+++ b/bookwyrm/templates/import/troubleshoot.html
@@ -0,0 +1,36 @@
+{% extends 'import/import_status.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Import Troubleshooting" %}{% endblock %}
+
+{% block page_title %}
+{% trans "Failed items" %}
+{% endblock %}
+
+{% block breadcrumbs %}
+
+ {% trans "Troubleshooting" %}
+
+{% endblock %}
+
+{% block actions %}
+
+
+
+ {% trans "Re-trying an import can fix missing items in cases such as:" %}
+
+
+ - {% trans "The book has been added to the instance since this import" %}
+ - {% trans "A transient error or timeout caused the external data source to be unavailable." %}
+ - {% trans "BookWyrm has been updated since this import with a bug fix" %}
+
+
+ {% trans "Contact your admin or open an issue if you are seeing unexpected failed items." %}
+
+
+
+
+{% endblock %}
diff --git a/bookwyrm/tests/activitypub/test_base_activity.py b/bookwyrm/tests/activitypub/test_base_activity.py
index 7117eb52a..b951c7ab4 100644
--- a/bookwyrm/tests/activitypub/test_base_activity.py
+++ b/bookwyrm/tests/activitypub/test_base_activity.py
@@ -146,7 +146,7 @@ class BaseActivity(TestCase):
self.user.avatar.file # pylint: disable=pointless-statement
# this would trigger a broadcast because it's a local user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
activity.to_model(model=models.User, instance=self.user)
self.assertIsNotNone(self.user.avatar.file)
self.assertEqual(self.user.name, "New Name")
@@ -154,7 +154,7 @@ class BaseActivity(TestCase):
def test_to_model_many_to_many(self, *_):
"""annoying that these all need special handling"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(
content="test status",
user=self.user,
@@ -186,7 +186,7 @@ class BaseActivity(TestCase):
def test_to_model_one_to_many(self, *_):
"""these are reversed relationships, where the secondary object
keys the primary object but not vice versa"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(
content="test status",
user=self.user,
@@ -224,7 +224,7 @@ class BaseActivity(TestCase):
@responses.activate
def test_set_related_field(self, *_):
"""celery task to add back-references to created objects"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(
content="test status",
user=self.user,
diff --git a/bookwyrm/tests/activitystreams/test_abstractstream.py b/bookwyrm/tests/activitystreams/test_abstractstream.py
index f96742865..17a1b587f 100644
--- a/bookwyrm/tests/activitystreams/test_abstractstream.py
+++ b/bookwyrm/tests/activitystreams/test_abstractstream.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from bookwyrm import activitystreams, models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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")
diff --git a/bookwyrm/tests/activitystreams/test_booksstream.py b/bookwyrm/tests/activitystreams/test_booksstream.py
index d6d94b738..347e7a942 100644
--- a/bookwyrm/tests/activitystreams/test_booksstream.py
+++ b/bookwyrm/tests/activitystreams/test_booksstream.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from bookwyrm import activitystreams, models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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")
diff --git a/bookwyrm/tests/activitystreams/test_homestream.py b/bookwyrm/tests/activitystreams/test_homestream.py
index 42a73f3cf..d48bdfbab 100644
--- a/bookwyrm/tests/activitystreams/test_homestream.py
+++ b/bookwyrm/tests/activitystreams/test_homestream.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from bookwyrm import activitystreams, models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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")
diff --git a/bookwyrm/tests/activitystreams/test_localstream.py b/bookwyrm/tests/activitystreams/test_localstream.py
index e6b05557f..fa1a67417 100644
--- a/bookwyrm/tests/activitystreams/test_localstream.py
+++ b/bookwyrm/tests/activitystreams/test_localstream.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from bookwyrm import activitystreams, models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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")
diff --git a/bookwyrm/tests/activitystreams/test_signals.py b/bookwyrm/tests/activitystreams/test_signals.py
index eb70d28e4..34aeb947c 100644
--- a/bookwyrm/tests/activitystreams/test_signals.py
+++ b/bookwyrm/tests/activitystreams/test_signals.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from bookwyrm import activitystreams, models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class ActivitystreamsSignals(TestCase):
"""using redis to build activity streams"""
@@ -53,11 +53,12 @@ class ActivitystreamsSignals(TestCase):
status = models.Status.objects.create(
user=self.remote_user, content="hi", privacy="public"
)
- with patch("bookwyrm.activitystreams.add_status_task.delay") as mock:
+ with patch("bookwyrm.activitystreams.add_status_task.apply_async") as mock:
activitystreams.add_status_on_create_command(models.Status, status, False)
self.assertEqual(mock.call_count, 1)
- args = mock.call_args[0]
- self.assertEqual(args[0], status.id)
+ args = mock.call_args[1]
+ self.assertEqual(args["args"][0], status.id)
+ self.assertEqual(args["queue"], "high_priority")
def test_populate_streams_on_account_create(self, _):
"""create streams for a user"""
diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py
index 80b0b771d..f57507632 100644
--- a/bookwyrm/tests/activitystreams/test_tasks.py
+++ b/bookwyrm/tests/activitystreams/test_tasks.py
@@ -34,7 +34,7 @@ class Activitystreams(TestCase):
)
work = models.Work.objects.create(title="test work")
self.book = models.Edition.objects.create(title="test book", parent_work=work)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.status = models.Status.objects.create(
content="hi", user=self.local_user
)
@@ -133,7 +133,7 @@ class Activitystreams(TestCase):
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_boost_to_another_timeline(self, *_):
"""boost from a non-follower doesn't remove original status from feed"""
status = models.Status.objects.create(user=self.local_user, content="hi")
@@ -155,7 +155,7 @@ class Activitystreams(TestCase):
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_boost_to_another_timeline_remote(self, *_):
"""boost from a remote non-follower doesn't remove original status from feed"""
status = models.Status.objects.create(user=self.local_user, content="hi")
@@ -177,7 +177,7 @@ class Activitystreams(TestCase):
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_boost_to_following_timeline(self, *_):
"""add a boost and deduplicate the boosted status on the timeline"""
self.local_user.following.add(self.another_user)
@@ -199,7 +199,7 @@ class Activitystreams(TestCase):
@patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores")
@patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_boost_to_same_timeline(self, *_):
"""add a boost and deduplicate the boosted status on the timeline"""
status = models.Status.objects.create(user=self.local_user, content="hi")
diff --git a/bookwyrm/tests/data/generic.csv b/bookwyrm/tests/data/generic.csv
index a081a6421..470ce7a80 100644
--- a/bookwyrm/tests/data/generic.csv
+++ b/bookwyrm/tests/data/generic.csv
@@ -1,5 +1,5 @@
-id,title,author,ISBN,rating,shelf,review,added
-38,Gideon the Ninth (The Locked Tomb #1),Tamsyn Muir,"9781250313195",,read,,2021-11-10
-48,Harrow the Ninth (The Locked Tomb #2),Tamsyn Muir,,3,read,,2021-11-10
+id,title,author,ISBN13,rating,shelf,review,added,finished
+38,Gideon the Ninth,Tamsyn Muir,"9781250313195",,read,,2021-11-10,2021-11-11
+48,Harrow the Ninth,Tamsyn Muir,,3,read,,2021-11-10
23,Subcutanean,Aaron A. Reed,,,read,,2021-11-10
-10,Patisserie at Home,Mélanie Dupuis,"9780062445315",2,read,"mixed feelings",2021-11-10
+10,Patisserie at Home,Mélanie Dupuis,"9780062445315",2,read,"mixed feelings",2021-11-10,2021-11-11
diff --git a/bookwyrm/tests/data/goodreads-rating.csv b/bookwyrm/tests/data/goodreads-rating.csv
deleted file mode 100644
index fec0c77d5..000000000
--- a/bookwyrm/tests/data/goodreads-rating.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-Book Id,Title,Author,Author l-f,Additional Authors,ISBN,ISBN13,My Rating,Average Rating,Publisher,Binding,Number of Pages,Year Published,Original Publication Year,Date Read,Date Added,Bookshelves,Bookshelves with positions,Exclusive Shelf,My Review,Spoiler,Private Notes,Read Count,Recommended For,Recommended By,Owned Copies,Original Purchase Date,Original Purchase Location,Condition,Condition Description,BCID
-42036538,Gideon the Ninth (The Locked Tomb #1),Tamsyn Muir,"Muir, Tamsyn",,"=""1250313198""","=""9781250313195""",0,4.20,Tor,Hardcover,448,2019,2019,2020/10/25,2020/10/21,,,read,,,,1,,,0,,,,,
-52691223,Subcutanean,Aaron A. Reed,"Reed, Aaron A.",,"=""""","=""""",0,4.45,,Paperback,232,2020,,2020/03/06,2020/03/05,,,read,,,,1,,,0,,,,,
-28694510,Patisserie at Home,Mélanie Dupuis,"Dupuis, Mélanie",Anne Cazor,"=""0062445316""","=""9780062445315""",2,4.60,Harper Design,Hardcover,288,2016,,,2019/07/08,,,read,,,,2,,,0,,,,,
-
diff --git a/bookwyrm/tests/data/goodreads.csv b/bookwyrm/tests/data/goodreads.csv
index 5f124edc9..a0a8232e1 100644
--- a/bookwyrm/tests/data/goodreads.csv
+++ b/bookwyrm/tests/data/goodreads.csv
@@ -1,4 +1,4 @@
Book Id,Title,Author,Author l-f,Additional Authors,ISBN,ISBN13,My Rating,Average Rating,Publisher,Binding,Number of Pages,Year Published,Original Publication Year,Date Read,Date Added,Bookshelves,Bookshelves with positions,Exclusive Shelf,My Review,Spoiler,Private Notes,Read Count,Recommended For,Recommended By,Owned Copies,Original Purchase Date,Original Purchase Location,Condition,Condition Description,BCID
-42036538,Gideon the Ninth (The Locked Tomb #1),Tamsyn Muir,"Muir, Tamsyn",,"=""1250313198""","=""9781250313195""",0,4.20,Tor,Hardcover,448,2019,2019,2020/10/25,2020/10/21,,,read,,,,1,,,0,,,,,
+42036538,Gideon the Ninth (The Locked Tomb #1),Tamsyn Muir,"Muir, Tamsyn",,"=""1250313198""","=""9781250313195""",3,4.20,Tor,Hardcover,448,2019,2019,2020/10/25,2020/10/21,,,read,,,,1,,,0,,,,,
52691223,Subcutanean,Aaron A. Reed,"Reed, Aaron A.",,"=""""","=""""",0,4.45,,Paperback,232,2020,,2020/03/06,2020/03/05,,,read,,,,1,,,0,,,,,
28694510,Patisserie at Home,Mélanie Dupuis,"Dupuis, Mélanie",Anne Cazor,"=""0062445316""","=""9780062445315""",2,4.60,Harper Design,Hardcover,288,2016,,,2019/07/08,,,read,"mixed feelings",,,2,,,0,,,,,
diff --git a/bookwyrm/tests/data/librarything.tsv b/bookwyrm/tests/data/librarything.tsv
index a707f2a9b..68bbe48e9 100644
--- a/bookwyrm/tests/data/librarything.tsv
+++ b/bookwyrm/tests/data/librarything.tsv
@@ -1,4 +1,4 @@
Book Id Title Sort Character Primary Author Primary Author Role Secondary Author Secondary Author Roles Publication Date Review Rating Comment Private Comment Summary Media Physical Description Weight Height Thickness Length Dimensions Page Count LCCN Acquired Date Started Date Read Barcode BCID Tags Collections Languages Original Languages LC Classification ISBN ISBNs Subjects Dewey Decimal Dewey Wording Other Call Number Copies Source Entry Date From Where OCLC Work id Lending Patron Lending Status Lending Start Lending End
-5498194 Marelle 1 Cortázar, Julio Gallimard (1979), Poche 1979 chef d'oeuvre 4.5 Marelle by Julio Cortázar (1979) Broché 590 p.; 7.24 inches 1.28 pounds 7.24 inches 1.26 inches 4.96 inches 7.24 x 4.96 x 1.26 inches 590 [2007-04-16] [2007-05-08] roman, espagnol, expérimental, bohème, philosophie Your library French Spanish PQ7797 .C7145 [2070291340] 2070291340, 9782070291342 Cortâazar, Julio. Rayuela 863 Literature > Spanish And Portuguese > Spanish fiction 1 Amazon.fr [2006-08-09] 57814
+5498194 Marelle 1 Cortazar, Julio Gallimard (1979), Poche 1979 chef d'oeuvre 4.5 Marelle by Julio Cortázar (1979) Broché 590 p.; 7.24 inches 1.28 pounds 7.24 inches 1.26 inches 4.96 inches 7.24 x 4.96 x 1.26 inches 590 [2007-04-16] [2007-05-08] roman, espagnol, expérimental, bohème, philosophie Your library French Spanish PQ7797 .C7145 [2070291340] 2070291340, 9782070291342 Cortâazar, Julio. Rayuela 863 Literature > Spanish And Portuguese > Spanish fiction 1 Amazon.fr [2006-08-09] 57814
5015319 Le grand incendie de Londres: Récit, avec incises et bifurcations, 1985-1987 (Fiction & Cie) 1 Roubaud, Jacques Seuil (1989), Unknown Binding 1989 5 Le grand incendie de Londres: Récit, avec incises et bifurcations, 1985-1987 (Fiction & Cie) by Jacques Roubaud (1989) Broché 411 p.; 7.72 inches 0.88 pounds 7.72 inches 1.02 inches 5.43 inches 7.72 x 5.43 x 1.02 inches 411 Your library English PQ2678 .O77 [2020104725] 2020104725, 9782020104722 Autobiographical fiction|Roubaud, Jacques > Fiction 813 American And Canadian > Fiction > Literature 1 Amazon.com [2006-07-25] 478910
5015399 Le Maître et Marguerite 1 Boulgakov, Mikhaïl Pocket (1994), Poche 1994 Le Maître et Marguerite by Mikhaïl Boulgakov (1994) Broché 579 p.; 7.09 inches 0.66 pounds 7.09 inches 1.18 inches 4.33 inches 7.09 x 4.33 x 1.18 inches 579 Your library French PG3476 .B78 [2266062328] 2266062328, 9782266062329 Allegories|Bulgakov|Good and evil > Fiction|Humanities|Jerusalem > Fiction|Jesus Christ > Fiction|Literature|Mental illness > Fiction|Moscow (Russia) > Fiction|Novel|Pilate, Pontius, 1st cent. > Fiction|Political fiction|Russia > Fiction|Russian fiction|Russian publications (Form Entry)|Soviet Union > History > 1925-1953 > Fiction|literature 891.7342 1917-1945 > 1917-1991 (USSR) > Literature > Literature of other Indo-European languages > Other Languages > Russian > Russian Fiction 1 Amazon.fr [2006-07-25] 10151
diff --git a/bookwyrm/tests/importers/test_goodreads_import.py b/bookwyrm/tests/importers/test_goodreads_import.py
index a24512921..0a421df43 100644
--- a/bookwyrm/tests/importers/test_goodreads_import.py
+++ b/bookwyrm/tests/importers/test_goodreads_import.py
@@ -1,5 +1,4 @@
""" testing import """
-import csv
import pathlib
from unittest.mock import patch
import datetime
@@ -32,7 +31,7 @@ class GoodreadsImport(TestCase):
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
- self.user = models.User.objects.create_user(
+ self.local_user = models.User.objects.create_user(
"mouse", "mouse@mouse.mouse", "password", local=True
)
@@ -45,12 +44,17 @@ class GoodreadsImport(TestCase):
def test_create_job(self, *_):
"""creates the import job entry and checks csv"""
- import_job = self.importer.create_job(self.user, self.csv, False, "public")
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
import_items = models.ImportItem.objects.filter(job=import_job).all()
self.assertEqual(len(import_items), 3)
self.assertEqual(import_items[0].index, 0)
self.assertEqual(import_items[0].data["Book Id"], "42036538")
+ self.assertEqual(import_items[0].normalized_data["isbn_13"], '="9781250313195"')
+ self.assertEqual(import_items[0].normalized_data["isbn_10"], '="1250313198"')
+
self.assertEqual(import_items[1].index, 1)
self.assertEqual(import_items[1].data["Book Id"], "52691223")
self.assertEqual(import_items[2].index, 2)
@@ -58,12 +62,16 @@ class GoodreadsImport(TestCase):
def test_create_retry_job(self, *_):
"""trying again with items that didn't import"""
- import_job = self.importer.create_job(self.user, self.csv, False, "unlisted")
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "unlisted"
+ )
import_items = models.ImportItem.objects.filter(job=import_job).all()[:2]
- retry = self.importer.create_retry_job(self.user, import_job, import_items)
+ retry = self.importer.create_retry_job(
+ self.local_user, import_job, import_items
+ )
self.assertNotEqual(import_job, retry)
- self.assertEqual(retry.user, self.user)
+ self.assertEqual(retry.user, self.local_user)
self.assertEqual(retry.include_reviews, False)
self.assertEqual(retry.privacy, "unlisted")
@@ -76,23 +84,18 @@ class GoodreadsImport(TestCase):
def test_handle_imported_book(self, *_):
"""goodreads import added a book, this adds related connections"""
- shelf = self.user.shelf_set.filter(identifier="read").first()
+ shelf = self.local_user.shelf_set.filter(identifier="read").first()
self.assertIsNone(shelf.books.first())
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- for index, entry in enumerate(list(csv.DictReader(csv_file))):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
@@ -100,7 +103,7 @@ class GoodreadsImport(TestCase):
shelf.shelfbook_set.first().shelved_date, make_date(2020, 10, 21)
)
- readthrough = models.ReadThrough.objects.get(user=self.user)
+ readthrough = models.ReadThrough.objects.get(user=self.local_user)
self.assertEqual(readthrough.book, self.book)
self.assertEqual(readthrough.start_date, make_date(2020, 10, 21))
self.assertEqual(readthrough.finish_date, make_date(2020, 10, 25))
@@ -108,20 +111,17 @@ class GoodreadsImport(TestCase):
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_review(self, *_):
"""goodreads review import"""
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[2]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.get(index=2)
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, True, "unlisted"
- )
- review = models.Review.objects.get(book=self.book, user=self.user)
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+
+ review = models.Review.objects.get(book=self.book, user=self.local_user)
self.assertEqual(review.content, "mixed feelings")
self.assertEqual(review.rating, 2)
self.assertEqual(review.published_date, make_date(2019, 7, 8))
@@ -130,23 +130,18 @@ class GoodreadsImport(TestCase):
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_rating(self, *_):
"""goodreads rating import"""
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath(
- "../data/goodreads-rating.csv"
- )
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[2]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.filter(index=0).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, True, "unlisted"
- )
- review = models.ReviewRating.objects.get(book=self.book, user=self.user)
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+
+ review = models.ReviewRating.objects.get(book=self.book, user=self.local_user)
self.assertIsInstance(review, models.ReviewRating)
- self.assertEqual(review.rating, 2)
- self.assertEqual(review.published_date, make_date(2019, 7, 8))
+ self.assertEqual(review.rating, 3)
+ self.assertEqual(review.published_date, make_date(2020, 10, 25))
self.assertEqual(review.privacy, "unlisted")
diff --git a/bookwyrm/tests/importers/test_importer.py b/bookwyrm/tests/importers/test_importer.py
index f5d9af302..5c3b20310 100644
--- a/bookwyrm/tests/importers/test_importer.py
+++ b/bookwyrm/tests/importers/test_importer.py
@@ -1,6 +1,4 @@
""" testing import """
-from collections import namedtuple
-import csv
import pathlib
from unittest.mock import patch
import datetime
@@ -11,7 +9,8 @@ import responses
from bookwyrm import models
from bookwyrm.importers import Importer
-from bookwyrm.importers.importer import import_data, handle_imported_book
+from bookwyrm.importers.importer import start_import_task, import_item_task
+from bookwyrm.importers.importer import handle_imported_book
def make_date(*args):
@@ -29,26 +28,7 @@ class GenericImporter(TestCase):
def setUp(self):
"""use a test csv"""
- class TestImporter(Importer):
- """basic importer"""
-
- mandatory_fields = ["title", "author"]
-
- def parse_fields(self, entry):
- return {
- "id": entry["id"],
- "Title": entry["title"],
- "Author": entry["author"],
- "ISBN13": entry["ISBN"],
- "Star Rating": entry["rating"],
- "My Rating": entry["rating"],
- "My Review": entry["review"],
- "Exclusive Shelf": entry["shelf"],
- "Date Added": entry["added"],
- "Date Read": None,
- }
-
- self.importer = TestImporter()
+ self.importer = Importer()
datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
self.csv = open(datafile, "r", encoding=self.importer.encoding)
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
@@ -77,13 +57,24 @@ class GenericImporter(TestCase):
import_items = models.ImportItem.objects.filter(job=import_job).all()
self.assertEqual(len(import_items), 4)
self.assertEqual(import_items[0].index, 0)
- self.assertEqual(import_items[0].data["id"], "38")
+ self.assertEqual(import_items[0].normalized_data["id"], "38")
+ self.assertEqual(import_items[0].normalized_data["title"], "Gideon the Ninth")
+ self.assertEqual(import_items[0].normalized_data["authors"], "Tamsyn Muir")
+ self.assertEqual(import_items[0].normalized_data["isbn_13"], "9781250313195")
+ self.assertIsNone(import_items[0].normalized_data["isbn_10"])
+ self.assertEqual(import_items[0].normalized_data["shelf"], "read")
+
self.assertEqual(import_items[1].index, 1)
- self.assertEqual(import_items[1].data["id"], "48")
+ self.assertEqual(import_items[1].normalized_data["id"], "48")
+ self.assertEqual(import_items[1].normalized_data["title"], "Harrow the Ninth")
+
self.assertEqual(import_items[2].index, 2)
- self.assertEqual(import_items[2].data["id"], "23")
+ self.assertEqual(import_items[2].normalized_data["id"], "23")
+ self.assertEqual(import_items[2].normalized_data["title"], "Subcutanean")
+
self.assertEqual(import_items[3].index, 3)
- self.assertEqual(import_items[3].data["id"], "10")
+ self.assertEqual(import_items[3].normalized_data["id"], "10")
+ self.assertEqual(import_items[3].normalized_data["title"], "Patisserie at Home")
def test_create_retry_job(self, *_):
"""trying again with items that didn't import"""
@@ -103,67 +94,105 @@ class GenericImporter(TestCase):
retry_items = models.ImportItem.objects.filter(job=retry).all()
self.assertEqual(len(retry_items), 2)
self.assertEqual(retry_items[0].index, 0)
- self.assertEqual(retry_items[0].data["id"], "38")
+ self.assertEqual(retry_items[0].normalized_data["id"], "38")
self.assertEqual(retry_items[1].index, 1)
- self.assertEqual(retry_items[1].data["id"], "48")
+ self.assertEqual(retry_items[1].normalized_data["id"], "48")
def test_start_import(self, *_):
"""check that a task was created"""
import_job = self.importer.create_job(
self.local_user, self.csv, False, "unlisted"
)
- MockTask = namedtuple("Task", ("id"))
- mock_task = MockTask(7)
- with patch("bookwyrm.importers.importer.import_data.delay") as start:
- start.return_value = mock_task
+ with patch("bookwyrm.importers.importer.start_import_task.delay") as mock:
self.importer.start_import(import_job)
- import_job.refresh_from_db()
- self.assertEqual(import_job.task_id, "7")
+ self.assertEqual(mock.call_count, 1)
@responses.activate
- def test_import_data(self, *_):
+ def test_start_import_task(self, *_):
"""resolve entry"""
import_job = self.importer.create_job(
self.local_user, self.csv, False, "unlisted"
)
- book = models.Edition.objects.create(title="Test Book")
+ with patch("bookwyrm.importers.importer.import_item_task.delay") as mock:
+ start_import_task(import_job.id)
+
+ self.assertEqual(mock.call_count, 4)
+
+ @responses.activate
+ def test_import_item_task(self, *_):
+ """resolve entry"""
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "unlisted"
+ )
+
+ import_item = models.ImportItem.objects.get(job=import_job, index=0)
with patch(
"bookwyrm.models.import_job.ImportItem.get_book_from_isbn"
) as resolve:
- resolve.return_value = book
- with patch("bookwyrm.importers.importer.handle_imported_book"):
- import_data(self.importer.service, import_job.id)
+ resolve.return_value = self.book
- import_item = models.ImportItem.objects.get(job=import_job, index=0)
- self.assertEqual(import_item.book.id, book.id)
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
+ import_item_task(import_item.id)
+ kwargs = mock.call_args.kwargs
+ self.assertEqual(kwargs["queue"], "low_priority")
+ import_item.refresh_from_db()
+
+ def test_complete_job(self, *_):
+ """test notification"""
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "unlisted"
+ )
+ items = import_job.items.all()
+ for item in items[:3]:
+ item.fail_reason = "hello"
+ item.save()
+ item.update_job()
+ self.assertFalse(
+ models.Notification.objects.filter(
+ user=self.local_user,
+ related_import=import_job,
+ notification_type="IMPORT",
+ ).exists()
+ )
+
+ item = items[3]
+ item.fail_reason = "hello"
+ item.save()
+ item.update_job()
+ import_job.refresh_from_db()
+ self.assertTrue(import_job.complete)
+ self.assertTrue(
+ models.Notification.objects.filter(
+ user=self.local_user,
+ related_import=import_job,
+ notification_type="IMPORT",
+ ).exists()
+ )
def test_handle_imported_book(self, *_):
"""import added a book, this adds related connections"""
shelf = self.local_user.shelf_set.filter(identifier="read").first()
self.assertIsNone(shelf.books.first())
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- for index, entry in enumerate(list(csv.DictReader(csv_file))):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.local_user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
def test_handle_imported_book_already_shelved(self, *_):
"""import added a book, this adds related connections"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
shelf = self.local_user.shelf_set.filter(identifier="to-read").first()
models.ShelfBook.objects.create(
shelf=shelf,
@@ -172,20 +201,15 @@ class GenericImporter(TestCase):
shelved_date=make_date(2020, 2, 2),
)
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- for index, entry in enumerate(list(csv.DictReader(csv_file))):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.local_user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
@@ -199,48 +223,34 @@ class GenericImporter(TestCase):
def test_handle_import_twice(self, *_):
"""re-importing books"""
shelf = self.local_user.shelf_set.filter(identifier="read").first()
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- for index, entry in enumerate(list(csv.DictReader(csv_file))):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.local_user, import_item, False, "public"
- )
- handle_imported_book(
- self.importer.service, self.local_user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
+ self.assertEqual(models.ReadThrough.objects.count(), 1)
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_review(self, *_):
"""review import"""
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[3]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.filter(index=3).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
with patch("bookwyrm.models.Status.broadcast") as broadcast_mock:
- handle_imported_book(
- self.importer.service,
- self.local_user,
- import_item,
- True,
- "unlisted",
- )
+ handle_imported_book(import_item)
kwargs = broadcast_mock.call_args.kwargs
self.assertEqual(kwargs["software"], "bookwyrm")
review = models.Review.objects.get(book=self.book, user=self.local_user)
@@ -248,42 +258,89 @@ class GenericImporter(TestCase):
self.assertEqual(review.rating, 2.0)
self.assertEqual(review.privacy, "unlisted")
+ import_item.refresh_from_db()
+ self.assertEqual(import_item.linked_review, review)
+
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_rating(self, *_):
"""rating import"""
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[1]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.filter(index=1).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.local_user, import_item, True, "unlisted"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
review = models.ReviewRating.objects.get(book=self.book, user=self.local_user)
self.assertIsInstance(review, models.ReviewRating)
self.assertEqual(review.rating, 3.0)
self.assertEqual(review.privacy, "unlisted")
+ import_item.refresh_from_db()
+ self.assertEqual(import_item.linked_review.id, review.id)
+
+ @patch("bookwyrm.activitystreams.add_status_task.delay")
+ def test_handle_imported_book_rating_duplicate_with_link(self, *_):
+ """rating import twice"""
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
+ )
+ import_item = import_job.items.filter(index=1).first()
+ import_item.book = self.book
+ import_item.save()
+
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+ handle_imported_book(import_item)
+
+ review = models.ReviewRating.objects.get(book=self.book, user=self.local_user)
+ self.assertIsInstance(review, models.ReviewRating)
+ self.assertEqual(review.rating, 3.0)
+ self.assertEqual(review.privacy, "unlisted")
+
+ import_item.refresh_from_db()
+ self.assertEqual(import_item.linked_review.id, review.id)
+
+ @patch("bookwyrm.activitystreams.add_status_task.delay")
+ def test_handle_imported_book_rating_duplicate_without_link(self, *_):
+ """rating import twice"""
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
+ )
+ import_item = import_job.items.filter(index=1).first()
+ import_item.book = self.book
+ import_item.save()
+
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+ import_item.refresh_from_db()
+ import_item.linked_review = None
+ import_item.save()
+
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+
+ review = models.ReviewRating.objects.get(book=self.book, user=self.local_user)
+ self.assertIsInstance(review, models.ReviewRating)
+ self.assertEqual(review.rating, 3.0)
+ self.assertEqual(review.privacy, "unlisted")
+
+ import_item.refresh_from_db()
+ self.assertEqual(import_item.linked_review.id, review.id)
+
def test_handle_imported_book_reviews_disabled(self, *_):
"""review import"""
- import_job = models.ImportJob.objects.create(user=self.local_user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[2]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "unlisted"
)
+ import_item = import_job.items.filter(index=3).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.local_user, import_item, False, "unlisted"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
self.assertFalse(
models.Review.objects.filter(book=self.book, user=self.local_user).exists()
)
diff --git a/bookwyrm/tests/importers/test_librarything_import.py b/bookwyrm/tests/importers/test_librarything_import.py
index f76666a78..49354b368 100644
--- a/bookwyrm/tests/importers/test_librarything_import.py
+++ b/bookwyrm/tests/importers/test_librarything_import.py
@@ -1,16 +1,14 @@
""" testing import """
-import csv
import pathlib
from unittest.mock import patch
import datetime
import pytz
from django.test import TestCase
-import responses
from bookwyrm import models
from bookwyrm.importers import LibrarythingImporter
-from bookwyrm.importers.importer import import_data, handle_imported_book
+from bookwyrm.importers.importer import handle_imported_book
def make_date(*args):
@@ -35,7 +33,7 @@ class LibrarythingImport(TestCase):
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
- self.user = models.User.objects.create_user(
+ self.local_user = models.User.objects.create_user(
"mmai", "mmai@mmai.mmai", "password", local=True
)
work = models.Work.objects.create(title="Test Work")
@@ -47,8 +45,10 @@ class LibrarythingImport(TestCase):
def test_create_job(self, *_):
"""creates the import job entry and checks csv"""
- import_job = self.importer.create_job(self.user, self.csv, False, "public")
- self.assertEqual(import_job.user, self.user)
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ self.assertEqual(import_job.user, self.local_user)
self.assertEqual(import_job.include_reviews, False)
self.assertEqual(import_job.privacy, "public")
@@ -56,6 +56,14 @@ class LibrarythingImport(TestCase):
self.assertEqual(len(import_items), 3)
self.assertEqual(import_items[0].index, 0)
self.assertEqual(import_items[0].data["Book Id"], "5498194")
+ self.assertEqual(import_items[0].normalized_data["isbn_13"], "9782070291342")
+ self.assertEqual(import_items[0].normalized_data["isbn_10"], "2070291340")
+ self.assertEqual(import_items[0].normalized_data["title"], "Marelle")
+ self.assertEqual(import_items[0].normalized_data["authors"], "Cortazar, Julio")
+ self.assertEqual(import_items[0].normalized_data["date_added"], "2006-08-09")
+ self.assertEqual(import_items[0].normalized_data["date_started"], "2007-04-16")
+ self.assertEqual(import_items[0].normalized_data["date_finished"], "2007-05-08")
+
self.assertEqual(import_items[1].index, 1)
self.assertEqual(import_items[1].data["Book Id"], "5015319")
self.assertEqual(import_items[2].index, 2)
@@ -63,12 +71,16 @@ class LibrarythingImport(TestCase):
def test_create_retry_job(self, *_):
"""trying again with items that didn't import"""
- import_job = self.importer.create_job(self.user, self.csv, False, "unlisted")
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "unlisted"
+ )
import_items = models.ImportItem.objects.filter(job=import_job).all()[:2]
- retry = self.importer.create_retry_job(self.user, import_job, import_items)
+ retry = self.importer.create_retry_job(
+ self.local_user, import_job, import_items
+ )
self.assertNotEqual(import_job, retry)
- self.assertEqual(retry.user, self.user)
+ self.assertEqual(retry.user, self.local_user)
self.assertEqual(retry.include_reviews, False)
self.assertEqual(retry.privacy, "unlisted")
@@ -79,80 +91,54 @@ class LibrarythingImport(TestCase):
self.assertEqual(retry_items[1].index, 1)
self.assertEqual(retry_items[1].data["Book Id"], "5015319")
- @responses.activate
- def test_import_data(self, *_):
- """resolve entry"""
- import_job = self.importer.create_job(self.user, self.csv, False, "unlisted")
- book = models.Edition.objects.create(title="Test Book")
-
- with patch(
- "bookwyrm.models.import_job.ImportItem.get_book_from_isbn"
- ) as resolve:
- resolve.return_value = book
- with patch("bookwyrm.importers.importer.handle_imported_book"):
- import_data(self.importer.service, import_job.id)
-
- import_item = models.ImportItem.objects.get(job=import_job, index=0)
- self.assertEqual(import_item.book.id, book.id)
-
def test_handle_imported_book(self, *_):
"""librarything import added a book, this adds related connections"""
- shelf = self.user.shelf_set.filter(identifier="read").first()
+ shelf = self.local_user.shelf_set.filter(identifier="read").first()
self.assertIsNone(shelf.books.first())
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/librarything.tsv")
- csv_file = open(datafile, "r", encoding=self.importer.encoding)
- for index, entry in enumerate(
- list(csv.DictReader(csv_file, delimiter=self.importer.delimiter))
- ):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
- readthrough = models.ReadThrough.objects.get(user=self.user)
+ readthrough = models.ReadThrough.objects.get(user=self.local_user)
self.assertEqual(readthrough.book, self.book)
self.assertEqual(readthrough.start_date, make_date(2007, 4, 16))
self.assertEqual(readthrough.finish_date, make_date(2007, 5, 8))
def test_handle_imported_book_already_shelved(self, *_):
"""librarything import added a book, this adds related connections"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- shelf = self.user.shelf_set.filter(identifier="to-read").first()
- models.ShelfBook.objects.create(shelf=shelf, user=self.user, book=self.book)
-
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/librarything.tsv")
- csv_file = open(datafile, "r", encoding=self.importer.encoding)
- for index, entry in enumerate(
- list(csv.DictReader(csv_file, delimiter=self.importer.delimiter))
- ):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ shelf = self.local_user.shelf_set.filter(identifier="to-read").first()
+ models.ShelfBook.objects.create(
+ shelf=shelf, user=self.local_user, book=self.book
)
- break
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, False, "public"
- )
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
+
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
- self.assertIsNone(self.user.shelf_set.get(identifier="read").books.first())
+ self.assertIsNone(
+ self.local_user.shelf_set.get(identifier="read").books.first()
+ )
- readthrough = models.ReadThrough.objects.get(user=self.user)
+ readthrough = models.ReadThrough.objects.get(user=self.local_user)
self.assertEqual(readthrough.book, self.book)
self.assertEqual(readthrough.start_date, make_date(2007, 4, 16))
self.assertEqual(readthrough.finish_date, make_date(2007, 5, 8))
@@ -160,21 +146,18 @@ class LibrarythingImport(TestCase):
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_review(self, *_):
"""librarything review import"""
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/librarything.tsv")
- csv_file = open(datafile, "r", encoding=self.importer.encoding)
- entry = list(csv.DictReader(csv_file, delimiter=self.importer.delimiter))[0]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.filter(index=0).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, True, "unlisted"
- )
- review = models.Review.objects.get(book=self.book, user=self.user)
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+
+ review = models.Review.objects.get(book=self.book, user=self.local_user)
self.assertEqual(review.content, "chef d'oeuvre")
- self.assertEqual(review.rating, 5)
+ self.assertEqual(review.rating, 4.5)
self.assertEqual(review.published_date, make_date(2007, 5, 8))
self.assertEqual(review.privacy, "unlisted")
diff --git a/bookwyrm/tests/importers/test_storygraph_import.py b/bookwyrm/tests/importers/test_storygraph_import.py
index addf362cb..09cf32dc1 100644
--- a/bookwyrm/tests/importers/test_storygraph_import.py
+++ b/bookwyrm/tests/importers/test_storygraph_import.py
@@ -1,5 +1,4 @@
""" testing import """
-import csv
import pathlib
from unittest.mock import patch
import datetime
@@ -32,7 +31,7 @@ class StorygraphImport(TestCase):
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
- self.user = models.User.objects.create_user(
+ self.local_user = models.User.objects.create_user(
"mouse", "mouse@mouse.mouse", "password", local=True
)
@@ -45,53 +44,34 @@ class StorygraphImport(TestCase):
def test_create_job(self, *_):
"""creates the import job entry and checks csv"""
- import_job = self.importer.create_job(self.user, self.csv, False, "public")
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
import_items = models.ImportItem.objects.filter(job=import_job).all()
self.assertEqual(len(import_items), 2)
self.assertEqual(import_items[0].index, 0)
- self.assertEqual(import_items[0].data["Title"], "Always Coming Home")
+ self.assertEqual(import_items[0].normalized_data["title"], "Always Coming Home")
self.assertEqual(import_items[1].index, 1)
- self.assertEqual(import_items[1].data["Title"], "Subprime Attention Crisis")
- self.assertEqual(import_items[1].data["My Rating"], 5.0)
-
- def test_create_retry_job(self, *_):
- """trying again with items that didn't import"""
- import_job = self.importer.create_job(self.user, self.csv, False, "unlisted")
- import_items = models.ImportItem.objects.filter(job=import_job).all()[:2]
-
- retry = self.importer.create_retry_job(self.user, import_job, import_items)
- self.assertNotEqual(import_job, retry)
- self.assertEqual(retry.user, self.user)
- self.assertEqual(retry.include_reviews, False)
- self.assertEqual(retry.privacy, "unlisted")
-
- retry_items = models.ImportItem.objects.filter(job=retry).all()
- self.assertEqual(len(retry_items), 2)
- self.assertEqual(retry_items[0].index, 0)
- self.assertEqual(retry_items[0].data["Title"], "Always Coming Home")
- self.assertEqual(retry_items[1].index, 1)
- self.assertEqual(retry_items[1].data["Title"], "Subprime Attention Crisis")
+ self.assertEqual(
+ import_items[1].normalized_data["title"], "Subprime Attention Crisis"
+ )
+ self.assertEqual(import_items[1].normalized_data["rating"], "5.0")
def test_handle_imported_book(self, *_):
"""storygraph import added a book, this adds related connections"""
- shelf = self.user.shelf_set.filter(identifier="to-read").first()
+ shelf = self.local_user.shelf_set.filter(identifier="to-read").first()
self.assertIsNone(shelf.books.first())
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/storygraph.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- for index, entry in enumerate(list(csv.DictReader(csv_file))):
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=index, data=entry, book=self.book
- )
- break
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, False, "public"
+ )
+ import_item = import_job.items.first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, False, "public"
- )
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book)
@@ -102,20 +82,17 @@ class StorygraphImport(TestCase):
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_handle_imported_book_rating(self, *_):
"""storygraph rating import"""
- import_job = models.ImportJob.objects.create(user=self.user)
- datafile = pathlib.Path(__file__).parent.joinpath("../data/storygraph.csv")
- csv_file = open(datafile, "r") # pylint: disable=unspecified-encoding
- entry = list(csv.DictReader(csv_file))[1]
- entry = self.importer.parse_fields(entry)
- import_item = models.ImportItem.objects.create(
- job_id=import_job.id, index=0, data=entry, book=self.book
+ import_job = self.importer.create_job(
+ self.local_user, self.csv, True, "unlisted"
)
+ import_item = import_job.items.filter(index=1).first()
+ import_item.book = self.book
+ import_item.save()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
- handle_imported_book(
- self.importer.service, self.user, import_item, True, "unlisted"
- )
- review = models.ReviewRating.objects.get(book=self.book, user=self.user)
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
+ handle_imported_book(import_item)
+
+ review = models.ReviewRating.objects.get(book=self.book, user=self.local_user)
self.assertIsInstance(review, models.ReviewRating)
self.assertEqual(review.rating, 5.0)
self.assertEqual(review.published_date, make_date(2021, 5, 10))
diff --git a/bookwyrm/tests/management/test_populate_streams.py b/bookwyrm/tests/management/test_populate_streams.py
index ca21b0ee8..5be1774da 100644
--- a/bookwyrm/tests/management/test_populate_streams.py
+++ b/bookwyrm/tests/management/test_populate_streams.py
@@ -6,7 +6,7 @@ from bookwyrm import models
from bookwyrm.management.commands.populate_streams import populate_streams
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class Activitystreams(TestCase):
"""using redis to build activity streams"""
diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py
index 911cca5cc..91a1fe7c8 100644
--- a/bookwyrm/tests/models/test_activitypub_mixin.py
+++ b/bookwyrm/tests/models/test_activitypub_mixin.py
@@ -21,7 +21,7 @@ from bookwyrm.settings import PAGE_LENGTH
# pylint: disable=invalid-name
@patch("bookwyrm.activitystreams.add_status_task.delay")
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class ActivitypubMixins(TestCase):
"""functionality shared across models"""
diff --git a/bookwyrm/tests/models/test_group.py b/bookwyrm/tests/models/test_group.py
index 33341d192..2dd3cee18 100644
--- a/bookwyrm/tests/models/test_group.py
+++ b/bookwyrm/tests/models/test_group.py
@@ -5,7 +5,7 @@ from django.test import TestCase
from bookwyrm import models, settings
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class Group(TestCase):
"""some activitypub oddness ahead"""
@@ -87,7 +87,7 @@ class Group(TestCase):
def test_group_members_can_see_followers_only_lists(self, _):
"""follower-only group booklists should not be excluded from group booklist listing for group members who do not follower list owner"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
followers_list = models.List.objects.create(
name="Followers List",
curation="group",
@@ -107,7 +107,7 @@ class Group(TestCase):
def test_group_members_can_see_private_lists(self, _):
"""private group booklists should not be excluded from group booklist listing for group members"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
private_list = models.List.objects.create(
name="Private List",
diff --git a/bookwyrm/tests/models/test_import_model.py b/bookwyrm/tests/models/test_import_model.py
index 0e5d6760a..f48143d0d 100644
--- a/bookwyrm/tests/models/test_import_model.py
+++ b/bookwyrm/tests/models/test_import_model.py
@@ -18,83 +18,68 @@ class ImportJob(TestCase):
def setUp(self):
"""data is from a goodreads export of The Raven Tower"""
- read_data = {
- "Book Id": 39395857,
- "Title": "The Raven Tower",
- "Author": "Ann Leckie",
- "Author l-f": "Leckie, Ann",
- "Additional Authors": "",
- "ISBN": '="0356506991"',
- "ISBN13": '="9780356506999"',
- "My Rating": 0,
- "Average Rating": 4.06,
- "Publisher": "Orbit",
- "Binding": "Hardcover",
- "Number of Pages": 416,
- "Year Published": 2019,
- "Original Publication Year": 2019,
- "Date Read": "2019/04/12",
- "Date Added": "2019/04/09",
- "Bookshelves": "",
- "Bookshelves with positions": "",
- "Exclusive Shelf": "read",
- "My Review": "",
- "Spoiler": "",
- "Private Notes": "",
- "Read Count": 1,
- "Recommended For": "",
- "Recommended By": "",
- "Owned Copies": 0,
- "Original Purchase Date": "",
- "Original Purchase Location": "",
- "Condition": "",
- "Condition Description": "",
- "BCID": "",
- }
- currently_reading_data = read_data.copy()
- currently_reading_data["Exclusive Shelf"] = "currently-reading"
- currently_reading_data["Date Read"] = ""
-
- unknown_read_data = currently_reading_data.copy()
- unknown_read_data["Exclusive Shelf"] = "read"
- unknown_read_data["Date Read"] = ""
-
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
"bookwyrm.activitystreams.populate_stream_task.delay"
):
- user = models.User.objects.create_user(
- "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
+ self.local_user = models.User.objects.create_user(
+ "mouse", "mouse@mouse.mouse", "password", local=True
)
- job = models.ImportJob.objects.create(user=user)
- self.item_1 = models.ImportItem.objects.create(
- job=job, index=1, data=currently_reading_data
- )
- self.item_2 = models.ImportItem.objects.create(job=job, index=2, data=read_data)
- self.item_3 = models.ImportItem.objects.create(
- job=job, index=3, data=unknown_read_data
- )
+ self.job = models.ImportJob.objects.create(user=self.local_user, mappings={})
def test_isbn(self):
"""it unquotes the isbn13 field from data"""
- expected = "9780356506999"
- item = models.ImportItem.objects.get(index=1)
- self.assertEqual(item.isbn, expected)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ },
+ )
+ self.assertEqual(item.isbn, "9780356506999")
def test_shelf(self):
"""converts to the local shelf typology"""
- expected = "reading"
- self.assertEqual(self.item_1.shelf, expected)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ },
+ )
+ self.assertEqual(item.shelf, "reading")
def test_date_added(self):
"""converts to the local shelf typology"""
expected = datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
- item = models.ImportItem.objects.get(index=1)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ "date_added": "2019/04/09",
+ },
+ )
self.assertEqual(item.date_added, expected)
def test_date_read(self):
"""converts to the local shelf typology"""
expected = datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc)
- item = models.ImportItem.objects.get(index=2)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ "date_added": "2019/04/09",
+ "date_finished": "2019/04/12",
+ },
+ )
self.assertEqual(item.date_read, expected)
def test_currently_reading_reads(self):
@@ -104,31 +89,66 @@ class ImportJob(TestCase):
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
)
]
- actual = models.ImportItem.objects.get(index=1)
- self.assertEqual(actual.reads[0].start_date, expected[0].start_date)
- self.assertEqual(actual.reads[0].finish_date, expected[0].finish_date)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ "date_added": "2019/04/09",
+ },
+ )
+ self.assertEqual(item.reads[0].start_date, expected[0].start_date)
+ self.assertIsNone(item.reads[0].finish_date)
def test_read_reads(self):
"""infer read dates where available"""
- actual = self.item_2
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ "date_added": "2019/04/09",
+ "date_finished": "2019/04/12",
+ },
+ )
self.assertEqual(
- actual.reads[0].start_date,
+ item.reads[0].start_date,
datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc),
)
self.assertEqual(
- actual.reads[0].finish_date,
+ item.reads[0].finish_date,
datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc),
)
def test_unread_reads(self):
"""handle books with no read dates"""
expected = []
- actual = models.ImportItem.objects.get(index=3)
- self.assertEqual(actual.reads, expected)
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ "shelf": "reading",
+ },
+ )
+ self.assertEqual(item.reads, expected)
@responses.activate
def test_get_book_from_isbn(self):
"""search and load books by isbn (9780356506999)"""
+ item = models.ImportItem.objects.create(
+ index=1,
+ job=self.job,
+ data={},
+ normalized_data={
+ "isbn_13": '="9780356506999"',
+ },
+ )
connector_info = models.Connector.objects.create(
identifier="openlibrary.org",
name="OpenLibrary",
@@ -177,6 +197,6 @@ class ImportJob(TestCase):
with patch(
"bookwyrm.connectors.openlibrary.Connector." "get_authors_from_data"
):
- book = self.item_1.get_book_from_isbn()
+ book = item.get_book_from_isbn()
self.assertEqual(book.title, "Sabriel")
diff --git a/bookwyrm/tests/models/test_list.py b/bookwyrm/tests/models/test_list.py
index 0d749453e..254005bc3 100644
--- a/bookwyrm/tests/models/test_list.py
+++ b/bookwyrm/tests/models/test_list.py
@@ -5,7 +5,7 @@ from django.test import TestCase
from bookwyrm import models, settings
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class List(TestCase):
"""some activitypub oddness ahead"""
@@ -22,7 +22,7 @@ class List(TestCase):
def test_remote_id(self, _):
"""shelves use custom remote ids"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
book_list = models.List.objects.create(
name="Test List", user=self.local_user
)
@@ -31,7 +31,7 @@ class List(TestCase):
def test_to_activity(self, _):
"""jsonify it"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
book_list = models.List.objects.create(
name="Test List", user=self.local_user
)
@@ -45,7 +45,7 @@ class List(TestCase):
def test_list_item(self, _):
"""a list entry"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
book_list = models.List.objects.create(
name="Test List", user=self.local_user, privacy="unlisted"
)
@@ -63,7 +63,7 @@ class List(TestCase):
def test_list_item_pending(self, _):
"""a list entry"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
book_list = models.List.objects.create(
name="Test List", user=self.local_user
)
diff --git a/bookwyrm/tests/models/test_relationship_models.py b/bookwyrm/tests/models/test_relationship_models.py
index 04dbe1a33..2b388398c 100644
--- a/bookwyrm/tests/models/test_relationship_models.py
+++ b/bookwyrm/tests/models/test_relationship_models.py
@@ -33,11 +33,13 @@ class Relationship(TestCase):
def test_user_follows_from_request(self, _):
"""convert a follow request into a follow"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
request = models.UserFollowRequest.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
- activity = json.loads(mock.call_args[0][1])
+ 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
@@ -54,7 +56,7 @@ class Relationship(TestCase):
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.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
request = models.UserFollowRequest.objects.create(
user_subject=self.local_user,
user_object=self.remote_user,
@@ -69,19 +71,19 @@ class Relationship(TestCase):
self.assertEqual(rel.user_subject, self.local_user)
self.assertEqual(rel.user_object, self.remote_user)
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
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,
user_object=self.remote_user,
)
- activity = json.loads(broadcast_mock.call_args[0][1])
+ activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"], self.remote_user.remote_id)
self.assertEqual(activity["type"], "Follow")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_follow_request_accept(self, broadcast_mock, _):
"""accept a request and make it a relationship"""
self.local_user.manually_approves_followers = True
@@ -96,7 +98,7 @@ class Relationship(TestCase):
)
request.accept()
- activity = json.loads(broadcast_mock.call_args[0][1])
+ activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Accept")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], "https://www.hi.com/")
@@ -107,7 +109,7 @@ class Relationship(TestCase):
self.assertEqual(rel.user_subject, self.remote_user)
self.assertEqual(rel.user_object, self.local_user)
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_follow_request_reject(self, broadcast_mock, _):
"""accept a request and make it a relationship"""
self.local_user.manually_approves_followers = True
@@ -120,7 +122,7 @@ class Relationship(TestCase):
)
request.reject()
- activity = json.loads(broadcast_mock.call_args[0][1])
+ activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Reject")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], request.remote_id)
diff --git a/bookwyrm/tests/models/test_shelf_model.py b/bookwyrm/tests/models/test_shelf_model.py
index fe179e883..0683fbeff 100644
--- a/bookwyrm/tests/models/test_shelf_model.py
+++ b/bookwyrm/tests/models/test_shelf_model.py
@@ -27,7 +27,7 @@ class Shelf(TestCase):
def test_remote_id(self, *_):
"""shelves use custom remote ids"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
@@ -36,7 +36,7 @@ class Shelf(TestCase):
def test_to_activity(self, *_):
"""jsonify it"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
@@ -51,19 +51,23 @@ class Shelf(TestCase):
def test_create_update_shelf(self, *_):
"""create and broadcast shelf creation"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Create")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["name"], "Test Shelf")
shelf.name = "arthur russel"
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
shelf.save()
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Update")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["name"], "arthur russel")
@@ -71,27 +75,31 @@ class Shelf(TestCase):
def test_shelve(self, *_):
"""create and broadcast shelf creation"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
shelf_book = models.ShelfBook.objects.create(
shelf=shelf, user=self.local_user, book=self.book
)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], shelf_book.remote_id)
self.assertEqual(activity["target"], shelf.remote_id)
self.assertEqual(shelf.books.first(), self.book)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
shelf_book.delete()
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Remove")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], shelf_book.remote_id)
diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py
index 7d0dd138b..822d837a7 100644
--- a/bookwyrm/tests/models/test_status_model.py
+++ b/bookwyrm/tests/models/test_status_model.py
@@ -362,19 +362,15 @@ class Status(TestCase):
def test_favorite(self, *_):
"""fav a status"""
- real_broadcast = models.Favorite.broadcast
-
- def fav_broadcast_mock(_, activity, user):
- """ok"""
- self.assertEqual(user.remote_id, self.local_user.remote_id)
- self.assertEqual(activity["type"], "Like")
-
- models.Favorite.broadcast = fav_broadcast_mock
-
status = models.Status.objects.create(
content="test content", user=self.local_user
)
- fav = models.Favorite.objects.create(status=status, user=self.local_user)
+
+ with patch("bookwyrm.models.Favorite.broadcast") as mock:
+ fav = models.Favorite.objects.create(status=status, user=self.local_user)
+ args = mock.call_args[0]
+ self.assertEqual(args[1].remote_id, self.local_user.remote_id)
+ self.assertEqual(args[0]["type"], "Like")
# can't fav a status twice
with self.assertRaises(IntegrityError):
@@ -384,7 +380,6 @@ class Status(TestCase):
self.assertEqual(activity["type"], "Like")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"], status.remote_id)
- models.Favorite.broadcast = real_broadcast
def test_boost(self, *_):
"""boosting, this one's a bit fussy"""
diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py
index 528d3fdc4..389928cda 100644
--- a/bookwyrm/tests/models/test_user_model.py
+++ b/bookwyrm/tests/models/test_user_model.py
@@ -165,12 +165,12 @@ class User(TestCase):
"""deactivate a user"""
self.assertTrue(self.user.is_active)
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as broadcast_mock:
self.user.delete()
self.assertEqual(broadcast_mock.call_count, 1)
- activity = json.loads(broadcast_mock.call_args[0][1])
+ activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"], self.user.remote_id)
self.assertFalse(self.user.is_active)
diff --git a/bookwyrm/tests/test_book_search.py b/bookwyrm/tests/test_book_search.py
index 4b9a06811..16435ffff 100644
--- a/bookwyrm/tests/test_book_search.py
+++ b/bookwyrm/tests/test_book_search.py
@@ -57,12 +57,24 @@ class BookSearch(TestCase):
self.assertEqual(len(results), 1)
self.assertEqual(results[0], self.second_edition)
+ def test_search_identifiers_return_first(self):
+ """search by unique identifiers"""
+ result = book_search.search_identifiers("hello", return_first=True)
+ self.assertEqual(result, self.second_edition)
+
def test_search_title_author(self):
"""search by unique identifiers"""
results = book_search.search_title_author("Another", min_confidence=0)
self.assertEqual(len(results), 1)
self.assertEqual(results[0], self.second_edition)
+ def test_search_title_author_return_first(self):
+ """search by unique identifiers"""
+ results = book_search.search_title_author(
+ "Another", min_confidence=0, return_first=True
+ )
+ self.assertEqual(results, self.second_edition)
+
def test_format_search_result(self):
"""format a search result"""
result = book_search.format_search_result(self.first_edition)
diff --git a/bookwyrm/tests/test_postgres.py b/bookwyrm/tests/test_postgres.py
index 70775d47e..624512575 100644
--- a/bookwyrm/tests/test_postgres.py
+++ b/bookwyrm/tests/test_postgres.py
@@ -5,7 +5,7 @@ from django.test import TestCase
from bookwyrm import models
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class PostgresTriggers(TestCase):
"""special migrations, fancy stuff ya know"""
diff --git a/bookwyrm/tests/test_suggested_users.py b/bookwyrm/tests/test_suggested_users.py
index f625ac10c..dce5d7704 100644
--- a/bookwyrm/tests/test_suggested_users.py
+++ b/bookwyrm/tests/test_suggested_users.py
@@ -9,7 +9,7 @@ from bookwyrm import models
from bookwyrm.suggested_users import suggested_users, get_annotated_users
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@@ -168,7 +168,7 @@ class SuggestedUsers(TestCase):
remote_id="https://example.com/book/1",
parent_work=work,
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
# 1 shared follow
self.local_user.following.add(user_2)
user_1.followers.add(user_2)
@@ -213,7 +213,7 @@ class SuggestedUsers(TestCase):
user.following.add(user_1)
user.followers.add(self.local_user)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
for i in range(3):
book = models.Edition.objects.create(
title=i,
diff --git a/bookwyrm/tests/test_templatetags.py b/bookwyrm/tests/test_templatetags.py
index 5954ce271..ed4466f58 100644
--- a/bookwyrm/tests/test_templatetags.py
+++ b/bookwyrm/tests/test_templatetags.py
@@ -44,7 +44,7 @@ class TemplateTags(TestCase):
def test_get_user_rating(self, *_):
"""get a user's most recent rating of a book"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.Review.objects.create(user=self.user, book=self.book, rating=3)
self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 3)
@@ -63,7 +63,7 @@ class TemplateTags(TestCase):
utilities.get_user_identifier(self.remote_user), "rat@example.com"
)
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
def test_get_replies(self, *_):
"""direct replies to a status"""
parent = models.Review.objects.create(
@@ -90,7 +90,7 @@ class TemplateTags(TestCase):
def test_get_parent(self, *_):
"""get the reply parent of a status"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
parent = models.Review.objects.create(
user=self.user, book=self.book, content="hi"
)
@@ -107,7 +107,7 @@ class TemplateTags(TestCase):
status = models.Review.objects.create(user=self.remote_user, book=self.book)
self.assertFalse(interaction.get_user_liked(self.user, status))
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.Favorite.objects.create(user=self.user, status=status)
self.assertTrue(interaction.get_user_liked(self.user, status))
@@ -116,13 +116,13 @@ class TemplateTags(TestCase):
status = models.Review.objects.create(user=self.remote_user, book=self.book)
self.assertFalse(interaction.get_user_boosted(self.user, status))
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.Boost.objects.create(user=self.user, boosted_status=status)
self.assertTrue(interaction.get_user_boosted(self.user, status))
def test_get_boosted(self, *_):
"""load a boosted status"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Review.objects.create(user=self.remote_user, book=self.book)
boost = models.Boost.objects.create(user=self.user, boosted_status=status)
boosted = status_display.get_boosted(boost)
@@ -166,7 +166,7 @@ class TemplateTags(TestCase):
def test_related_status(self, *_):
"""gets the subclass model for a notification status"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(content="hi", user=self.user)
notification = models.Notification.objects.create(
user=self.user, notification_type="MENTION", related_status=status
diff --git a/bookwyrm/tests/views/admin/test_reports.py b/bookwyrm/tests/views/admin/test_reports.py
index 2b063446a..8b9fe9f5d 100644
--- a/bookwyrm/tests/views/admin/test_reports.py
+++ b/bookwyrm/tests/views/admin/test_reports.py
@@ -151,10 +151,12 @@ class ReportViews(TestCase):
request.user.is_superuser = True
# de-activate
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.moderator_delete_user(request, self.rat.id)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.rat.refresh_from_db()
diff --git a/bookwyrm/tests/views/admin/test_user_admin.py b/bookwyrm/tests/views/admin/test_user_admin.py
index ef35c220d..486fe45e2 100644
--- a/bookwyrm/tests/views/admin/test_user_admin.py
+++ b/bookwyrm/tests/views/admin/test_user_admin.py
@@ -67,7 +67,7 @@ class UserAdminViews(TestCase):
request.user = self.local_user
request.user.is_superuser = True
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
result = view(request, self.local_user.id)
self.assertIsInstance(result, TemplateResponse)
diff --git a/bookwyrm/tests/views/books/test_book.py b/bookwyrm/tests/views/books/test_book.py
index a078f1616..561e21928 100644
--- a/bookwyrm/tests/views/books/test_book.py
+++ b/bookwyrm/tests/views/books/test_book.py
@@ -78,7 +78,7 @@ class BookViews(TestCase):
self.assertIsInstance(result, ActivitypubResponse)
self.assertEqual(result.status_code, 200)
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_book_page_statuses(self, *_):
"""there are so many views, this just makes sure it LOADS"""
@@ -169,7 +169,7 @@ class BookViews(TestCase):
request.user = self.local_user
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
views.upload_cover(request, self.book.id)
self.assertEqual(delay_mock.call_count, 1)
@@ -188,7 +188,7 @@ class BookViews(TestCase):
request.user = self.local_user
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
views.upload_cover(request, self.book.id)
self.assertEqual(delay_mock.call_count, 1)
@@ -202,7 +202,7 @@ class BookViews(TestCase):
request = self.factory.post("", {"description": "new description hi"})
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.add_description(request, self.book.id)
self.book.refresh_from_db()
diff --git a/bookwyrm/tests/views/books/test_edit_book.py b/bookwyrm/tests/views/books/test_edit_book.py
index 7bf5708f8..cd9578583 100644
--- a/bookwyrm/tests/views/books/test_edit_book.py
+++ b/bookwyrm/tests/views/books/test_edit_book.py
@@ -79,7 +79,7 @@ class EditBookViews(TestCase):
request = self.factory.post("", form.data)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, self.book.id)
self.book.refresh_from_db()
@@ -115,7 +115,7 @@ class EditBookViews(TestCase):
request = self.factory.post("", form.data)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, self.book.id)
self.book.refresh_from_db()
@@ -136,7 +136,7 @@ class EditBookViews(TestCase):
request = self.factory.post("", form.data)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, self.book.id)
self.book.refresh_from_db()
self.assertEqual(self.book.title, "New Title")
@@ -207,7 +207,7 @@ class EditBookViews(TestCase):
request.user = self.local_user
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
views.upload_cover(request, self.book.id)
self.assertEqual(delay_mock.call_count, 1)
diff --git a/bookwyrm/tests/views/books/test_editions.py b/bookwyrm/tests/views/books/test_editions.py
index 2f41fe66d..17f15654d 100644
--- a/bookwyrm/tests/views/books/test_editions.py
+++ b/bookwyrm/tests/views/books/test_editions.py
@@ -111,7 +111,7 @@ class BookViews(TestCase):
work = models.Work.objects.create(title="test work")
edition1 = models.Edition.objects.create(title="first ed", parent_work=work)
edition2 = models.Edition.objects.create(title="second ed", parent_work=work)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
shelf = models.Shelf.objects.create(name="Test Shelf", user=self.local_user)
models.ShelfBook.objects.create(
book=edition1,
@@ -124,7 +124,7 @@ class BookViews(TestCase):
self.assertEqual(models.ReadThrough.objects.get().book, edition1)
request = self.factory.post("", {"edition": edition2.id})
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.switch_edition(request)
self.assertEqual(models.ShelfBook.objects.get().book, edition2)
diff --git a/bookwyrm/tests/views/imports/__init__.py b/bookwyrm/tests/views/imports/__init__.py
new file mode 100644
index 000000000..b6e690fd5
--- /dev/null
+++ b/bookwyrm/tests/views/imports/__init__.py
@@ -0,0 +1 @@
+from . import *
diff --git a/bookwyrm/tests/views/test_import.py b/bookwyrm/tests/views/imports/test_import.py
similarity index 76%
rename from bookwyrm/tests/views/test_import.py
rename to bookwyrm/tests/views/imports/test_import.py
index 1411a5a89..b8b8b328d 100644
--- a/bookwyrm/tests/views/test_import.py
+++ b/bookwyrm/tests/views/imports/test_import.py
@@ -41,7 +41,7 @@ class ImportViews(TestCase):
def test_import_status(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.ImportStatus.as_view()
- import_job = models.ImportJob.objects.create(user=self.local_user)
+ import_job = models.ImportJob.objects.create(user=self.local_user, mappings={})
request = self.factory.get("")
request.user = self.local_user
with patch("bookwyrm.tasks.app.AsyncResult") as async_result:
@@ -55,10 +55,10 @@ class ImportViews(TestCase):
"""retry failed items"""
view = views.Import.as_view()
form = forms.ImportForm()
- form.data["source"] = "LibraryThing"
+ form.data["source"] = "Goodreads"
form.data["privacy"] = "public"
form.data["include_reviews"] = False
- csv_file = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
+ csv_file = pathlib.Path(__file__).parent.joinpath("../../data/goodreads.csv")
form.data["csv_file"] = SimpleUploadedFile(
# pylint: disable=consider-using-with
csv_file,
@@ -74,22 +74,3 @@ class ImportViews(TestCase):
job = models.ImportJob.objects.get()
self.assertFalse(job.include_reviews)
self.assertEqual(job.privacy, "public")
-
- def test_retry_import(self):
- """retry failed items"""
- view = views.ImportStatus.as_view()
- import_job = models.ImportJob.objects.create(
- user=self.local_user, privacy="unlisted"
- )
- request = self.factory.post("")
- request.user = self.local_user
-
- with patch("bookwyrm.importers.Importer.start_import"):
- view(request, import_job.id)
-
- self.assertEqual(models.ImportJob.objects.count(), 2)
- retry_job = models.ImportJob.objects.last()
-
- self.assertTrue(retry_job.retry)
- self.assertEqual(retry_job.user, self.local_user)
- self.assertEqual(retry_job.privacy, "unlisted")
diff --git a/bookwyrm/tests/views/imports/test_import_review.py b/bookwyrm/tests/views/imports/test_import_review.py
new file mode 100644
index 000000000..2ab48468b
--- /dev/null
+++ b/bookwyrm/tests/views/imports/test_import_review.py
@@ -0,0 +1,87 @@
+""" test for app action functionality """
+from unittest.mock import patch
+from django.template.response import TemplateResponse
+from django.test import TestCase
+from django.test.client import RequestFactory
+from bookwyrm.tests.validate_html import validate_html
+
+from bookwyrm import models, views
+
+
+class ImportManualReviewViews(TestCase):
+ """goodreads import views"""
+
+ def setUp(self):
+ """we need basic test data and mocks"""
+ self.factory = RequestFactory()
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ):
+ self.local_user = models.User.objects.create_user(
+ "mouse@local.com",
+ "mouse@mouse.mouse",
+ "password",
+ local=True,
+ localname="mouse",
+ )
+ models.SiteSettings.objects.create()
+ self.job = models.ImportJob.objects.create(user=self.local_user, mappings={})
+
+ work = models.Work.objects.create(title="Test Work")
+ self.book = models.Edition.objects.create(
+ title="Example Edition",
+ remote_id="https://example.com/book/1",
+ parent_work=work,
+ )
+
+ def test_import_troubleshoot_get(self):
+ """there are so many views, this just makes sure it LOADS"""
+ view = views.ImportManualReview.as_view()
+ request = self.factory.get("")
+ request.user = self.local_user
+ with patch("bookwyrm.tasks.app.AsyncResult") as async_result:
+ async_result.return_value = []
+ result = view(request, self.job.id)
+ self.assertIsInstance(result, TemplateResponse)
+ validate_html(result.render())
+ self.assertEqual(result.status_code, 200)
+
+ def test_approve_item(self):
+ """a guess is correct"""
+ import_item = models.ImportItem.objects.create(
+ index=0,
+ job=self.job,
+ book_guess=self.book,
+ fail_reason="no match",
+ data={},
+ normalized_data={},
+ )
+ request = self.factory.post("")
+ request.user = self.local_user
+
+ with patch("bookwyrm.importers.importer.import_item_task.delay") as mock:
+ views.approve_import_item(request, self.job.id, import_item.id)
+ self.assertEqual(mock.call_count, 1)
+ import_item.refresh_from_db()
+ self.assertIsNone(import_item.fail_reason)
+ self.assertIsNone(import_item.book_guess)
+ self.assertEqual(import_item.book.id, self.book.id)
+
+ def test_delete_item(self):
+ """a guess is correct"""
+ import_item = models.ImportItem.objects.create(
+ index=0,
+ job=self.job,
+ book_guess=self.book,
+ fail_reason="no match",
+ data={},
+ normalized_data={},
+ )
+ request = self.factory.post("")
+ request.user = self.local_user
+
+ views.delete_import_item(request, self.job.id, import_item.id)
+ import_item.refresh_from_db()
+ self.assertEqual(import_item.fail_reason, "no match")
+ self.assertIsNone(import_item.book_guess)
+ self.assertIsNone(import_item.book)
diff --git a/bookwyrm/tests/views/imports/test_import_troubleshoot.py b/bookwyrm/tests/views/imports/test_import_troubleshoot.py
new file mode 100644
index 000000000..5359cc1ea
--- /dev/null
+++ b/bookwyrm/tests/views/imports/test_import_troubleshoot.py
@@ -0,0 +1,59 @@
+""" test for app action functionality """
+from unittest.mock import patch
+from django.template.response import TemplateResponse
+from django.test import TestCase
+from django.test.client import RequestFactory
+from bookwyrm.tests.validate_html import validate_html
+
+from bookwyrm import models, views
+
+
+class ImportTroubleshootViews(TestCase):
+ """goodreads import views"""
+
+ def setUp(self):
+ """we need basic test data and mocks"""
+ self.factory = RequestFactory()
+ with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.populate_stream_task.delay"
+ ):
+ self.local_user = models.User.objects.create_user(
+ "mouse@local.com",
+ "mouse@mouse.mouse",
+ "password",
+ local=True,
+ localname="mouse",
+ )
+ models.SiteSettings.objects.create()
+
+ def test_import_troubleshoot_get(self):
+ """there are so many views, this just makes sure it LOADS"""
+ view = views.ImportTroubleshoot.as_view()
+ import_job = models.ImportJob.objects.create(user=self.local_user, mappings={})
+ request = self.factory.get("")
+ request.user = self.local_user
+ with patch("bookwyrm.tasks.app.AsyncResult") as async_result:
+ async_result.return_value = []
+ result = view(request, import_job.id)
+ self.assertIsInstance(result, TemplateResponse)
+ validate_html(result.render())
+ self.assertEqual(result.status_code, 200)
+
+ def test_retry_import(self):
+ """retry failed items"""
+ view = views.ImportTroubleshoot.as_view()
+ import_job = models.ImportJob.objects.create(
+ user=self.local_user, privacy="unlisted", mappings={}
+ )
+ request = self.factory.post("")
+ request.user = self.local_user
+
+ with patch("bookwyrm.importers.Importer.start_import"):
+ view(request, import_job.id)
+
+ self.assertEqual(models.ImportJob.objects.count(), 2)
+ retry_job = models.ImportJob.objects.last()
+
+ self.assertTrue(retry_job.retry)
+ self.assertEqual(retry_job.user, self.local_user)
+ self.assertEqual(retry_job.privacy, "unlisted")
diff --git a/bookwyrm/tests/views/inbox/test_inbox_announce.py b/bookwyrm/tests/views/inbox/test_inbox_announce.py
index 3a108878c..a291552d5 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_announce.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_announce.py
@@ -36,7 +36,7 @@ class InboxActivities(TestCase):
outbox="https://example.com/users/rat/outbox",
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
with patch("bookwyrm.activitystreams.add_status_task.delay"):
self.status = models.Status.objects.create(
user=self.local_user,
diff --git a/bookwyrm/tests/views/inbox/test_inbox_block.py b/bookwyrm/tests/views/inbox/test_inbox_block.py
index ffd74dbde..f6898fc65 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_block.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_block.py
@@ -40,7 +40,7 @@ class InboxBlock(TestCase):
def test_handle_blocks(self):
"""create a "block" database entry from an activity"""
self.local_user.followers.add(self.remote_user)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.UserFollowRequest.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
diff --git a/bookwyrm/tests/views/inbox/test_inbox_create.py b/bookwyrm/tests/views/inbox/test_inbox_create.py
index 76fd366ca..53b17d68a 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_create.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_create.py
@@ -10,7 +10,7 @@ from bookwyrm.activitypub import ActivitySerializerError
# pylint: disable=too-many-public-methods
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
class InboxCreate(TestCase):
"""readthrough tests"""
diff --git a/bookwyrm/tests/views/inbox/test_inbox_follow.py b/bookwyrm/tests/views/inbox/test_inbox_follow.py
index 6b629c2f0..71f101caa 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_follow.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_follow.py
@@ -49,10 +49,12 @@ class InboxRelationships(TestCase):
}
self.assertFalse(models.UserFollowRequest.objects.exists())
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.inbox.activity_task(activity)
self.assertEqual(mock.call_count, 1)
- response_activity = json.loads(mock.call_args[0][1])
+ response_activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(response_activity["type"], "Accept")
# notification created
@@ -77,17 +79,19 @@ class InboxRelationships(TestCase):
"object": "https://example.com/user/mouse",
}
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.inbox.activity_task(activity)
# the follow relationship should exist
follow = models.UserFollows.objects.get(user_object=self.local_user)
self.assertEqual(follow.user_subject, self.remote_user)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.inbox.activity_task(activity)
self.assertEqual(mock.call_count, 1)
- response_activity = json.loads(mock.call_args[0][1])
+ response_activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(response_activity["type"], "Accept")
# the follow relationship should STILL exist
@@ -109,7 +113,7 @@ class InboxRelationships(TestCase):
broadcast=False, update_fields=["manually_approves_followers"]
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.inbox.activity_task(activity)
# notification created
@@ -132,7 +136,7 @@ class InboxRelationships(TestCase):
self.local_user.save(
broadcast=False, update_fields=["manually_approves_followers"]
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
request = models.UserFollowRequest.objects.create(
user_subject=self.remote_user, user_object=self.local_user
)
@@ -160,7 +164,7 @@ class InboxRelationships(TestCase):
def test_unfollow(self):
"""remove a relationship"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
rel = models.UserFollows.objects.create(
user_subject=self.remote_user, user_object=self.local_user
)
@@ -186,7 +190,7 @@ class InboxRelationships(TestCase):
@patch("bookwyrm.activitystreams.add_user_statuses_task.delay")
def test_follow_accept(self, _):
"""a remote user approved a follow request from local"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
rel = models.UserFollowRequest.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
@@ -217,7 +221,7 @@ class InboxRelationships(TestCase):
def test_follow_reject(self):
"""turn down a follow request"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
rel = models.UserFollowRequest.objects.create(
user_subject=self.local_user, user_object=self.remote_user
)
diff --git a/bookwyrm/tests/views/inbox/test_inbox_like.py b/bookwyrm/tests/views/inbox/test_inbox_like.py
index db8f1fca8..2f1b6629d 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_like.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_like.py
@@ -35,7 +35,7 @@ class InboxActivities(TestCase):
outbox="https://example.com/users/rat/outbox",
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
with patch("bookwyrm.activitystreams.add_status_task.delay"):
self.status = models.Status.objects.create(
user=self.local_user,
diff --git a/bookwyrm/tests/views/inbox/test_inbox_remove.py b/bookwyrm/tests/views/inbox/test_inbox_remove.py
index cb4e4a16f..55cc81202 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_remove.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_remove.py
@@ -75,7 +75,7 @@ class InboxRemove(TestCase):
def test_handle_remove_book_from_list(self):
"""listing a book"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
booklist = models.List.objects.create(
name="test list",
user=self.local_user,
diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py
index 0efeac0c8..248c1ad2c 100644
--- a/bookwyrm/tests/views/inbox/test_inbox_update.py
+++ b/bookwyrm/tests/views/inbox/test_inbox_update.py
@@ -50,7 +50,7 @@ class InboxUpdate(TestCase):
def test_update_list(self):
"""a new list"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
book_list = models.List.objects.create(
name="hi", remote_id="https://example.com/list/22", user=self.local_user
)
@@ -171,7 +171,7 @@ class InboxUpdate(TestCase):
book = models.Work.objects.get(id=book.id)
self.assertEqual(book.title, "Piranesi")
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_update_status(self, *_):
"""edit a status"""
diff --git a/bookwyrm/tests/views/preferences/test_block.py b/bookwyrm/tests/views/preferences/test_block.py
index b23a6cbc4..975142a1f 100644
--- a/bookwyrm/tests/views/preferences/test_block.py
+++ b/bookwyrm/tests/views/preferences/test_block.py
@@ -9,7 +9,7 @@ from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class BlockViews(TestCase):
"""view user and edit profile"""
diff --git a/bookwyrm/tests/views/preferences/test_delete_user.py b/bookwyrm/tests/views/preferences/test_delete_user.py
index 09f722f70..b6d87ccde 100644
--- a/bookwyrm/tests/views/preferences/test_delete_user.py
+++ b/bookwyrm/tests/views/preferences/test_delete_user.py
@@ -35,9 +35,9 @@ class DeleteUserViews(TestCase):
self.book = models.Edition.objects.create(
title="test", parent_work=models.Work.objects.create(title="test work")
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"), patch(
- "bookwyrm.activitystreams.add_book_statuses_task.delay"
- ):
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ), patch("bookwyrm.activitystreams.add_book_statuses_task.delay"):
models.ShelfBook.objects.create(
book=self.book,
user=self.local_user,
@@ -70,11 +70,11 @@ class DeleteUserViews(TestCase):
self.assertIsNone(self.local_user.name)
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
view(request)
self.assertEqual(delay_mock.call_count, 1)
- activity = json.loads(delay_mock.call_args[0][1])
+ activity = json.loads(delay_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(
diff --git a/bookwyrm/tests/views/preferences/test_edit_user.py b/bookwyrm/tests/views/preferences/test_edit_user.py
index b52875a9a..7a845fbe3 100644
--- a/bookwyrm/tests/views/preferences/test_edit_user.py
+++ b/bookwyrm/tests/views/preferences/test_edit_user.py
@@ -38,9 +38,9 @@ class EditUserViews(TestCase):
self.book = models.Edition.objects.create(
title="test", parent_work=models.Work.objects.create(title="test work")
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"), patch(
- "bookwyrm.activitystreams.add_book_statuses_task.delay"
- ):
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ), patch("bookwyrm.activitystreams.add_book_statuses_task.delay"):
models.ShelfBook.objects.create(
book=self.book,
user=self.local_user,
@@ -74,7 +74,7 @@ class EditUserViews(TestCase):
self.assertIsNone(self.local_user.name)
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
view(request)
self.assertEqual(delay_mock.call_count, 1)
@@ -100,7 +100,7 @@ class EditUserViews(TestCase):
request.user = self.local_user
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
view(request)
self.assertEqual(delay_mock.call_count, 1)
diff --git a/bookwyrm/tests/views/shelf/test_shelf.py b/bookwyrm/tests/views/shelf/test_shelf.py
index 71df3631f..ab88de0a0 100644
--- a/bookwyrm/tests/views/shelf/test_shelf.py
+++ b/bookwyrm/tests/views/shelf/test_shelf.py
@@ -11,7 +11,7 @@ from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.tests.validate_html import validate_html
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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.activitystreams.add_book_statuses_task.delay")
@@ -39,7 +39,7 @@ class ShelfViews(TestCase):
remote_id="https://example.com/book/1",
parent_work=self.work,
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
@@ -142,7 +142,7 @@ class ShelfViews(TestCase):
"", {"privacy": "public", "user": self.local_user.id, "name": "cool name"}
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, request.user.username, shelf.identifier)
shelf.refresh_from_db()
@@ -159,7 +159,7 @@ class ShelfViews(TestCase):
"", {"privacy": "public", "user": self.local_user.id, "name": "cool name"}
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, request.user.username, shelf.identifier)
self.assertEqual(shelf.name, "To Read")
diff --git a/bookwyrm/tests/views/shelf/test_shelf_actions.py b/bookwyrm/tests/views/shelf/test_shelf_actions.py
index 3efae0f45..1a7d56fdd 100644
--- a/bookwyrm/tests/views/shelf/test_shelf_actions.py
+++ b/bookwyrm/tests/views/shelf/test_shelf_actions.py
@@ -9,7 +9,7 @@ from django.test.client import RequestFactory
from bookwyrm import forms, models, views
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@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.activitystreams.add_book_statuses_task.delay")
@@ -37,7 +37,7 @@ class ShelfActionViews(TestCase):
remote_id="https://example.com/book/1",
parent_work=self.work,
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
@@ -49,11 +49,13 @@ class ShelfActionViews(TestCase):
"", {"book": self.book.id, "shelf": self.shelf.identifier}
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.shelve(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
item = models.ShelfBook.objects.get()
@@ -69,7 +71,7 @@ class ShelfActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.shelve(request)
# make sure the book is on the shelf
self.assertEqual(shelf.books.get(), self.book)
@@ -82,7 +84,7 @@ class ShelfActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.shelve(request)
# make sure the book is on the shelf
self.assertEqual(shelf.books.get(), self.book)
@@ -95,7 +97,7 @@ class ShelfActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.shelve(request)
# make sure the book is on the shelf
self.assertEqual(shelf.books.get(), self.book)
@@ -118,7 +120,7 @@ class ShelfActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.shelve(request)
# make sure the book is on the shelf
self.assertEqual(shelf.books.get(), self.book)
@@ -126,7 +128,7 @@ class ShelfActionViews(TestCase):
def test_unshelve(self, *_):
"""remove a book from a shelf"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ShelfBook.objects.create(
book=self.book, user=self.local_user, shelf=self.shelf
)
@@ -136,9 +138,11 @@ class ShelfActionViews(TestCase):
self.assertEqual(self.shelf.books.count(), 1)
request = self.factory.post("", {"book": self.book.id, "shelf": self.shelf.id})
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.unshelve(request)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Remove")
self.assertEqual(activity["object"]["id"], item.remote_id)
self.assertEqual(self.shelf.books.count(), 0)
@@ -192,7 +196,7 @@ class ShelfActionViews(TestCase):
def test_delete_shelf_has_book(self, *_):
"""delete a brand new custom shelf"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ShelfBook.objects.create(
book=self.book, user=self.local_user, shelf=self.shelf
)
diff --git a/bookwyrm/tests/views/test_author.py b/bookwyrm/tests/views/test_author.py
index ccbfe5493..32b1565e3 100644
--- a/bookwyrm/tests/views/test_author.py
+++ b/bookwyrm/tests/views/test_author.py
@@ -111,7 +111,7 @@ class AuthorViews(TestCase):
request = self.factory.post("", form.data)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, author.id)
author.refresh_from_db()
self.assertEqual(author.name, "New Name")
diff --git a/bookwyrm/tests/views/test_discover.py b/bookwyrm/tests/views/test_discover.py
index 4b8927bca..b2a82241f 100644
--- a/bookwyrm/tests/views/test_discover.py
+++ b/bookwyrm/tests/views/test_discover.py
@@ -41,7 +41,7 @@ class DiscoverViews(TestCase):
self.assertEqual(result.status_code, 200)
result.render()
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_discover_page(self, *_):
"""there are so many views, this just makes sure it LOADS"""
diff --git a/bookwyrm/tests/views/test_feed.py b/bookwyrm/tests/views/test_feed.py
index a6f220b58..5c6a4dd37 100644
--- a/bookwyrm/tests/views/test_feed.py
+++ b/bookwyrm/tests/views/test_feed.py
@@ -57,7 +57,7 @@ class FeedViews(TestCase):
def test_status_page(self, *_):
"""there are so many views, this just makes sure it LOADS"""
view = views.Status.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(content="hi", user=self.local_user)
request = self.factory.get("")
request.user = self.local_user
@@ -95,7 +95,7 @@ class FeedViews(TestCase):
local=True,
localname="rat",
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(content="hi", user=another_user)
request = self.factory.get("")
@@ -115,7 +115,7 @@ class FeedViews(TestCase):
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Review.objects.create(
content="hi",
user=self.local_user,
@@ -144,7 +144,7 @@ class FeedViews(TestCase):
def test_replies_page(self, *_):
"""there are so many views, this just makes sure it LOADS"""
view = views.Replies.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Status.objects.create(content="hi", user=self.local_user)
request = self.factory.get("")
request.user = self.local_user
@@ -171,7 +171,7 @@ class FeedViews(TestCase):
result.render()
self.assertEqual(result.status_code, 200)
- @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+ @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
def test_get_suggested_book(self, *_):
"""gets books the ~*~ algorithm ~*~ thinks you want to post about"""
diff --git a/bookwyrm/tests/views/test_follow.py b/bookwyrm/tests/views/test_follow.py
index 947c55cf0..25b5a0146 100644
--- a/bookwyrm/tests/views/test_follow.py
+++ b/bookwyrm/tests/views/test_follow.py
@@ -59,7 +59,7 @@ class FollowViews(TestCase):
request.user = self.local_user
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.follow(request)
rel = models.UserFollowRequest.objects.get()
@@ -86,7 +86,7 @@ class FollowViews(TestCase):
request.user = self.local_user
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.follow(request)
rel = models.UserFollowRequest.objects.get()
@@ -111,7 +111,7 @@ class FollowViews(TestCase):
request.user = self.local_user
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.follow(request)
rel = models.UserFollows.objects.get()
@@ -127,10 +127,12 @@ class FollowViews(TestCase):
request.user = self.local_user
self.remote_user.followers.add(self.local_user)
self.assertEqual(self.remote_user.followers.count(), 1)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.unfollow(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args_list[0][0][1])
+ activity = json.loads(mock.call_args_list[0][1]["args"][1])
self.assertEqual(activity["type"], "Undo")
self.assertEqual(self.remote_user.followers.count(), 0)
@@ -147,7 +149,7 @@ class FollowViews(TestCase):
user_subject=self.remote_user, user_object=self.local_user
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.accept_follow_request(request)
# request should be deleted
self.assertEqual(models.UserFollowRequest.objects.filter(id=rel.id).count(), 0)
@@ -166,7 +168,7 @@ class FollowViews(TestCase):
user_subject=self.remote_user, user_object=self.local_user
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.delete_follow_request(request)
# request should be deleted
self.assertEqual(models.UserFollowRequest.objects.filter(id=rel.id).count(), 0)
diff --git a/bookwyrm/tests/views/test_get_started.py b/bookwyrm/tests/views/test_get_started.py
index ff441b578..6d1819a4b 100644
--- a/bookwyrm/tests/views/test_get_started.py
+++ b/bookwyrm/tests/views/test_get_started.py
@@ -56,7 +56,7 @@ class GetStartedViews(TestCase):
self.assertIsNone(self.local_user.name)
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
view(request)
self.assertEqual(delay_mock.call_count, 1)
@@ -98,7 +98,7 @@ class GetStartedViews(TestCase):
self.assertFalse(self.local_user.shelfbook_set.exists())
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as delay_mock:
view(request)
self.assertEqual(delay_mock.call_count, 1)
diff --git a/bookwyrm/tests/views/test_goal.py b/bookwyrm/tests/views/test_goal.py
index 557510d75..732072406 100644
--- a/bookwyrm/tests/views/test_goal.py
+++ b/bookwyrm/tests/views/test_goal.py
@@ -123,7 +123,7 @@ class GoalViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, self.local_user.localname, self.year)
goal = models.AnnualGoal.objects.get()
diff --git a/bookwyrm/tests/views/test_group.py b/bookwyrm/tests/views/test_group.py
index c7e0a0f76..b18ce6b4f 100644
--- a/bookwyrm/tests/views/test_group.py
+++ b/bookwyrm/tests/views/test_group.py
@@ -10,7 +10,7 @@ from bookwyrm import models, views, forms
from bookwyrm.tests.validate_html import validate_html
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class GroupViews(TestCase):
"""view group and edit details"""
diff --git a/bookwyrm/tests/views/test_helpers.py b/bookwyrm/tests/views/test_helpers.py
index 8f7b45a35..1aae830f6 100644
--- a/bookwyrm/tests/views/test_helpers.py
+++ b/bookwyrm/tests/views/test_helpers.py
@@ -55,7 +55,7 @@ class ViewsHelpers(TestCase):
datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json")
self.userdata = json.loads(datafile.read_bytes())
del self.userdata["icon"]
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.shelf = models.Shelf.objects.create(
name="Test Shelf", identifier="test-shelf", user=self.local_user
)
@@ -166,7 +166,7 @@ class ViewsHelpers(TestCase):
def test_handle_reading_status_to_read(self, *_):
"""posts shelve activities"""
shelf = self.local_user.shelf_set.get(identifier="to-read")
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.helpers.handle_reading_status(
self.local_user, shelf, self.book, "public"
)
@@ -178,7 +178,7 @@ class ViewsHelpers(TestCase):
def test_handle_reading_status_reading(self, *_):
"""posts shelve activities"""
shelf = self.local_user.shelf_set.get(identifier="reading")
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.helpers.handle_reading_status(
self.local_user, shelf, self.book, "public"
)
@@ -190,7 +190,7 @@ class ViewsHelpers(TestCase):
def test_handle_reading_status_read(self, *_):
"""posts shelve activities"""
shelf = self.local_user.shelf_set.get(identifier="read")
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.helpers.handle_reading_status(
self.local_user, shelf, self.book, "public"
)
@@ -201,7 +201,7 @@ class ViewsHelpers(TestCase):
def test_handle_reading_status_other(self, *_):
"""posts shelve activities"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.helpers.handle_reading_status(
self.local_user, self.shelf, self.book, "public"
)
diff --git a/bookwyrm/tests/views/test_interaction.py b/bookwyrm/tests/views/test_interaction.py
index e8b9353ed..aa402952c 100644
--- a/bookwyrm/tests/views/test_interaction.py
+++ b/bookwyrm/tests/views/test_interaction.py
@@ -7,7 +7,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.remove_status_task.delay")
class InteractionViews(TestCase):
"""viewing and creating statuses"""
@@ -74,7 +74,7 @@ class InteractionViews(TestCase):
self.assertEqual(models.Favorite.objects.count(), 1)
self.assertEqual(models.Notification.objects.count(), 1)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, status.id)
self.assertEqual(models.Favorite.objects.count(), 0)
self.assertEqual(models.Notification.objects.count(), 0)
@@ -110,12 +110,12 @@ class InteractionViews(TestCase):
status = models.Status.objects.create(user=self.local_user, content="hi")
with patch(
- "bookwyrm.models.activitypub_mixin.broadcast_task.delay"
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as broadcast_mock:
view(request, status.id)
self.assertEqual(broadcast_mock.call_count, 1)
- activity = json.loads(broadcast_mock.call_args[0][1])
+ activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Announce")
boost = models.Boost.objects.get()
diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py
index 35befec6b..c670ad188 100644
--- a/bookwyrm/tests/views/test_list.py
+++ b/bookwyrm/tests/views/test_list.py
@@ -61,7 +61,7 @@ class ListViews(TestCase):
parent_work=work_four,
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.list = models.List.objects.create(
name="Test List", user=self.local_user
)
@@ -73,7 +73,7 @@ class ListViews(TestCase):
def test_lists_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Lists.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.List.objects.create(name="Public list", user=self.local_user)
models.List.objects.create(
name="Private list", privacy="direct", user=self.local_user
@@ -96,7 +96,7 @@ class ListViews(TestCase):
def test_saved_lists_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.SavedLists.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
booklist = models.List.objects.create(
name="Public list", user=self.local_user
)
@@ -116,7 +116,7 @@ class ListViews(TestCase):
def test_saved_lists_page_empty(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.SavedLists.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.List.objects.create(name="Public list", user=self.local_user)
models.List.objects.create(
name="Private list", privacy="direct", user=self.local_user
@@ -153,11 +153,13 @@ class ListViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
result = view(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Create")
self.assertEqual(activity["actor"], self.local_user.remote_id)
@@ -172,7 +174,7 @@ class ListViews(TestCase):
view = views.List.as_view()
request = self.factory.get("")
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -191,7 +193,7 @@ class ListViews(TestCase):
def test_list_page_sorted(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.List.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
for (i, book) in enumerate([self.book, self.book_two, self.book_three]):
models.ListItem.objects.create(
book_list=self.list,
@@ -253,7 +255,7 @@ class ListViews(TestCase):
def test_list_page_logged_out(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.List.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -276,7 +278,7 @@ class ListViews(TestCase):
view = views.List.as_view()
request = self.factory.get("")
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -320,11 +322,13 @@ class ListViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
result = view(request, self.list.id)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Update")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], self.list.remote_id)
@@ -340,7 +344,7 @@ class ListViews(TestCase):
def test_curate_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.Curate.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.List.objects.create(name="Public list", user=self.local_user)
models.List.objects.create(
name="Private list", privacy="direct", user=self.local_user
@@ -360,7 +364,7 @@ class ListViews(TestCase):
def test_user_lists_page(self):
"""there are so many views, this just makes sure it LOADS"""
view = views.UserLists.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.List.objects.create(name="Public list", user=self.local_user)
models.List.objects.create(
name="Private list", privacy="direct", user=self.local_user
diff --git a/bookwyrm/tests/views/test_list_actions.py b/bookwyrm/tests/views/test_list_actions.py
index f7775d19f..1d9f46b3a 100644
--- a/bookwyrm/tests/views/test_list_actions.py
+++ b/bookwyrm/tests/views/test_list_actions.py
@@ -61,7 +61,7 @@ class ListActionViews(TestCase):
parent_work=work_four,
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.list = models.List.objects.create(
name="Test List", user=self.local_user
)
@@ -71,7 +71,7 @@ class ListActionViews(TestCase):
def test_delete_list(self):
"""delete an entire list"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -88,9 +88,11 @@ class ListActionViews(TestCase):
)
request = self.factory.post("")
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.delete_list(request, self.list.id)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["object"]["id"], self.list.remote_id)
@@ -110,7 +112,7 @@ class ListActionViews(TestCase):
def test_curate_approve(self):
"""approve a pending item"""
view = views.Curate.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
pending = models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -128,11 +130,13 @@ class ListActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
view(request, self.list.id)
self.assertEqual(mock.call_count, 2)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["target"], self.list.remote_id)
@@ -145,7 +149,7 @@ class ListActionViews(TestCase):
def test_curate_reject(self):
"""approve a pending item"""
view = views.Curate.as_view()
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
pending = models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -179,10 +183,12 @@ class ListActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.list.add_book(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["target"], self.list.remote_id)
@@ -214,7 +220,7 @@ class ListActionViews(TestCase):
},
)
request_two.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.add_book(request_one)
views.list.add_book(request_two)
@@ -256,7 +262,7 @@ class ListActionViews(TestCase):
)
request_three.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.add_book(request_one)
views.list.add_book(request_two)
views.list.add_book(request_three)
@@ -271,7 +277,7 @@ class ListActionViews(TestCase):
remove_request = self.factory.post("", {"item": items[1].id})
remove_request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.remove_book(remove_request, self.list.id)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book)
@@ -293,7 +299,7 @@ class ListActionViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -330,7 +336,7 @@ class ListActionViews(TestCase):
its order should be at the end of the approved books and before the
remaining pending books.
"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -370,7 +376,7 @@ class ListActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
view(request, self.list.id)
items = self.list.listitem_set.order_by("order").all()
@@ -422,7 +428,7 @@ class ListActionViews(TestCase):
)
request_three.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.add_book(request_one)
views.list.add_book(request_two)
views.list.add_book(request_three)
@@ -437,7 +443,7 @@ class ListActionViews(TestCase):
set_position_request = self.factory.post("", {"position": 1})
set_position_request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.set_book_position(set_position_request, items[2].id)
items = self.list.listitem_set.order_by("order").all()
self.assertEqual(items[0].book, self.book_three)
@@ -460,10 +466,12 @@ class ListActionViews(TestCase):
)
request.user = self.rat
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.list.add_book(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.rat.remote_id)
self.assertEqual(activity["target"], self.list.remote_id)
@@ -486,11 +494,13 @@ class ListActionViews(TestCase):
)
request.user = self.rat
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.list.add_book(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.rat.remote_id)
@@ -516,10 +526,12 @@ class ListActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ) as mock:
views.list.add_book(request)
self.assertEqual(mock.call_count, 1)
- activity = json.loads(mock.call_args[0][1])
+ activity = json.loads(mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Add")
self.assertEqual(activity["actor"], self.local_user.remote_id)
self.assertEqual(activity["target"], self.list.remote_id)
@@ -532,7 +544,7 @@ class ListActionViews(TestCase):
def test_remove_book(self):
"""take an item off a list"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
item = models.ListItem.objects.create(
book_list=self.list,
user=self.local_user,
@@ -549,13 +561,13 @@ class ListActionViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.list.remove_book(request, self.list.id)
self.assertFalse(self.list.listitem_set.exists())
def test_remove_book_unauthorized(self):
"""take an item off a list"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
item = models.ListItem.objects.create(
book_list=self.list, user=self.local_user, book=self.book, order=1
)
diff --git a/bookwyrm/tests/views/test_notifications.py b/bookwyrm/tests/views/test_notifications.py
index dd28a811b..5df62b1da 100644
--- a/bookwyrm/tests/views/test_notifications.py
+++ b/bookwyrm/tests/views/test_notifications.py
@@ -25,7 +25,7 @@ class NotificationViews(TestCase):
local=True,
localname="mouse",
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.status = models.Status.objects.create(
content="hi",
user=self.local_user,
diff --git a/bookwyrm/tests/views/test_outbox.py b/bookwyrm/tests/views/test_outbox.py
index a1f62cc61..5c5d47b08 100644
--- a/bookwyrm/tests/views/test_outbox.py
+++ b/bookwyrm/tests/views/test_outbox.py
@@ -11,7 +11,7 @@ from bookwyrm.settings import USER_AGENT
# pylint: disable=too-many-public-methods
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class OutboxView(TestCase):
"""sends out activities"""
diff --git a/bookwyrm/tests/views/test_reading.py b/bookwyrm/tests/views/test_reading.py
index 4e5206f63..4ec50165f 100644
--- a/bookwyrm/tests/views/test_reading.py
+++ b/bookwyrm/tests/views/test_reading.py
@@ -64,7 +64,7 @@ class ReadingViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.ReadingStatus.as_view()(request, "start", self.book.id)
self.assertEqual(shelf.books.get(), self.book)
@@ -100,7 +100,7 @@ class ReadingViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.ReadingStatus.as_view()(request, "start", self.book.id)
self.assertEqual(shelf.books.get(), self.book)
@@ -124,7 +124,7 @@ class ReadingViews(TestCase):
def test_start_reading_reshelve(self, *_):
"""begin a book"""
to_read_shelf = self.local_user.shelf_set.get(identifier=models.Shelf.TO_READ)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
models.ShelfBook.objects.create(
shelf=to_read_shelf, book=self.book, user=self.local_user
)
@@ -135,7 +135,7 @@ class ReadingViews(TestCase):
request = self.factory.post("")
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.ReadingStatus.as_view()(request, "start", self.book.id)
self.assertFalse(to_read_shelf.books.exists())
@@ -162,7 +162,7 @@ class ReadingViews(TestCase):
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.ReadingStatus.as_view()(request, "finish", self.book.id)
self.assertEqual(shelf.books.get(), self.book)
@@ -267,7 +267,7 @@ class ReadingViews(TestCase):
},
)
request.user = self.local_user
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
views.update_progress(request, self.book.id)
status = models.Comment.objects.get()
diff --git a/bookwyrm/tests/views/test_readthrough.py b/bookwyrm/tests/views/test_readthrough.py
index ef149ce30..5b554748f 100644
--- a/bookwyrm/tests/views/test_readthrough.py
+++ b/bookwyrm/tests/views/test_readthrough.py
@@ -9,7 +9,7 @@ from bookwyrm import models
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@patch("bookwyrm.activitystreams.remove_book_statuses_task.delay")
class ReadThrough(TestCase):
@@ -32,7 +32,7 @@ class ReadThrough(TestCase):
"cinco", "cinco@example.com", "seissiete", local=True, localname="cinco"
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
self.client.force_login(self.user)
@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay")
diff --git a/bookwyrm/tests/views/test_rss_feed.py b/bookwyrm/tests/views/test_rss_feed.py
index d4d112618..409c306dc 100644
--- a/bookwyrm/tests/views/test_rss_feed.py
+++ b/bookwyrm/tests/views/test_rss_feed.py
@@ -6,7 +6,7 @@ from bookwyrm import models
from bookwyrm.views import rss_feed
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.ActivityStream.get_activity_stream")
@patch("bookwyrm.activitystreams.add_status_task.delay")
class RssFeedView(TestCase):
diff --git a/bookwyrm/tests/views/test_search.py b/bookwyrm/tests/views/test_search.py
index 3299249a0..f80455113 100644
--- a/bookwyrm/tests/views/test_search.py
+++ b/bookwyrm/tests/views/test_search.py
@@ -139,7 +139,7 @@ class Views(TestCase):
def test_search_lists(self):
"""searches remote connectors"""
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+ with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
booklist = models.List.objects.create(
user=self.local_user, name="test list"
)
diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py
index db61b1528..b5d7ac162 100644
--- a/bookwyrm/tests/views/test_status.py
+++ b/bookwyrm/tests/views/test_status.py
@@ -14,7 +14,7 @@ from bookwyrm.tests.validate_html import validate_html
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.remove_status_task.delay")
-@patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay")
+@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class StatusViews(TestCase):
"""viewing and creating statuses"""
@@ -310,7 +310,7 @@ http://www.fish.com/"""
with patch("bookwyrm.activitystreams.remove_status_task.delay") as redis_mock:
view(request, status.id)
self.assertTrue(redis_mock.called)
- activity = json.loads(mock.call_args_list[1][0][1])
+ activity = json.loads(mock.call_args_list[1][1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"]["type"], "Tombstone")
status.refresh_from_db()
@@ -344,7 +344,7 @@ http://www.fish.com/"""
with patch("bookwyrm.activitystreams.remove_status_task.delay") as redis_mock:
view(request, status.id)
self.assertTrue(redis_mock.called)
- activity = json.loads(mock.call_args_list[1][0][1])
+ activity = json.loads(mock.call_args_list[1][1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"]["type"], "Tombstone")
status.refresh_from_db()
@@ -396,7 +396,7 @@ http://www.fish.com/"""
request.user = self.local_user
view(request, "comment", existing_status_id=status.id)
- activity = json.loads(mock.call_args_list[1][0][1])
+ activity = json.loads(mock.call_args_list[1][1]["args"][1])
self.assertEqual(activity["type"], "Update")
self.assertEqual(activity["object"]["id"], status.remote_id)
diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py
index 1183fa247..ddb029cc9 100644
--- a/bookwyrm/tests/views/test_user.py
+++ b/bookwyrm/tests/views/test_user.py
@@ -34,9 +34,11 @@ class UserViews(TestCase):
self.book = models.Edition.objects.create(
title="test", parent_work=models.Work.objects.create(title="test work")
)
- with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"), patch(
- "bookwyrm.suggested_users.rerank_suggestions_task.delay"
- ), patch("bookwyrm.activitystreams.add_book_statuses_task.delay"):
+ with patch(
+ "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
+ ), patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
+ "bookwyrm.activitystreams.add_book_statuses_task.delay"
+ ):
models.ShelfBook.objects.create(
book=self.book,
user=self.local_user,
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 839d783fd..514bb7e60 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -237,7 +237,41 @@ urlpatterns = [
re_path(r"^search/?$", views.Search.as_view(), name="search"),
# imports
re_path(r"^import/?$", views.Import.as_view(), name="import"),
- re_path(r"^import/(\d+)/?$", views.ImportStatus.as_view(), name="import-status"),
+ re_path(
+ r"^import/(?P
\d+)/?$",
+ views.ImportStatus.as_view(),
+ name="import-status",
+ ),
+ re_path(
+ r"^import/(?P\d+)/retry/(?P\d+)/?$",
+ views.retry_item,
+ name="import-item-retry",
+ ),
+ re_path(
+ r"^import/(?P\d+)/failed/?$",
+ views.ImportTroubleshoot.as_view(),
+ name="import-troubleshoot",
+ ),
+ re_path(
+ r"^import/(?P\d+)/review/?$",
+ views.ImportManualReview.as_view(),
+ name="import-review",
+ ),
+ re_path(
+ r"^import/(?P\d+)/review/?$",
+ views.ImportManualReview.as_view(),
+ name="import-review",
+ ),
+ re_path(
+ r"^import/(?P\d+)/review/(?P\d+)/approve/?$",
+ views.approve_import_item,
+ name="import-approve",
+ ),
+ re_path(
+ r"^import/(?P\d+)/review/(?P\d+)/delete/?$",
+ views.delete_import_item,
+ name="import-delete",
+ ),
# users
re_path(rf"{USER_PATH}\.json$", views.User.as_view()),
re_path(rf"{USER_PATH}/?$", views.User.as_view(), name="user-feed"),
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index e1dd83557..d79de4248 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -43,6 +43,16 @@ from .shelf.shelf import Shelf
from .shelf.shelf_actions import create_shelf, delete_shelf
from .shelf.shelf_actions import shelve, unshelve
+# csv import
+from .imports.import_data import Import
+from .imports.import_status import ImportStatus, retry_item
+from .imports.troubleshoot import ImportTroubleshoot
+from .imports.manually_review import (
+ ImportManualReview,
+ approve_import_item,
+ delete_import_item,
+)
+
# misc views
from .author import Author, EditAuthor
from .directory import Directory
@@ -62,7 +72,6 @@ from .group import (
accept_membership,
reject_membership,
)
-from .import_data import Import, ImportStatus
from .inbox import Inbox
from .interaction import Favorite, Unfavorite, Boost, Unboost
from .isbn import Isbn
diff --git a/bookwyrm/views/imports/__init__.py b/bookwyrm/views/imports/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/bookwyrm/views/import_data.py b/bookwyrm/views/imports/import_data.py
similarity index 58%
rename from bookwyrm/views/import_data.py
rename to bookwyrm/views/imports/import_data.py
index 5e113be88..7f6a4d13f 100644
--- a/bookwyrm/views/import_data.py
+++ b/bookwyrm/views/imports/import_data.py
@@ -2,9 +2,8 @@
from io import TextIOWrapper
from django.contrib.auth.decorators import login_required
-from django.core.exceptions import PermissionDenied
from django.http import HttpResponseBadRequest
-from django.shortcuts import get_object_or_404, redirect
+from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
@@ -12,12 +11,10 @@ from django.views import View
from bookwyrm import forms, models
from bookwyrm.importers import (
- Importer,
LibrarythingImporter,
GoodreadsImporter,
StorygraphImporter,
)
-from bookwyrm.tasks import app
# pylint: disable= no-self-use
@method_decorator(login_required, name="dispatch")
@@ -70,46 +67,3 @@ class Import(View):
return redirect(f"/import/{job.id}")
return HttpResponseBadRequest()
-
-
-@method_decorator(login_required, name="dispatch")
-class ImportStatus(View):
- """status of an existing import"""
-
- def get(self, request, job_id):
- """status of an import job"""
- job = get_object_or_404(models.ImportJob, id=job_id)
- if job.user != request.user:
- raise PermissionDenied()
-
- try:
- task = app.AsyncResult(job.task_id)
- # triggers attribute error if the task won't load
- task.status # pylint: disable=pointless-statement
- except (ValueError, AttributeError):
- task = None
-
- items = job.items.order_by("index").all()
- failed_items = [i for i in items if i.fail_reason]
- items = [i for i in items if not i.fail_reason]
- return TemplateResponse(
- request,
- "import/import_status.html",
- {"job": job, "items": items, "failed_items": failed_items, "task": task},
- )
-
- def post(self, request, job_id):
- """retry lines from an import"""
- job = get_object_or_404(models.ImportJob, id=job_id)
- items = []
- for item in request.POST.getlist("import_item"):
- items.append(get_object_or_404(models.ImportItem, id=item))
-
- importer = Importer()
- job = importer.create_retry_job(
- request.user,
- job,
- items,
- )
- importer.start_import(job)
- return redirect(f"/import/{job.id}")
diff --git a/bookwyrm/views/imports/import_status.py b/bookwyrm/views/imports/import_status.py
new file mode 100644
index 000000000..26ff8cdec
--- /dev/null
+++ b/bookwyrm/views/imports/import_status.py
@@ -0,0 +1,79 @@
+""" import books from another app """
+import math
+
+from django.contrib.auth.decorators import login_required
+from django.core.exceptions import PermissionDenied
+from django.core.paginator import Paginator
+from django.shortcuts import get_object_or_404, redirect
+from django.template.response import TemplateResponse
+from django.utils import timezone
+from django.utils.decorators import method_decorator
+from django.views import View
+from django.views.decorators.http import require_POST
+
+from bookwyrm import models
+from bookwyrm.importers import GoodreadsImporter
+from bookwyrm.importers.importer import import_item_task
+from bookwyrm.settings import PAGE_LENGTH
+
+# pylint: disable= no-self-use
+@method_decorator(login_required, name="dispatch")
+class ImportStatus(View):
+ """status of an existing import"""
+
+ def get(self, request, job_id):
+ """status of an import job"""
+ job = get_object_or_404(models.ImportJob, id=job_id)
+ if job.user != request.user:
+ raise PermissionDenied()
+
+ items = job.items.order_by("index")
+ item_count = items.count() or 1
+
+ paginated = Paginator(items, PAGE_LENGTH)
+ page = paginated.get_page(request.GET.get("page"))
+ manual_review_count = items.filter(
+ fail_reason__isnull=False, book_guess__isnull=False, book__isnull=True
+ ).count()
+ fail_count = items.filter(
+ fail_reason__isnull=False, book_guess__isnull=True
+ ).count()
+ pending_item_count = job.pending_items.count()
+ data = {
+ "job": job,
+ "items": page,
+ "manual_review_count": manual_review_count,
+ "fail_count": fail_count,
+ "page_range": paginated.get_elided_page_range(
+ page.number, on_each_side=2, on_ends=1
+ ),
+ "item_count": item_count,
+ "complete_count": item_count - pending_item_count,
+ "percent": math.floor( # pylint: disable=c-extension-no-member
+ (item_count - pending_item_count) / item_count * 100
+ ),
+ # hours since last import item update
+ "inactive_time": (job.updated_date - timezone.now()).seconds / 60 / 60,
+ "legacy": not job.mappings,
+ }
+
+ return TemplateResponse(request, "import/import_status.html", data)
+
+ def post(self, request, job_id):
+ """bring a legacy import into the latest format"""
+ job = get_object_or_404(models.ImportJob, id=job_id)
+ if job.user != request.user:
+ raise PermissionDenied()
+ GoodreadsImporter().update_legacy_job(job)
+ return redirect("import-status", job_id)
+
+
+@login_required
+@require_POST
+def retry_item(request, job_id, item_id):
+ """retry an item"""
+ item = get_object_or_404(
+ models.ImportItem, id=item_id, job__id=job_id, job__user=request.user
+ )
+ import_item_task.delay(item.id)
+ return redirect("import-status", job_id)
diff --git a/bookwyrm/views/imports/manually_review.py b/bookwyrm/views/imports/manually_review.py
new file mode 100644
index 000000000..723fd4bba
--- /dev/null
+++ b/bookwyrm/views/imports/manually_review.py
@@ -0,0 +1,72 @@
+""" verify books we're unsure about """
+from django.contrib.auth.decorators import login_required
+from django.core.exceptions import PermissionDenied
+from django.core.paginator import Paginator
+from django.shortcuts import get_object_or_404, redirect
+from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
+from django.views import View
+from django.views.decorators.http import require_POST
+
+from bookwyrm import models
+from bookwyrm.importers.importer import import_item_task
+from bookwyrm.settings import PAGE_LENGTH
+
+# pylint: disable= no-self-use
+@method_decorator(login_required, name="dispatch")
+class ImportManualReview(View):
+ """problems items in an existing import"""
+
+ def get(self, request, job_id):
+ """status of an import job"""
+ job = get_object_or_404(models.ImportJob, id=job_id)
+ if job.user != request.user:
+ raise PermissionDenied()
+
+ items = job.items.order_by("index").filter(
+ book__isnull=True, book_guess__isnull=False
+ )
+
+ paginated = Paginator(items, PAGE_LENGTH)
+ page = paginated.get_page(request.GET.get("page"))
+ data = {
+ "job": job,
+ "items": page,
+ "page_range": paginated.get_elided_page_range(
+ page.number, on_each_side=2, on_ends=1
+ ),
+ "complete": True,
+ }
+
+ return TemplateResponse(request, "import/manual_review.html", data)
+
+
+@login_required
+@require_POST
+# pylint: disable=unused-argument
+def approve_import_item(request, job_id, item_id):
+ """we guessed right"""
+ item = get_object_or_404(
+ models.ImportItem, id=item_id, job__id=job_id, book_guess__isnull=False
+ )
+ item.fail_reason = None
+ item.book = item.book_guess
+ item.book_guess = None
+ item.save()
+
+ # the good stuff - actually import the data
+ import_item_task.delay(item.id)
+ return redirect("import-review", job_id)
+
+
+@login_required
+@require_POST
+# pylint: disable=unused-argument
+def delete_import_item(request, job_id, item_id):
+ """we guessed right"""
+ item = get_object_or_404(
+ models.ImportItem, id=item_id, job__id=job_id, book_guess__isnull=False
+ )
+ item.book_guess = None
+ item.save()
+ return redirect("import-review", job_id)
diff --git a/bookwyrm/views/imports/troubleshoot.py b/bookwyrm/views/imports/troubleshoot.py
new file mode 100644
index 000000000..f637b966b
--- /dev/null
+++ b/bookwyrm/views/imports/troubleshoot.py
@@ -0,0 +1,54 @@
+""" import books from another app """
+from django.contrib.auth.decorators import login_required
+from django.core.exceptions import PermissionDenied
+from django.core.paginator import Paginator
+from django.shortcuts import get_object_or_404, redirect
+from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
+from django.views import View
+
+from bookwyrm import models
+from bookwyrm.importers import Importer
+from bookwyrm.settings import PAGE_LENGTH
+
+# pylint: disable= no-self-use
+@method_decorator(login_required, name="dispatch")
+class ImportTroubleshoot(View):
+ """problems items in an existing import"""
+
+ def get(self, request, job_id):
+ """status of an import job"""
+ job = get_object_or_404(models.ImportJob, id=job_id)
+ if job.user != request.user:
+ raise PermissionDenied()
+
+ items = job.items.order_by("index").filter(
+ fail_reason__isnull=False, book_guess__isnull=True
+ )
+
+ paginated = Paginator(items, PAGE_LENGTH)
+ page = paginated.get_page(request.GET.get("page"))
+ data = {
+ "job": job,
+ "items": page,
+ "page_range": paginated.get_elided_page_range(
+ page.number, on_each_side=2, on_ends=1
+ ),
+ "complete": True,
+ }
+
+ return TemplateResponse(request, "import/troubleshoot.html", data)
+
+ def post(self, request, job_id):
+ """retry lines from an import"""
+ job = get_object_or_404(models.ImportJob, id=job_id)
+ items = job.items.filter(fail_reason__isnull=False)
+
+ importer = Importer()
+ job = importer.create_retry_job(
+ request.user,
+ job,
+ items,
+ )
+ importer.start_import(job)
+ return redirect(f"/import/{job.id}")
diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po
index 7d8fc801a..14bbb1b96 100644
--- a/locale/en_US/LC_MESSAGES/django.po
+++ b/locale/en_US/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-10-24 14:09+0000\n"
+"POT-Creation-Date: 2021-11-14 15:08+0000\n"
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
"Last-Translator: Mouse Reeve \n"
"Language-Team: English \n"
@@ -73,15 +73,16 @@ msgstr ""
msgid "Descending"
msgstr ""
-#: bookwyrm/importers/importer.py:75
+#: bookwyrm/importers/importer.py:127
msgid "Error loading book"
msgstr ""
-#: bookwyrm/importers/importer.py:88
+#: bookwyrm/importers/importer.py:135
msgid "Could not find a match for book"
msgstr ""
#: bookwyrm/models/base_model.py:17
+#: bookwyrm/templates/import/import_status.html:171
msgid "Pending"
msgstr ""
@@ -101,23 +102,23 @@ msgstr ""
msgid "Domain block"
msgstr ""
-#: bookwyrm/models/book.py:232
+#: bookwyrm/models/book.py:233
msgid "Audiobook"
msgstr ""
-#: bookwyrm/models/book.py:233
+#: bookwyrm/models/book.py:234
msgid "eBook"
msgstr ""
-#: bookwyrm/models/book.py:234
+#: bookwyrm/models/book.py:235
msgid "Graphic novel"
msgstr ""
-#: bookwyrm/models/book.py:235
+#: bookwyrm/models/book.py:236
msgid "Hardcover"
msgstr ""
-#: bookwyrm/models/book.py:236
+#: bookwyrm/models/book.py:237
msgid "Paperback"
msgstr ""
@@ -134,21 +135,21 @@ msgstr ""
msgid "Blocked"
msgstr ""
-#: bookwyrm/models/fields.py:27
+#: bookwyrm/models/fields.py:29
#, python-format
msgid "%(value)s is not a valid remote_id"
msgstr ""
-#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45
+#: bookwyrm/models/fields.py:38 bookwyrm/models/fields.py:47
#, python-format
msgid "%(value)s is not a valid username"
msgstr ""
-#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:171
+#: bookwyrm/models/fields.py:183 bookwyrm/templates/layout.html:171
msgid "username"
msgstr ""
-#: bookwyrm/models/fields.py:186
+#: bookwyrm/models/fields.py:188
msgid "A user with that username already exists."
msgstr ""
@@ -893,22 +894,37 @@ msgstr ""
msgid "All known users"
msgstr ""
-#: bookwyrm/templates/discover/card-header.html:9
+#: bookwyrm/templates/discover/card-header.html:8
#, python-format
-msgid "%(username)s rated %(book_title)s"
+msgid "%(username)s wants to read %(book_title)s"
msgstr ""
#: bookwyrm/templates/discover/card-header.html:13
#, python-format
+msgid "%(username)s finished reading %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/discover/card-header.html:18
+#, python-format
+msgid "%(username)s started reading %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/discover/card-header.html:23
+#, python-format
+msgid "%(username)s rated %(book_title)s"
+msgstr ""
+
+#: bookwyrm/templates/discover/card-header.html:27
+#, python-format
msgid "%(username)s reviewed %(book_title)s"
msgstr ""
-#: bookwyrm/templates/discover/card-header.html:17
+#: bookwyrm/templates/discover/card-header.html:31
#, python-format
msgid "%(username)s commented on %(book_title)s"
msgstr ""
-#: bookwyrm/templates/discover/card-header.html:21
+#: bookwyrm/templates/discover/card-header.html:35
#, python-format
msgid "%(username)s quoted %(book_title)s"
msgstr ""
@@ -1059,9 +1075,8 @@ msgstr ""
msgid "Updates"
msgstr ""
-#: bookwyrm/templates/feed/layout.html:12
-#: bookwyrm/templates/user/books_header.html:3
-msgid "Your books"
+#: bookwyrm/templates/feed/layout.html:12 bookwyrm/templates/layout.html:106
+msgid "Your Books"
msgstr ""
#: bookwyrm/templates/feed/layout.html:14
@@ -1070,11 +1085,13 @@ msgstr ""
#: bookwyrm/templates/feed/layout.html:25
#: bookwyrm/templates/shelf/shelf.html:38
+#: bookwyrm/templates/user/books_header.html:4
msgid "To Read"
msgstr ""
#: bookwyrm/templates/feed/layout.html:26
#: bookwyrm/templates/shelf/shelf.html:40
+#: bookwyrm/templates/user/books_header.html:6
msgid "Currently Reading"
msgstr ""
@@ -1082,6 +1099,7 @@ msgstr ""
#: bookwyrm/templates/shelf/shelf.html:42
#: bookwyrm/templates/snippets/shelve_button/shelve_button_dropdown_options.html:23
#: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12
+#: bookwyrm/templates/user/books_header.html:8
msgid "Read"
msgstr ""
@@ -1367,88 +1385,161 @@ msgid "No recent imports"
msgstr ""
#: bookwyrm/templates/import/import_status.html:6
-#: bookwyrm/templates/import/import_status.html:10
+#: bookwyrm/templates/import/import_status.html:15
+#: bookwyrm/templates/import/import_status.html:29
msgid "Import Status"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:11
-msgid "Back to imports"
+#: bookwyrm/templates/import/import_status.html:13
+#: bookwyrm/templates/import/import_status.html:27
+msgid "Retry Status"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:15
+#: bookwyrm/templates/import/import_status.html:22
+msgid "Imports"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:39
msgid "Import started:"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:20
-msgid "Import completed:"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:24
-msgid "TASK FAILED"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:32
-msgid "Import still in progress."
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:34
-msgid "(Hit reload to update!)"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:41
-msgid "Failed to load"
+#: bookwyrm/templates/import/import_status.html:48
+msgid "In progress"
msgstr ""
#: bookwyrm/templates/import/import_status.html:50
-#, python-format
-msgid "Jump to the bottom of the list to select the %(failed_count)s items which failed to import."
+msgid "Refresh"
msgstr ""
#: bookwyrm/templates/import/import_status.html:62
#, python-format
-msgid "Line %(index)s: %(title)s by %(author)s"
+msgid "%(display_counter)s item needs manual approval."
+msgid_plural "%(display_counter)s items need manual approval."
+msgstr[0] ""
+msgstr[1] ""
+
+#: bookwyrm/templates/import/import_status.html:67
+#: bookwyrm/templates/import/manual_review.html:8
+msgid "Review items"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:82
-msgid "Select all"
+#: bookwyrm/templates/import/import_status.html:73
+#, python-format
+msgid "%(display_counter)s item failed to import."
+msgid_plural "%(display_counter)s items failed to import."
+msgstr[0] ""
+msgstr[1] ""
+
+#: bookwyrm/templates/import/import_status.html:79
+msgid "View and troubleshoot failed items"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:85
-msgid "Retry items"
+#: bookwyrm/templates/import/import_status.html:91
+msgid "Row"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:112
-msgid "Successfully imported"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:114
-msgid "Import Progress"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:119
-msgid "Book"
-msgstr ""
-
-#: bookwyrm/templates/import/import_status.html:122
+#: bookwyrm/templates/import/import_status.html:94
#: bookwyrm/templates/shelf/shelf.html:141
#: bookwyrm/templates/shelf/shelf.html:163
msgid "Title"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:125
+#: bookwyrm/templates/import/import_status.html:97
+msgid "ISBN"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:100
#: bookwyrm/templates/shelf/shelf.html:142
#: bookwyrm/templates/shelf/shelf.html:166
msgid "Author"
msgstr ""
-#: bookwyrm/templates/import/import_status.html:148
+#: bookwyrm/templates/import/import_status.html:103
+msgid "Shelf"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:106
+#: bookwyrm/templates/import/manual_review.html:13
+#: bookwyrm/templates/snippets/create_status.html:17
+msgid "Review"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:110
+msgid "Book"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:113
+#: bookwyrm/templates/settings/announcements/announcements.html:38
+#: bookwyrm/templates/settings/federation/instance_list.html:46
+#: bookwyrm/templates/settings/invites/manage_invite_requests.html:44
+#: bookwyrm/templates/settings/invites/status_filter.html:5
+#: bookwyrm/templates/settings/users/user_admin.html:34
+#: bookwyrm/templates/settings/users/user_info.html:20
+msgid "Status"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:144
+msgid "View imported review"
+msgstr ""
+
+#: bookwyrm/templates/import/import_status.html:158
msgid "Imported"
msgstr ""
+#: bookwyrm/templates/import/import_status.html:164
+msgid "Needs manual review"
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:5
+#: bookwyrm/templates/import/troubleshoot.html:4
+msgid "Import Troubleshooting"
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:21
+msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book."
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:56
+#: bookwyrm/templates/lists/curate.html:57
+msgid "Approve"
+msgstr ""
+
+#: bookwyrm/templates/import/manual_review.html:64
+msgid "Reject"
+msgstr ""
+
#: bookwyrm/templates/import/tooltip.html:6
msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account."
msgstr ""
+#: bookwyrm/templates/import/troubleshoot.html:7
+msgid "Failed items"
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:12
+msgid "Troubleshooting"
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:20
+msgid "Re-trying an import can fix missing items in cases such as:"
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:23
+msgid "The book has been added to the instance since this import"
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:24
+msgid "A transient error or timeout caused the external data source to be unavailable."
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:25
+msgid "BookWyrm has been updated since this import with a bug fix"
+msgstr ""
+
+#: bookwyrm/templates/import/troubleshoot.html:28
+msgid "Contact your admin or open an issue if you are seeing unexpected failed items."
+msgstr ""
+
#: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230
#, python-format
msgid "About %(site_name)s"
@@ -1580,10 +1671,6 @@ msgstr ""
msgid "Feed"
msgstr ""
-#: bookwyrm/templates/layout.html:106
-msgid "Your Books"
-msgstr ""
-
#: bookwyrm/templates/layout.html:116
msgid "Settings"
msgstr ""
@@ -1683,10 +1770,6 @@ msgstr ""
msgid "Suggested by"
msgstr ""
-#: bookwyrm/templates/lists/curate.html:57
-msgid "Approve"
-msgstr ""
-
#: bookwyrm/templates/lists/curate.html:63
msgid "Discard"
msgstr ""
@@ -2239,15 +2322,6 @@ msgstr ""
msgid "End date"
msgstr ""
-#: bookwyrm/templates/settings/announcements/announcements.html:38
-#: bookwyrm/templates/settings/federation/instance_list.html:46
-#: bookwyrm/templates/settings/invites/manage_invite_requests.html:44
-#: bookwyrm/templates/settings/invites/status_filter.html:5
-#: bookwyrm/templates/settings/users/user_admin.html:34
-#: bookwyrm/templates/settings/users/user_info.html:20
-msgid "Status"
-msgstr ""
-
#: bookwyrm/templates/settings/announcements/announcements.html:48
msgid "active"
msgstr ""
@@ -3096,10 +3170,6 @@ msgstr ""
msgid "Un-boost"
msgstr ""
-#: bookwyrm/templates/snippets/create_status.html:17
-msgid "Review"
-msgstr ""
-
#: bookwyrm/templates/snippets/create_status.html:39
msgid "Quote"
msgstr ""
@@ -3526,7 +3596,7 @@ msgstr ""
msgid "commented on %(book)s"
msgstr ""
-#: bookwyrm/templates/snippets/status/headers/note.html:15
+#: bookwyrm/templates/snippets/status/headers/note.html:8
#, python-format
msgid "replied to %(username)s's status"
msgstr ""
@@ -3605,7 +3675,11 @@ msgstr ""
msgid "Show less"
msgstr ""
-#: bookwyrm/templates/user/books_header.html:5
+#: bookwyrm/templates/user/books_header.html:10
+msgid "Your books"
+msgstr ""
+
+#: bookwyrm/templates/user/books_header.html:15
#, python-format
msgid "%(username)s's books"
msgstr ""
@@ -3749,7 +3823,7 @@ msgstr ""
msgid "%(title)s: %(subtitle)s"
msgstr ""
-#: bookwyrm/views/import_data.py:67
+#: bookwyrm/views/imports/import_data.py:64
msgid "Not a valid csv file"
msgstr ""