Merge branch 'feature/jobs' into 'develop'
[akkoma] / test / web / activity_pub / activity_pub_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
6 use Pleroma.DataCase
7 alias Pleroma.Web.ActivityPub.ActivityPub
8 alias Pleroma.Web.ActivityPub.Utils
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Activity
11 alias Pleroma.Object
12 alias Pleroma.User
13 alias Pleroma.Instances
14 alias Pleroma.Builders.ActivityBuilder
15
16 import Pleroma.Factory
17 import Tesla.Mock
18 import Mock
19
20 setup do
21 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
22 :ok
23 end
24
25 describe "fetching restricted by visibility" do
26 test "it restricts by the appropriate visibility" do
27 user = insert(:user)
28
29 {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
30
31 {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
32
33 {:ok, unlisted_activity} =
34 CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
35
36 {:ok, private_activity} =
37 CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
38
39 activities =
40 ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id})
41
42 assert activities == [direct_activity]
43
44 activities =
45 ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id})
46
47 assert activities == [unlisted_activity]
48
49 activities =
50 ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id})
51
52 assert activities == [private_activity]
53
54 activities =
55 ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id})
56
57 assert activities == [public_activity]
58 end
59 end
60
61 describe "building a user from his ap id" do
62 test "it returns a user" do
63 user_id = "http://mastodon.example.org/users/admin"
64 {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
65 assert user.ap_id == user_id
66 assert user.nickname == "admin@mastodon.example.org"
67 assert user.info.source_data
68 assert user.info.ap_enabled
69 assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
70 end
71
72 test "it fetches the appropriate tag-restricted posts" do
73 user = insert(:user)
74
75 {:ok, status_one} = CommonAPI.post(user, %{"status" => ". #test"})
76 {:ok, status_two} = CommonAPI.post(user, %{"status" => ". #essais"})
77 {:ok, status_three} = CommonAPI.post(user, %{"status" => ". #test #reject"})
78
79 fetch_one = ActivityPub.fetch_activities([], %{"tag" => "test"})
80 fetch_two = ActivityPub.fetch_activities([], %{"tag" => ["test", "essais"]})
81
82 fetch_three =
83 ActivityPub.fetch_activities([], %{
84 "tag" => ["test", "essais"],
85 "tag_reject" => ["reject"]
86 })
87
88 fetch_four =
89 ActivityPub.fetch_activities([], %{
90 "tag" => ["test"],
91 "tag_all" => ["test", "reject"]
92 })
93
94 assert fetch_one == [status_one, status_three]
95 assert fetch_two == [status_one, status_two, status_three]
96 assert fetch_three == [status_one, status_two]
97 assert fetch_four == [status_three]
98 end
99 end
100
101 describe "insertion" do
102 test "drops activities beyond a certain limit" do
103 limit = Pleroma.Config.get([:instance, :remote_limit])
104
105 random_text =
106 :crypto.strong_rand_bytes(limit + 1)
107 |> Base.encode64()
108 |> binary_part(0, limit + 1)
109
110 data = %{
111 "ok" => true,
112 "object" => %{
113 "content" => random_text
114 }
115 }
116
117 assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data)
118 end
119
120 test "doesn't drop activities with content being null" do
121 data = %{
122 "ok" => true,
123 "object" => %{
124 "content" => nil
125 }
126 }
127
128 assert {:ok, _} = ActivityPub.insert(data)
129 end
130
131 test "returns the activity if one with the same id is already in" do
132 activity = insert(:note_activity)
133 {:ok, new_activity} = ActivityPub.insert(activity.data)
134
135 assert activity == new_activity
136 end
137
138 test "inserts a given map into the activity database, giving it an id if it has none." do
139 data = %{
140 "ok" => true
141 }
142
143 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
144 assert activity.data["ok"] == data["ok"]
145 assert is_binary(activity.data["id"])
146
147 given_id = "bla"
148
149 data = %{
150 "ok" => true,
151 "id" => given_id,
152 "context" => "blabla"
153 }
154
155 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
156 assert activity.data["ok"] == data["ok"]
157 assert activity.data["id"] == given_id
158 assert activity.data["context"] == "blabla"
159 assert activity.data["context_id"]
160 end
161
162 test "adds a context when none is there" do
163 data = %{
164 "id" => "some_id",
165 "object" => %{
166 "id" => "object_id"
167 }
168 }
169
170 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
171
172 assert is_binary(activity.data["context"])
173 assert is_binary(activity.data["object"]["context"])
174 assert activity.data["context_id"]
175 assert activity.data["object"]["context_id"]
176 end
177
178 test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
179 data = %{
180 "object" => %{
181 "type" => "Note",
182 "ok" => true
183 }
184 }
185
186 {:ok, %Activity{} = activity} = ActivityPub.insert(data)
187 assert is_binary(activity.data["object"]["id"])
188 assert %Object{} = Object.get_by_ap_id(activity.data["object"]["id"])
189 end
190 end
191
192 describe "create activities" do
193 test "removes doubled 'to' recipients" do
194 user = insert(:user)
195
196 {:ok, activity} =
197 ActivityPub.create(%{
198 to: ["user1", "user1", "user2"],
199 actor: user,
200 context: "",
201 object: %{}
202 })
203
204 assert activity.data["to"] == ["user1", "user2"]
205 assert activity.actor == user.ap_id
206 assert activity.recipients == ["user1", "user2", user.ap_id]
207 end
208 end
209
210 describe "fetch activities for recipients" do
211 test "retrieve the activities for certain recipients" do
212 {:ok, activity_one} = ActivityBuilder.insert(%{"to" => ["someone"]})
213 {:ok, activity_two} = ActivityBuilder.insert(%{"to" => ["someone_else"]})
214 {:ok, _activity_three} = ActivityBuilder.insert(%{"to" => ["noone"]})
215
216 activities = ActivityPub.fetch_activities(["someone", "someone_else"])
217 assert length(activities) == 2
218 assert activities == [activity_one, activity_two]
219 end
220 end
221
222 describe "fetch activities in context" do
223 test "retrieves activities that have a given context" do
224 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
225 {:ok, activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
226 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
227 {:ok, _activity_four} = ActivityBuilder.insert(%{"type" => "Announce", "context" => "2hu"})
228 activity_five = insert(:note_activity)
229 user = insert(:user)
230
231 {:ok, user} = User.block(user, %{ap_id: activity_five.data["actor"]})
232
233 activities = ActivityPub.fetch_activities_for_context("2hu", %{"blocking_user" => user})
234 assert activities == [activity_two, activity]
235 end
236 end
237
238 test "doesn't return blocked activities" do
239 activity_one = insert(:note_activity)
240 activity_two = insert(:note_activity)
241 activity_three = insert(:note_activity)
242 user = insert(:user)
243 booster = insert(:user)
244 {:ok, user} = User.block(user, %{ap_id: activity_one.data["actor"]})
245
246 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
247
248 assert Enum.member?(activities, activity_two)
249 assert Enum.member?(activities, activity_three)
250 refute Enum.member?(activities, activity_one)
251
252 {:ok, user} = User.unblock(user, %{ap_id: activity_one.data["actor"]})
253
254 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
255
256 assert Enum.member?(activities, activity_two)
257 assert Enum.member?(activities, activity_three)
258 assert Enum.member?(activities, activity_one)
259
260 {:ok, user} = User.block(user, %{ap_id: activity_three.data["actor"]})
261 {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.repeat(activity_three.id, booster)
262 %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id)
263 activity_three = Repo.get(Activity, activity_three.id)
264
265 activities = ActivityPub.fetch_activities([], %{"blocking_user" => user})
266
267 assert Enum.member?(activities, activity_two)
268 refute Enum.member?(activities, activity_three)
269 refute Enum.member?(activities, boost_activity)
270 assert Enum.member?(activities, activity_one)
271
272 activities = ActivityPub.fetch_activities([], %{"blocking_user" => nil})
273
274 assert Enum.member?(activities, activity_two)
275 assert Enum.member?(activities, activity_three)
276 assert Enum.member?(activities, boost_activity)
277 assert Enum.member?(activities, activity_one)
278 end
279
280 test "excludes reblogs on request" do
281 user = insert(:user)
282 {:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user})
283 {:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user})
284
285 [activity] = ActivityPub.fetch_user_activities(user, nil, %{"exclude_reblogs" => "true"})
286
287 assert activity == expected_activity
288 end
289
290 describe "public fetch activities" do
291 test "doesn't retrieve unlisted activities" do
292 user = insert(:user)
293
294 {:ok, _unlisted_activity} =
295 CommonAPI.post(user, %{"status" => "yeah", "visibility" => "unlisted"})
296
297 {:ok, listed_activity} = CommonAPI.post(user, %{"status" => "yeah"})
298
299 [activity] = ActivityPub.fetch_public_activities()
300
301 assert activity == listed_activity
302 end
303
304 test "retrieves public activities" do
305 _activities = ActivityPub.fetch_public_activities()
306
307 %{public: public} = ActivityBuilder.public_and_non_public()
308
309 activities = ActivityPub.fetch_public_activities()
310 assert length(activities) == 1
311 assert Enum.at(activities, 0) == public
312 end
313
314 test "retrieves a maximum of 20 activities" do
315 activities = ActivityBuilder.insert_list(30)
316 last_expected = List.last(activities)
317
318 activities = ActivityPub.fetch_public_activities()
319 last = List.last(activities)
320
321 assert length(activities) == 20
322 assert last == last_expected
323 end
324
325 test "retrieves ids starting from a since_id" do
326 activities = ActivityBuilder.insert_list(30)
327 later_activities = ActivityBuilder.insert_list(10)
328 since_id = List.last(activities).id
329 last_expected = List.last(later_activities)
330
331 activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id})
332 last = List.last(activities)
333
334 assert length(activities) == 10
335 assert last == last_expected
336 end
337
338 test "retrieves ids up to max_id" do
339 _first_activities = ActivityBuilder.insert_list(10)
340 activities = ActivityBuilder.insert_list(20)
341 later_activities = ActivityBuilder.insert_list(10)
342 max_id = List.first(later_activities).id
343 last_expected = List.last(activities)
344
345 activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id})
346 last = List.last(activities)
347
348 assert length(activities) == 20
349 assert last == last_expected
350 end
351 end
352
353 describe "like an object" do
354 test "adds a like activity to the db" do
355 note_activity = insert(:note_activity)
356 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
357 user = insert(:user)
358 user_two = insert(:user)
359
360 {:ok, like_activity, object} = ActivityPub.like(user, object)
361
362 assert like_activity.data["actor"] == user.ap_id
363 assert like_activity.data["type"] == "Like"
364 assert like_activity.data["object"] == object.data["id"]
365 assert like_activity.data["to"] == [User.ap_followers(user), note_activity.data["actor"]]
366 assert like_activity.data["context"] == object.data["context"]
367 assert object.data["like_count"] == 1
368 assert object.data["likes"] == [user.ap_id]
369
370 # Just return the original activity if the user already liked it.
371 {:ok, same_like_activity, object} = ActivityPub.like(user, object)
372
373 assert like_activity == same_like_activity
374 assert object.data["likes"] == [user.ap_id]
375
376 [note_activity] = Activity.get_all_create_by_object_ap_id(object.data["id"])
377 assert note_activity.data["object"]["like_count"] == 1
378
379 {:ok, _like_activity, object} = ActivityPub.like(user_two, object)
380 assert object.data["like_count"] == 2
381 end
382 end
383
384 describe "unliking" do
385 test "unliking a previously liked object" do
386 note_activity = insert(:note_activity)
387 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
388 user = insert(:user)
389
390 # Unliking something that hasn't been liked does nothing
391 {:ok, object} = ActivityPub.unlike(user, object)
392 assert object.data["like_count"] == 0
393
394 {:ok, like_activity, object} = ActivityPub.like(user, object)
395 assert object.data["like_count"] == 1
396
397 {:ok, _, _, object} = ActivityPub.unlike(user, object)
398 assert object.data["like_count"] == 0
399
400 assert Repo.get(Activity, like_activity.id) == nil
401 end
402 end
403
404 describe "announcing an object" do
405 test "adds an announce activity to the db" do
406 note_activity = insert(:note_activity)
407 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
408 user = insert(:user)
409
410 {:ok, announce_activity, object} = ActivityPub.announce(user, object)
411 assert object.data["announcement_count"] == 1
412 assert object.data["announcements"] == [user.ap_id]
413
414 assert announce_activity.data["to"] == [
415 User.ap_followers(user),
416 note_activity.data["actor"]
417 ]
418
419 assert announce_activity.data["object"] == object.data["id"]
420 assert announce_activity.data["actor"] == user.ap_id
421 assert announce_activity.data["context"] == object.data["context"]
422 end
423 end
424
425 describe "unannouncing an object" do
426 test "unannouncing a previously announced object" do
427 note_activity = insert(:note_activity)
428 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
429 user = insert(:user)
430
431 # Unannouncing an object that is not announced does nothing
432 # {:ok, object} = ActivityPub.unannounce(user, object)
433 # assert object.data["announcement_count"] == 0
434
435 {:ok, announce_activity, object} = ActivityPub.announce(user, object)
436 assert object.data["announcement_count"] == 1
437
438 {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object)
439 assert object.data["announcement_count"] == 0
440
441 assert unannounce_activity.data["to"] == [
442 User.ap_followers(user),
443 announce_activity.data["actor"]
444 ]
445
446 assert unannounce_activity.data["type"] == "Undo"
447 assert unannounce_activity.data["object"] == announce_activity.data
448 assert unannounce_activity.data["actor"] == user.ap_id
449 assert unannounce_activity.data["context"] == announce_activity.data["context"]
450
451 assert Repo.get(Activity, announce_activity.id) == nil
452 end
453 end
454
455 describe "uploading files" do
456 test "copies the file to the configured folder" do
457 file = %Plug.Upload{
458 content_type: "image/jpg",
459 path: Path.absname("test/fixtures/image.jpg"),
460 filename: "an_image.jpg"
461 }
462
463 {:ok, %Object{} = object} = ActivityPub.upload(file)
464 assert object.data["name"] == "an_image.jpg"
465 end
466
467 test "works with base64 encoded images" do
468 file = %{
469 "img" => data_uri()
470 }
471
472 {:ok, %Object{}} = ActivityPub.upload(file)
473 end
474 end
475
476 describe "fetch the latest Follow" do
477 test "fetches the latest Follow activity" do
478 %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
479 follower = Repo.get_by(User, ap_id: activity.data["actor"])
480 followed = Repo.get_by(User, ap_id: activity.data["object"])
481
482 assert activity == Utils.fetch_latest_follow(follower, followed)
483 end
484 end
485
486 describe "fetching an object" do
487 test "it fetches an object" do
488 {:ok, object} =
489 ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
490
491 assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
492 assert activity.data["id"]
493
494 {:ok, object_again} =
495 ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
496
497 assert [attachment] = object.data["attachment"]
498 assert is_list(attachment["url"])
499
500 assert object == object_again
501 end
502
503 test "it works with objects only available via Ostatus" do
504 {:ok, object} = ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
505 assert activity = Activity.get_create_by_object_ap_id(object.data["id"])
506 assert activity.data["id"]
507
508 {:ok, object_again} =
509 ActivityPub.fetch_object_from_id("https://shitposter.club/notice/2827873")
510
511 assert object == object_again
512 end
513
514 test "it correctly stitches up conversations between ostatus and ap" do
515 last = "https://mstdn.io/users/mayuutann/statuses/99568293732299394"
516 {:ok, object} = ActivityPub.fetch_object_from_id(last)
517
518 object = Object.get_by_ap_id(object.data["inReplyTo"])
519 assert object
520 end
521 end
522
523 describe "following / unfollowing" do
524 test "creates a follow activity" do
525 follower = insert(:user)
526 followed = insert(:user)
527
528 {:ok, activity} = ActivityPub.follow(follower, followed)
529 assert activity.data["type"] == "Follow"
530 assert activity.data["actor"] == follower.ap_id
531 assert activity.data["object"] == followed.ap_id
532 end
533
534 test "creates an undo activity for the last follow" do
535 follower = insert(:user)
536 followed = insert(:user)
537
538 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
539 {:ok, activity} = ActivityPub.unfollow(follower, followed)
540
541 assert activity.data["type"] == "Undo"
542 assert activity.data["actor"] == follower.ap_id
543
544 assert is_map(activity.data["object"])
545 assert activity.data["object"]["type"] == "Follow"
546 assert activity.data["object"]["object"] == followed.ap_id
547 assert activity.data["object"]["id"] == follow_activity.data["id"]
548 end
549 end
550
551 describe "blocking / unblocking" do
552 test "creates a block activity" do
553 blocker = insert(:user)
554 blocked = insert(:user)
555
556 {:ok, activity} = ActivityPub.block(blocker, blocked)
557
558 assert activity.data["type"] == "Block"
559 assert activity.data["actor"] == blocker.ap_id
560 assert activity.data["object"] == blocked.ap_id
561 end
562
563 test "creates an undo activity for the last block" do
564 blocker = insert(:user)
565 blocked = insert(:user)
566
567 {:ok, block_activity} = ActivityPub.block(blocker, blocked)
568 {:ok, activity} = ActivityPub.unblock(blocker, blocked)
569
570 assert activity.data["type"] == "Undo"
571 assert activity.data["actor"] == blocker.ap_id
572
573 assert is_map(activity.data["object"])
574 assert activity.data["object"]["type"] == "Block"
575 assert activity.data["object"]["object"] == blocked.ap_id
576 assert activity.data["object"]["id"] == block_activity.data["id"]
577 end
578 end
579
580 describe "deletion" do
581 test "it creates a delete activity and deletes the original object" do
582 note = insert(:note_activity)
583 object = Object.get_by_ap_id(note.data["object"]["id"])
584 {:ok, delete} = ActivityPub.delete(object)
585
586 assert delete.data["type"] == "Delete"
587 assert delete.data["actor"] == note.data["actor"]
588 assert delete.data["object"] == note.data["object"]["id"]
589
590 assert Repo.get(Activity, delete.id) != nil
591
592 assert Repo.get(Object, object.id).data["type"] == "Tombstone"
593 end
594 end
595
596 describe "timeline post-processing" do
597 test "it filters broken threads" do
598 user1 = insert(:user)
599 user2 = insert(:user)
600 user3 = insert(:user)
601
602 {:ok, user1} = User.follow(user1, user3)
603 assert User.following?(user1, user3)
604
605 {:ok, user2} = User.follow(user2, user3)
606 assert User.following?(user2, user3)
607
608 {:ok, user3} = User.follow(user3, user2)
609 assert User.following?(user3, user2)
610
611 {:ok, public_activity} = CommonAPI.post(user3, %{"status" => "hi 1"})
612
613 {:ok, private_activity_1} =
614 CommonAPI.post(user3, %{"status" => "hi 2", "visibility" => "private"})
615
616 {:ok, private_activity_2} =
617 CommonAPI.post(user2, %{
618 "status" => "hi 3",
619 "visibility" => "private",
620 "in_reply_to_status_id" => private_activity_1.id
621 })
622
623 {:ok, private_activity_3} =
624 CommonAPI.post(user3, %{
625 "status" => "hi 4",
626 "visibility" => "private",
627 "in_reply_to_status_id" => private_activity_2.id
628 })
629
630 activities = ActivityPub.fetch_activities([user1.ap_id | user1.following])
631
632 assert [public_activity, private_activity_1, private_activity_3] == activities
633 assert length(activities) == 3
634
635 activities = ActivityPub.contain_timeline(activities, user1)
636
637 assert [public_activity, private_activity_1] == activities
638 assert length(activities) == 2
639 end
640 end
641
642 test "it can fetch plume articles" do
643 {:ok, object} =
644 ActivityPub.fetch_object_from_id(
645 "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"
646 )
647
648 assert object
649 end
650
651 describe "update" do
652 test "it creates an update activity with the new user data" do
653 user = insert(:user)
654 {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
655 user_data = Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
656
657 {:ok, update} =
658 ActivityPub.update(%{
659 actor: user_data["id"],
660 to: [user.follower_address],
661 cc: [],
662 object: user_data
663 })
664
665 assert update.data["actor"] == user.ap_id
666 assert update.data["to"] == [user.follower_address]
667 assert update.data["object"]["id"] == user_data["id"]
668 assert update.data["object"]["type"] == user_data["type"]
669 end
670 end
671
672 test "it can fetch peertube videos" do
673 {:ok, object} =
674 ActivityPub.fetch_object_from_id(
675 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
676 )
677
678 assert object
679 end
680
681 test "returned pinned statuses" do
682 Pleroma.Config.put([:instance, :max_pinned_statuses], 3)
683 user = insert(:user)
684
685 {:ok, activity_one} = CommonAPI.post(user, %{"status" => "HI!!!"})
686 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
687 {:ok, activity_three} = CommonAPI.post(user, %{"status" => "HI!!!"})
688
689 CommonAPI.pin(activity_one.id, user)
690 user = refresh_record(user)
691
692 CommonAPI.pin(activity_two.id, user)
693 user = refresh_record(user)
694
695 CommonAPI.pin(activity_three.id, user)
696 user = refresh_record(user)
697
698 activities = ActivityPub.fetch_user_activities(user, nil, %{"pinned" => "true"})
699
700 assert 3 = length(activities)
701 end
702
703 describe "publish_one/1" do
704 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
705 Instances,
706 [:passthrough],
707 [] do
708 actor = insert(:user)
709 inbox = "http://200.site/users/nick1/inbox"
710
711 assert {:ok, _} = ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
712
713 assert called(Instances.set_reachable(inbox))
714 end
715
716 test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
717 Instances,
718 [:passthrough],
719 [] do
720 actor = insert(:user)
721 inbox = "http://200.site/users/nick1/inbox"
722
723 assert {:ok, _} =
724 ActivityPub.publish_one(%{
725 inbox: inbox,
726 json: "{}",
727 actor: actor,
728 id: 1,
729 unreachable_since: NaiveDateTime.utc_now()
730 })
731
732 assert called(Instances.set_reachable(inbox))
733 end
734
735 test_with_mock "does NOT call `Instances.set_reachable` on successful federation if `unreachable_since` is nil",
736 Instances,
737 [:passthrough],
738 [] do
739 actor = insert(:user)
740 inbox = "http://200.site/users/nick1/inbox"
741
742 assert {:ok, _} =
743 ActivityPub.publish_one(%{
744 inbox: inbox,
745 json: "{}",
746 actor: actor,
747 id: 1,
748 unreachable_since: nil
749 })
750
751 refute called(Instances.set_reachable(inbox))
752 end
753
754 test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
755 Instances,
756 [:passthrough],
757 [] do
758 actor = insert(:user)
759 inbox = "http://404.site/users/nick1/inbox"
760
761 assert {:error, _} =
762 ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
763
764 assert called(Instances.set_unreachable(inbox))
765 end
766
767 test_with_mock "it calls `Instances.set_unreachable` on target inbox on request error of any kind",
768 Instances,
769 [:passthrough],
770 [] do
771 actor = insert(:user)
772 inbox = "http://connrefused.site/users/nick1/inbox"
773
774 assert {:error, _} =
775 ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
776
777 assert called(Instances.set_unreachable(inbox))
778 end
779
780 test_with_mock "does NOT call `Instances.set_unreachable` if target is reachable",
781 Instances,
782 [:passthrough],
783 [] do
784 actor = insert(:user)
785 inbox = "http://200.site/users/nick1/inbox"
786
787 assert {:ok, _} = ActivityPub.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
788
789 refute called(Instances.set_unreachable(inbox))
790 end
791
792 test_with_mock "does NOT call `Instances.set_unreachable` if target instance has non-nil `unreachable_since`",
793 Instances,
794 [:passthrough],
795 [] do
796 actor = insert(:user)
797 inbox = "http://connrefused.site/users/nick1/inbox"
798
799 assert {:error, _} =
800 ActivityPub.publish_one(%{
801 inbox: inbox,
802 json: "{}",
803 actor: actor,
804 id: 1,
805 unreachable_since: NaiveDateTime.utc_now()
806 })
807
808 refute called(Instances.set_unreachable(inbox))
809 end
810 end
811
812 def data_uri do
813 File.read!("test/fixtures/avatar_data_uri")
814 end
815 end