1 # Pleroma: A lightweight social networking server
2 # Copyright © 2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.PublisherTest do
8 import ExUnit.CaptureLog
13 alias Pleroma.Activity
14 alias Pleroma.Instances
15 alias Pleroma.Web.ActivityPub.Publisher
17 @as_public "https://www.w3.org/ns/activitystreams#Public"
20 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
24 describe "determine_inbox/2" do
25 test "it returns sharedInbox for messages involving as:Public in to" do
28 info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
32 data: %{"to" => [@as_public], "cc" => [user.follower_address]}
35 assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
38 test "it returns sharedInbox for messages involving as:Public in cc" do
41 info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
45 data: %{"cc" => [@as_public], "to" => [user.follower_address]}
48 assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
51 test "it returns sharedInbox for messages involving multiple recipients in to" do
54 info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
57 user_two = insert(:user)
58 user_three = insert(:user)
61 data: %{"cc" => [], "to" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
64 assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
67 test "it returns sharedInbox for messages involving multiple recipients in cc" do
70 info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}}
73 user_two = insert(:user)
74 user_three = insert(:user)
77 data: %{"to" => [], "cc" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
80 assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
83 test "it returns sharedInbox for messages involving multiple recipients in total" do
88 "inbox" => "http://example.com/personal-inbox",
89 "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
94 user_two = insert(:user)
97 data: %{"to" => [user_two.ap_id], "cc" => [user.ap_id]}
100 assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
103 test "it returns inbox for messages involving single recipients in total" do
108 "inbox" => "http://example.com/personal-inbox",
109 "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
114 activity = %Activity{
115 data: %{"to" => [user.ap_id], "cc" => []}
118 assert Publisher.determine_inbox(activity, user) == "http://example.com/personal-inbox"
122 describe "publish_one/1" do
123 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
127 actor = insert(:user)
128 inbox = "http://200.site/users/nick1/inbox"
130 assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
132 assert called(Instances.set_reachable(inbox))
135 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
139 actor = insert(:user)
140 inbox = "http://200.site/users/nick1/inbox"
143 Publisher.publish_one(%{
148 unreachable_since: NaiveDateTime.utc_now()
151 assert called(Instances.set_reachable(inbox))
154 test_with_mock "does NOT call `Instances.set_reachable` on successful federation if `unreachable_since` is nil",
158 actor = insert(:user)
159 inbox = "http://200.site/users/nick1/inbox"
162 Publisher.publish_one(%{
167 unreachable_since: nil
170 refute called(Instances.set_reachable(inbox))
173 test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
177 actor = insert(:user)
178 inbox = "http://404.site/users/nick1/inbox"
180 assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
182 assert called(Instances.set_unreachable(inbox))
185 test_with_mock "it calls `Instances.set_unreachable` on target inbox on request error of any kind",
189 actor = insert(:user)
190 inbox = "http://connrefused.site/users/nick1/inbox"
192 assert capture_log(fn ->
194 Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
195 end) =~ "connrefused"
197 assert called(Instances.set_unreachable(inbox))
200 test_with_mock "does NOT call `Instances.set_unreachable` if target is reachable",
204 actor = insert(:user)
205 inbox = "http://200.site/users/nick1/inbox"
207 assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
209 refute called(Instances.set_unreachable(inbox))
212 test_with_mock "does NOT call `Instances.set_unreachable` if target instance has non-nil `unreachable_since`",
216 actor = insert(:user)
217 inbox = "http://connrefused.site/users/nick1/inbox"
219 assert capture_log(fn ->
221 Publisher.publish_one(%{
226 unreachable_since: NaiveDateTime.utc_now()
228 end) =~ "connrefused"
230 refute called(Instances.set_unreachable(inbox))
234 describe "publish/2" do
235 test_with_mock "publishes an activity with BCC to all relevant peers.",
236 Pleroma.Web.Federator.Publisher,
244 source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}
248 actor = insert(:user, follower_address: follower.ap_id)
251 {:ok, _follower_one} = Pleroma.User.follow(follower, actor)
252 actor = refresh_record(actor)
255 insert(:note_activity,
256 recipients: [follower.ap_id],
257 data_attrs: %{"bcc" => [user.ap_id]}
260 res = Publisher.publish(actor, note_activity)
264 Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
265 inbox: "https://domain.com/users/nick1/inbox",
267 id: note_activity.data["id"]