1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.UtilsTest do
11 alias Pleroma.Web.ActivityPub.ActivityPub
12 alias Pleroma.Web.ActivityPub.Utils
13 alias Pleroma.Web.CommonAPI
15 import Pleroma.Factory
17 describe "fetch the latest Follow" do
18 test "fetches the latest Follow activity" do
19 %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
20 follower = User.get_cached_by_ap_id(activity.data["actor"])
21 followed = User.get_cached_by_ap_id(activity.data["object"])
23 assert activity == Utils.fetch_latest_follow(follower, followed)
27 describe "fetch the latest Block" do
28 test "fetches the latest Block activity" do
29 blocker = insert(:user)
30 blocked = insert(:user)
31 {:ok, activity} = ActivityPub.block(blocker, blocked)
33 assert activity == Utils.fetch_latest_block(blocker, blocked)
37 describe "determine_explicit_mentions()" do
38 test "works with an object that has mentions" do
43 "href" => "https://example.com/~alyssa",
44 "name" => "Alyssa P. Hacker"
49 assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
52 test "works with an object that does not have mentions" do
55 %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
59 assert Utils.determine_explicit_mentions(object) == []
62 test "works with an object that has mentions and other tags" do
67 "href" => "https://example.com/~alyssa",
68 "name" => "Alyssa P. Hacker"
70 %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
74 assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
77 test "works with an object that has no tags" do
80 assert Utils.determine_explicit_mentions(object) == []
83 test "works with an object that has only IR tags" do
84 object = %{"tag" => ["2hu"]}
86 assert Utils.determine_explicit_mentions(object) == []
90 describe "make_like_data" do
93 other_user = insert(:user)
94 third_user = insert(:user)
95 [user: user, other_user: other_user, third_user: third_user]
98 test "addresses actor's follower address if the activity is public", %{
100 other_user: other_user,
101 third_user: third_user
103 expected_to = Enum.sort([user.ap_id, other_user.follower_address])
104 expected_cc = Enum.sort(["https://www.w3.org/ns/activitystreams#Public", third_user.ap_id])
107 CommonAPI.post(user, %{
109 "hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
112 %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
113 assert Enum.sort(to) == expected_to
114 assert Enum.sort(cc) == expected_cc
117 test "does not adress actor's follower address if the activity is not public", %{
119 other_user: other_user,
120 third_user: third_user
122 expected_to = Enum.sort([user.ap_id])
123 expected_cc = [third_user.ap_id]
126 CommonAPI.post(user, %{
127 "status" => "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
128 "visibility" => "private"
131 %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
132 assert Enum.sort(to) == expected_to
133 assert Enum.sort(cc) == expected_cc
137 describe "fetch_ordered_collection" do
140 test "fetches the first OrderedCollectionPage when an OrderedCollection is encountered" do
142 %{method: :get, url: "http://mastodon.com/outbox"} ->
143 json(%{"type" => "OrderedCollection", "first" => "http://mastodon.com/outbox?page=true"})
145 %{method: :get, url: "http://mastodon.com/outbox?page=true"} ->
146 json(%{"type" => "OrderedCollectionPage", "orderedItems" => ["ok"]})
149 assert Utils.fetch_ordered_collection("http://mastodon.com/outbox", 1) == ["ok"]
152 test "fetches several pages in the right order one after another, but only the specified amount" do
154 %{method: :get, url: "http://example.com/outbox"} ->
156 "type" => "OrderedCollectionPage",
157 "orderedItems" => [0],
158 "next" => "http://example.com/outbox?page=1"
161 %{method: :get, url: "http://example.com/outbox?page=1"} ->
163 "type" => "OrderedCollectionPage",
164 "orderedItems" => [1],
165 "next" => "http://example.com/outbox?page=2"
168 %{method: :get, url: "http://example.com/outbox?page=2"} ->
169 json(%{"type" => "OrderedCollectionPage", "orderedItems" => [2]})
172 assert Utils.fetch_ordered_collection("http://example.com/outbox", 0) == [0]
173 assert Utils.fetch_ordered_collection("http://example.com/outbox", 1) == [0, 1]
176 test "returns an error if the url doesn't have an OrderedCollection/Page" do
178 %{method: :get, url: "http://example.com/not-an-outbox"} ->
179 json(%{"type" => "NotAnOutbox"})
182 assert {:error, _} = Utils.fetch_ordered_collection("http://example.com/not-an-outbox", 1)
185 test "returns the what was collected if there are less pages than specified" do
187 %{method: :get, url: "http://example.com/outbox"} ->
189 "type" => "OrderedCollectionPage",
190 "orderedItems" => [0],
191 "next" => "http://example.com/outbox?page=1"
194 %{method: :get, url: "http://example.com/outbox?page=1"} ->
195 json(%{"type" => "OrderedCollectionPage", "orderedItems" => [1]})
198 assert Utils.fetch_ordered_collection("http://example.com/outbox", 5) == [0, 1]
202 test "make_json_ld_header/0" do
203 assert Utils.make_json_ld_header() == %{
205 "https://www.w3.org/ns/activitystreams",
206 "http://localhost:4001/schemas/litepub-0.1.jsonld",
214 describe "get_existing_votes" do
215 test "fetches existing votes" do
217 other_user = insert(:user)
220 CommonAPI.post(user, %{
221 "status" => "How do I pronounce LaTeX?",
223 "options" => ["laytekh", "lahtekh", "latex"],
229 object = Object.normalize(activity)
230 {:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
231 assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
234 test "fetches only Create activities" do
236 other_user = insert(:user)
239 CommonAPI.post(user, %{
240 "status" => "Are we living in a society?",
242 "options" => ["yes", "no"],
247 object = Object.normalize(activity)
248 {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
249 vote_object = Object.normalize(vote)
250 {:ok, _activity, _object} = ActivityPub.like(user, vote_object)
251 [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
252 assert fetched_vote.id == vote.id
256 describe "update_follow_state_for_all/2" do
257 test "updates the state of all Follow activities with the same actor and object" do
258 user = insert(:user, info: %{locked: true})
259 follower = insert(:user)
261 {:ok, follow_activity} = ActivityPub.follow(follower, user)
262 {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
265 follow_activity_two.data
266 |> Map.put("state", "accept")
268 cng = Ecto.Changeset.change(follow_activity_two, data: data)
270 {:ok, follow_activity_two} = Repo.update(cng)
272 {:ok, follow_activity_two} =
273 Utils.update_follow_state_for_all(follow_activity_two, "accept")
275 assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
276 assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
280 describe "update_follow_state/2" do
281 test "updates the state of the given follow activity" do
282 user = insert(:user, info: %{locked: true})
283 follower = insert(:user)
285 {:ok, follow_activity} = ActivityPub.follow(follower, user)
286 {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
289 follow_activity_two.data
290 |> Map.put("state", "accept")
292 cng = Ecto.Changeset.change(follow_activity_two, data: data)
294 {:ok, follow_activity_two} = Repo.update(cng)
296 {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
298 assert Repo.get(Activity, follow_activity.id).data["state"] == "pending"
299 assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"