provide full replies collection in ActivityPub objects

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
Oneric 2025-10-09 10:15:26 +02:00 committed by nicole mikołajczyk
commit 03210f487d
15 changed files with 430 additions and 158 deletions

View file

@ -430,6 +430,75 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
end
describe "/objects/:uuid/replies" do
test "it renders the top-level collection", %{
conn: conn
} do
user = insert(:user)
note = insert(:note_activity)
note = Pleroma.Activity.get_by_id_with_object(note.id)
uuid = String.split(note.object.data["id"], "/") |> List.last()
{:ok, _} =
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: note.id})
conn =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/objects/#{uuid}/replies")
assert match?(
%{
"id" => _,
"type" => "OrderedCollection",
"totalItems" => 1,
"first" => %{
"id" => _,
"type" => "OrderedCollectionPage",
"orderedItems" => [_]
}
},
json_response(conn, 200)
)
end
test "it renders a collection page", %{
conn: conn
} do
user = insert(:user)
note = insert(:note_activity)
note = Pleroma.Activity.get_by_id_with_object(note.id)
uuid = String.split(note.object.data["id"], "/") |> List.last()
{:ok, r1} =
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: note.id})
{:ok, r2} =
CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: note.id})
{:ok, _} =
CommonAPI.post(user, %{status: "reply3", in_reply_to_status_id: note.id})
conn =
conn
|> put_req_header("accept", "application/activity+json")
|> get("/objects/#{uuid}/replies?page=true&min_id=#{r1.object.id}&limit=1")
expected_uris = [r2.object.data["id"]]
assert match?(
%{
"id" => _,
"type" => "OrderedCollectionPage",
"prev" => _,
"next" => _,
"orderedItems" => ^expected_uris
},
json_response(conn, 200)
)
end
end
describe "/activities/:uuid" do
test "it doesn't return a local-only activity", %{conn: conn} do
user = insert(:user)

View file

@ -696,12 +696,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
describe "set_replies/1" do
setup do: clear_config([:activitypub, :note_replies_output_limit], 2)
test "returns unmodified object if activity doesn't have self-replies" do
test "still provides reply collection id even if activity doesn't have replies yet" do
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
assert Transmogrifier.set_replies(data) == data
modified = Transmogrifier.set_replies(data)
refute data["replies"]
assert modified["replies"]
assert match?(%{"id" => "http" <> _, "totalItems" => 0}, modified["replies"])
# first page should be omitted if there are no entries anyway
refute modified["replies"]["first"]
end
test "sets `replies` collection with a limited number of self-replies" do
test "sets `replies` collection with a limited number of replies, preferring oldest" do
[user, another_user] = insert_list(2, :user)
{:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"})
@ -730,7 +736,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
object = Object.normalize(activity, fetch: false)
replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
assert %{"type" => "Collection", "items" => ^replies_uris} =
assert %{"type" => "OrderedCollection", "first" => %{"orderedItems" => ^replies_uris}} =
Transmogrifier.set_replies(object.data)["replies"]
end
end

View file

@ -49,9 +49,39 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
replies_uris = [self_reply1.object.data["id"]]
result = ObjectView.render("object.json", %{object: refresh_record(activity)})
assert %{"type" => "Collection", "items" => ^replies_uris} =
assert %{
"type" => "OrderedCollection",
"id" => _,
"first" => %{"orderedItems" => ^replies_uris}
} =
get_in(result, ["object", "replies"])
end
test "renders a replies collection on its own" do
user = insert(:user)
activity = insert(:note_activity, user: user)
activity = Pleroma.Activity.get_by_id_with_object(activity.id)
{:ok, r1} =
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id})
{:ok, r2} =
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id})
replies_uris = [r1.object.data["id"], r2.object.data["id"]]
result =
ObjectView.render("object_replies.json", %{
render_params: %{object_ap_id: activity.object.data["id"]}
})
%{
"type" => "OrderedCollection",
"id" => _,
"totalItems" => 2,
"first" => %{"orderedItems" => ^replies_uris}
} = result
end
end
test "renders a like activity" do