1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.UtilsTest do
6 use Pleroma.DataCase, async: true
11 alias Pleroma.Web.ActivityPub.Utils
12 alias Pleroma.Web.AdminAPI.AccountView
13 alias Pleroma.Web.CommonAPI
15 import Pleroma.Factory
17 require Pleroma.Constants
19 describe "fetch the latest Follow" do
20 test "fetches the latest Follow activity" do
21 %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
22 follower = User.get_cached_by_ap_id(activity.data["actor"])
23 followed = User.get_cached_by_ap_id(activity.data["object"])
25 assert activity == Utils.fetch_latest_follow(follower, followed)
29 describe "determine_explicit_mentions()" do
30 test "works with an object that has mentions" do
35 "href" => "https://example.com/~alyssa",
36 "name" => "Alyssa P. Hacker"
41 assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
44 test "works with an object that does not have mentions" do
47 %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
51 assert Utils.determine_explicit_mentions(object) == []
54 test "works with an object that has mentions and other tags" do
59 "href" => "https://example.com/~alyssa",
60 "name" => "Alyssa P. Hacker"
62 %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
66 assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
69 test "works with an object that has no tags" do
72 assert Utils.determine_explicit_mentions(object) == []
75 test "works with an object that has only IR tags" do
76 object = %{"tag" => ["2hu"]}
78 assert Utils.determine_explicit_mentions(object) == []
81 test "works with an object has tags as map" do
85 "href" => "https://example.com/~alyssa",
86 "name" => "Alyssa P. Hacker"
90 assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
94 describe "make_like_data" do
97 other_user = insert(:user)
98 third_user = insert(:user)
99 [user: user, other_user: other_user, third_user: third_user]
102 test "addresses actor's follower address if the activity is public", %{
104 other_user: other_user,
105 third_user: third_user
107 expected_to = Enum.sort([user.ap_id, other_user.follower_address])
108 expected_cc = Enum.sort(["https://www.w3.org/ns/activitystreams#Public", third_user.ap_id])
111 CommonAPI.post(user, %{
113 "hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
116 %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
117 assert Enum.sort(to) == expected_to
118 assert Enum.sort(cc) == expected_cc
121 test "does not adress actor's follower address if the activity is not public", %{
123 other_user: other_user,
124 third_user: third_user
126 expected_to = Enum.sort([user.ap_id])
127 expected_cc = [third_user.ap_id]
130 CommonAPI.post(user, %{
131 status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
132 visibility: "private"
135 %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
136 assert Enum.sort(to) == expected_to
137 assert Enum.sort(cc) == expected_cc
141 test "make_json_ld_header/0" do
142 assert Utils.make_json_ld_header() == %{
144 "https://www.w3.org/ns/activitystreams",
145 "http://localhost:4001/schemas/litepub-0.1.jsonld",
153 describe "get_existing_votes" do
154 test "fetches existing votes" do
156 other_user = insert(:user)
159 CommonAPI.post(user, %{
160 status: "How do I pronounce LaTeX?",
162 options: ["laytekh", "lahtekh", "latex"],
168 object = Object.normalize(activity, fetch: false)
169 {:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
170 assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
173 test "fetches only Create activities" do
175 other_user = insert(:user)
178 CommonAPI.post(user, %{
179 status: "Are we living in a society?",
181 options: ["yes", "no"],
186 object = Object.normalize(activity, fetch: false)
187 {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
188 {:ok, _activity} = CommonAPI.favorite(user, activity.id)
189 [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
190 assert fetched_vote.id == vote.id
194 describe "update_follow_state_for_all/2" do
195 test "updates the state of all Follow activities with the same actor and object" do
196 user = insert(:user, is_locked: true)
197 follower = insert(:user)
199 {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
200 {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
203 follow_activity_two.data
204 |> Map.put("state", "accept")
206 cng = Ecto.Changeset.change(follow_activity_two, data: data)
208 {:ok, follow_activity_two} = Repo.update(cng)
210 {:ok, follow_activity_two} =
211 Utils.update_follow_state_for_all(follow_activity_two, "accept")
213 assert refresh_record(follow_activity).data["state"] == "accept"
214 assert refresh_record(follow_activity_two).data["state"] == "accept"
218 describe "update_follow_state/2" do
219 test "updates the state of the given follow activity" do
220 user = insert(:user, is_locked: true)
221 follower = insert(:user)
223 {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
224 {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
227 follow_activity_two.data
228 |> Map.put("state", "accept")
230 cng = Ecto.Changeset.change(follow_activity_two, data: data)
232 {:ok, follow_activity_two} = Repo.update(cng)
234 {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
236 assert refresh_record(follow_activity).data["state"] == "pending"
237 assert refresh_record(follow_activity_two).data["state"] == "reject"
241 describe "update_element_in_object/3" do
242 test "updates likes" do
244 activity = insert(:note_activity)
245 object = Object.normalize(activity, fetch: false)
247 assert {:ok, updated_object} =
248 Utils.update_element_in_object(
254 assert updated_object.data["likes"] == [user.ap_id]
255 assert updated_object.data["like_count"] == 1
259 describe "add_like_to_object/2" do
260 test "add actor to likes" do
262 user2 = insert(:user)
263 object = insert(:note)
265 assert {:ok, updated_object} =
266 Utils.add_like_to_object(
267 %Activity{data: %{"actor" => user.ap_id}},
271 assert updated_object.data["likes"] == [user.ap_id]
272 assert updated_object.data["like_count"] == 1
274 assert {:ok, updated_object2} =
275 Utils.add_like_to_object(
276 %Activity{data: %{"actor" => user2.ap_id}},
280 assert updated_object2.data["likes"] == [user2.ap_id, user.ap_id]
281 assert updated_object2.data["like_count"] == 2
285 describe "remove_like_from_object/2" do
286 test "removes ap_id from likes" do
288 user2 = insert(:user)
289 object = insert(:note, data: %{"likes" => [user.ap_id, user2.ap_id], "like_count" => 2})
291 assert {:ok, updated_object} =
292 Utils.remove_like_from_object(
293 %Activity{data: %{"actor" => user.ap_id}},
297 assert updated_object.data["likes"] == [user2.ap_id]
298 assert updated_object.data["like_count"] == 1
302 describe "get_existing_like/2" do
303 test "fetches existing like" do
304 note_activity = insert(:note_activity)
305 assert object = Object.normalize(note_activity, fetch: false)
308 refute Utils.get_existing_like(user.ap_id, object)
309 {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
311 assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
315 describe "get_get_existing_announce/2" do
316 test "returns nil if announce not found" do
317 actor = insert(:user)
318 refute Utils.get_existing_announce(actor.ap_id, %{data: %{"id" => "test"}})
321 test "fetches existing announce" do
322 note_activity = insert(:note_activity)
323 assert object = Object.normalize(note_activity, fetch: false)
324 actor = insert(:user)
326 {:ok, announce} = CommonAPI.repeat(note_activity.id, actor)
327 assert Utils.get_existing_announce(actor.ap_id, object) == announce
331 describe "fetch_latest_block/2" do
332 test "fetches last block activities" do
333 user1 = insert(:user)
334 user2 = insert(:user)
336 assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
337 assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
338 assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
340 assert Utils.fetch_latest_block(user1, user2) == activity
344 describe "recipient_in_message/3" do
345 test "returns true when recipient in `to`" do
346 recipient = insert(:user)
347 actor = insert(:user)
348 assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
350 assert Utils.recipient_in_message(
353 %{"to" => [recipient.ap_id], "cc" => ""}
357 test "returns true when recipient in `cc`" do
358 recipient = insert(:user)
359 actor = insert(:user)
360 assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
362 assert Utils.recipient_in_message(
365 %{"cc" => [recipient.ap_id], "to" => ""}
369 test "returns true when recipient in `bto`" do
370 recipient = insert(:user)
371 actor = insert(:user)
372 assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
374 assert Utils.recipient_in_message(
377 %{"bcc" => "", "bto" => [recipient.ap_id]}
381 test "returns true when recipient in `bcc`" do
382 recipient = insert(:user)
383 actor = insert(:user)
384 assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
386 assert Utils.recipient_in_message(
389 %{"bto" => "", "bcc" => [recipient.ap_id]}
393 test "returns true when message without addresses fields" do
394 recipient = insert(:user)
395 actor = insert(:user)
396 assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
398 assert Utils.recipient_in_message(
401 %{"btod" => "", "bccc" => [recipient.ap_id]}
405 test "returns false" do
406 recipient = insert(:user)
407 actor = insert(:user)
408 refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
412 describe "lazy_put_activity_defaults/2" do
413 test "returns map with id and published data" do
414 note_activity = insert(:note_activity)
415 object = Object.normalize(note_activity, fetch: false)
416 res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
417 assert res["context"] == object.data["id"]
418 assert res["context_id"] == object.id
420 assert res["published"]
423 test "returns map with fake id and published data" do
425 "context" => "pleroma:fakecontext",
427 "id" => "pleroma:fakeid",
429 } = Utils.lazy_put_activity_defaults(%{}, true)
432 test "returns activity data with object" do
433 note_activity = insert(:note_activity)
434 object = Object.normalize(note_activity, fetch: false)
437 Utils.lazy_put_activity_defaults(%{
438 "context" => object.data["id"],
442 assert res["context"] == object.data["id"]
443 assert res["context_id"] == object.id
445 assert res["published"]
446 assert res["object"]["id"]
447 assert res["object"]["published"]
448 assert res["object"]["context"] == object.data["id"]
449 assert res["object"]["context_id"] == object.id
453 describe "make_flag_data" do
454 test "returns empty map when params is invalid" do
455 assert Utils.make_flag_data(%{}, %{}) == %{}
458 test "returns map with Flag object" do
459 reporter = insert(:user)
460 target_account = insert(:user)
461 {:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"})
462 context = Utils.generate_context_id()
465 target_ap_id = target_account.ap_id
466 activity_ap_id = activity.data["id"]
469 Utils.make_flag_data(
473 account: target_account,
474 statuses: [%{"id" => activity.data["id"]}],
482 "id" => activity_ap_id,
483 "content" => content,
484 "published" => activity.object.data["published"],
486 AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
491 "content" => ^content,
492 "context" => ^context,
493 "object" => [^target_ap_id, ^note_obj],
499 describe "add_announce_to_object/2" do
500 test "adds actor to announcement" do
502 object = insert(:note)
505 insert(:note_activity,
507 "actor" => user.ap_id,
508 "cc" => [Pleroma.Constants.as_public()]
512 assert {:ok, updated_object} = Utils.add_announce_to_object(activity, object)
513 assert updated_object.data["announcements"] == [user.ap_id]
514 assert updated_object.data["announcement_count"] == 1
518 describe "remove_announce_from_object/2" do
519 test "removes actor from announcements" do
521 user2 = insert(:user)
525 data: %{"announcements" => [user.ap_id, user2.ap_id], "announcement_count" => 2}
528 activity = insert(:note_activity, data: %{"actor" => user.ap_id})
530 assert {:ok, updated_object} = Utils.remove_announce_from_object(activity, object)
531 assert updated_object.data["announcements"] == [user2.ap_id]
532 assert updated_object.data["announcement_count"] == 1
536 describe "get_cached_emoji_reactions/1" do
537 test "returns the data or an emtpy list" do
538 object = insert(:note)
539 assert Utils.get_cached_emoji_reactions(object) == []
541 object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]})
542 assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"]]]
544 object = insert(:note, data: %{"reactions" => %{}})
545 assert Utils.get_cached_emoji_reactions(object) == []