From 220f2c1eb4b214887ce43df95c0407f6043f5ea8 Mon Sep 17 00:00:00 2001
From: Mouse Reeve <mousereeve@riseup.net>
Date: Mon, 15 Mar 2021 13:55:48 -0700
Subject: [PATCH] Fixes image attachments

---
 bookwyrm/activitypub/image.py        |  4 +--
 bookwyrm/models/activitypub_mixin.py |  6 +++-
 bookwyrm/models/attachment.py        |  6 +++-
 bookwyrm/tests/views/test_feed.py    | 45 ++++++++++++++++++++++++++--
 4 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/bookwyrm/activitypub/image.py b/bookwyrm/activitypub/image.py
index 248e7a4a..931de977 100644
--- a/bookwyrm/activitypub/image.py
+++ b/bookwyrm/activitypub/image.py
@@ -9,5 +9,5 @@ class Image(ActivityObject):
 
     url: str
     name: str = ""
-    type: str = "Image"
-    id: str = ""
+    type: str = "Document"
+    id: str = None
diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py
index 0a3c33a1..23ac1642 100644
--- a/bookwyrm/models/activitypub_mixin.py
+++ b/bookwyrm/models/activitypub_mixin.py
@@ -445,7 +445,11 @@ def unfurl_related_field(related_field, sort_field=None):
             unfurl_related_field(i) for i in related_field.order_by(sort_field).all()
         ]
     if related_field.reverse_unfurl:
-        return related_field.field_to_activity()
+        # if it's a one-to-one (key pair)
+        if hasattr(related_field, "field_to_activity"):
+            return related_field.field_to_activity()
+        # if it's one-to-many (attachments)
+        return related_field.to_activity()
     return related_field.remote_id
 
 
diff --git a/bookwyrm/models/attachment.py b/bookwyrm/models/attachment.py
index 0cd2c111..8d2238a1 100644
--- a/bookwyrm/models/attachment.py
+++ b/bookwyrm/models/attachment.py
@@ -25,7 +25,11 @@ class Image(Attachment):
     """ an image attachment """
 
     image = fields.ImageField(
-        upload_to="status/", null=True, blank=True, activitypub_field="url"
+        upload_to="status/",
+        null=True,
+        blank=True,
+        activitypub_field="url",
+        alt_field="caption",
     )
     caption = fields.TextField(null=True, blank=True, activitypub_field="name")
 
diff --git a/bookwyrm/tests/views/test_feed.py b/bookwyrm/tests/views/test_feed.py
index c54be006..42668467 100644
--- a/bookwyrm/tests/views/test_feed.py
+++ b/bookwyrm/tests/views/test_feed.py
@@ -1,5 +1,10 @@
 """ test for app action functionality """
+from io import BytesIO
 from unittest.mock import patch
+import pathlib
+
+from PIL import Image
+from django.core.files.base import ContentFile
 from django.template.response import TemplateResponse
 from django.test import TestCase
 from django.test.client import RequestFactory
@@ -9,8 +14,8 @@ from bookwyrm import views
 from bookwyrm.activitypub import ActivitypubResponse
 
 
-class FeedMessageViews(TestCase):
-    """ dms """
+class FeedViews(TestCase):
+    """ activity feed, statuses, dms """
 
     def setUp(self):
         """ we need basic test data and mocks """
@@ -59,6 +64,42 @@ class FeedMessageViews(TestCase):
         self.assertIsInstance(result, ActivitypubResponse)
         self.assertEqual(result.status_code, 200)
 
+    def test_status_page_with_image(self):
+        """ there are so many views, this just makes sure it LOADS """
+        view = views.Status.as_view()
+
+        image_file = pathlib.Path(__file__).parent.joinpath(
+            "../../static/images/default_avi.jpg"
+        )
+        image = Image.open(image_file)
+        output = BytesIO()
+        image.save(output, format=image.format)
+        with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
+            status = models.Review.objects.create(
+                content="hi",
+                user=self.local_user,
+                book=self.book,
+            )
+            attachment = models.Image.objects.create(
+                status=status, caption="alt text here"
+            )
+            attachment.image.save("test.jpg", ContentFile(output.getvalue()))
+
+        request = self.factory.get("")
+        request.user = self.local_user
+        with patch("bookwyrm.views.feed.is_api_request") as is_api:
+            is_api.return_value = False
+            result = view(request, "mouse", status.id)
+        self.assertIsInstance(result, TemplateResponse)
+        result.render()
+        self.assertEqual(result.status_code, 200)
+
+        with patch("bookwyrm.views.feed.is_api_request") as is_api:
+            is_api.return_value = True
+            result = view(request, "mouse", status.id)
+        self.assertIsInstance(result, ActivitypubResponse)
+        self.assertEqual(result.status_code, 200)
+
     def test_replies_page(self):
         """ there are so many views, this just makes sure it LOADS """
         view = views.Replies.as_view()