1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
6 use Oban.Testing, repo: Pleroma.Repo
11 alias Pleroma.Chat.MessageReference
12 alias Pleroma.Notification
15 alias Pleroma.Tests.ObanHelpers
17 alias Pleroma.Web.ActivityPub.ActivityPub
18 alias Pleroma.Web.ActivityPub.Builder
19 alias Pleroma.Web.ActivityPub.SideEffects
20 alias Pleroma.Web.CommonAPI
23 import Pleroma.Factory
25 describe "handle_after_transaction" do
26 test "it streams out notifications and streams" do
27 author = insert(:user, local: true)
28 recipient = insert(:user, local: true)
30 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
32 {:ok, create_activity_data, _meta} =
33 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
35 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
37 {:ok, _create_activity, meta} =
38 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
40 assert [notification] = meta[:notifications]
47 stream: fn _, _ -> nil end
58 SideEffects.handle_after_transaction(meta)
60 assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
61 assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
62 assert called(Pleroma.Web.Push.send(notification))
67 describe "blocking users" do
70 blocked = insert(:user)
71 User.follow(blocked, user)
72 User.follow(user, blocked)
74 {:ok, block_data, []} = Builder.block(user, blocked)
75 {:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
77 %{user: user, blocked: blocked, block: block}
80 test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
81 assert User.following?(user, blocked)
82 assert User.following?(blocked, user)
84 {:ok, _, _} = SideEffects.handle(block)
86 refute User.following?(user, blocked)
87 refute User.following?(blocked, user)
88 assert User.blocks?(user, blocked)
91 test "it updates following relationship", %{user: user, blocked: blocked, block: block} do
92 {:ok, _, _} = SideEffects.handle(block)
94 refute Pleroma.FollowingRelationship.get(user, blocked)
95 assert User.get_follow_state(user, blocked) == nil
96 assert User.get_follow_state(blocked, user) == nil
97 assert User.get_follow_state(user, blocked, nil) == nil
98 assert User.get_follow_state(blocked, user, nil) == nil
101 test "it blocks but does not unfollow if the relevant setting is set", %{
106 clear_config([:activitypub, :unfollow_blocked], false)
107 assert User.following?(user, blocked)
108 assert User.following?(blocked, user)
110 {:ok, _, _} = SideEffects.handle(block)
112 refute User.following?(user, blocked)
113 assert User.following?(blocked, user)
114 assert User.blocks?(user, blocked)
118 describe "update users" do
120 user = insert(:user, local: false)
122 {:ok, update_data, []} =
123 Builder.update(user, %{"id" => user.ap_id, "type" => "Person", "name" => "new name!"})
125 {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
127 %{user: user, update_data: update_data, update: update}
130 test "it updates the user", %{user: user, update: update} do
131 {:ok, _, _} = SideEffects.handle(update)
132 user = User.get_by_id(user.id)
133 assert user.name == "new name!"
136 test "it uses a given changeset to update", %{user: user, update: update} do
137 changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
139 assert user.default_scope == "public"
140 {:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
141 user = User.get_by_id(user.id)
142 assert user.default_scope == "direct"
146 describe "update notes" do
149 Pleroma.Web.ActivityPub.Utils.make_date()
153 note = insert(:note, user: user, data: %{"published" => make_time.()})
154 _note_activity = insert(:note_activity, note: note)
158 |> Map.put("summary", "edited summary")
159 |> Map.put("content", "edited content")
160 |> Map.put("updated", make_time.())
162 {:ok, update_data, []} = Builder.update(user, updated_note)
163 {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
169 update_data: update_data,
171 updated_note: updated_note
175 test "it updates the note", %{
176 object_id: object_id,
178 updated_note: updated_note
180 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
181 updated_time = updated_note["updated"]
183 new_note = Pleroma.Object.get_by_id(object_id)
186 "summary" => "edited summary",
187 "content" => "edited content",
188 "updated" => ^updated_time
192 test "it rejects updates with no updated attribute in object", %{
193 object_id: object_id,
195 updated_note: updated_note
197 old_note = Pleroma.Object.get_by_id(object_id)
198 updated_note = Map.drop(updated_note, ["updated"])
199 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
200 new_note = Pleroma.Object.get_by_id(object_id)
201 assert old_note.data == new_note.data
204 test "it rejects updates with updated attribute older than what we have in the original object",
206 object_id: object_id,
208 updated_note: updated_note
210 old_note = Pleroma.Object.get_by_id(object_id)
211 {:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
214 Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, -10)))
216 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
217 new_note = Pleroma.Object.get_by_id(object_id)
218 assert old_note.data == new_note.data
221 test "it rejects updates with updated attribute older than the last Update", %{
222 object_id: object_id,
224 updated_note: updated_note
226 old_note = Pleroma.Object.get_by_id(object_id)
227 {:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
230 Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, +10)))
232 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
234 old_note = Pleroma.Object.get_by_id(object_id)
235 {:ok, update_time, _} = DateTime.from_iso8601(old_note.data["updated"])
238 Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(update_time, -5)))
240 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
242 new_note = Pleroma.Object.get_by_id(object_id)
243 assert old_note.data == new_note.data
246 test "it updates using object_data", %{
247 object_id: object_id,
249 updated_note: updated_note
251 updated_note = Map.put(updated_note, "summary", "mew mew")
252 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
253 new_note = Pleroma.Object.get_by_id(object_id)
254 assert %{"summary" => "mew mew", "content" => "edited content"} = new_note.data
257 test "it records the original note in formerRepresentations", %{
259 object_id: object_id,
261 updated_note: updated_note
263 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
264 %{data: new_note} = Pleroma.Object.get_by_id(object_id)
265 assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
267 assert [Map.drop(note.data, ["id", "formerRepresentations"])] ==
268 new_note["formerRepresentations"]["orderedItems"]
270 assert new_note["formerRepresentations"]["totalItems"] == 1
273 test "it puts the original note at the front of formerRepresentations", %{
276 object_id: object_id,
278 updated_note: updated_note
280 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
281 %{data: first_edit} = Pleroma.Object.get_by_id(object_id)
283 second_updated_note =
285 |> Map.put("summary", "edited summary 2")
286 |> Map.put("content", "edited content 2")
289 first_edit["updated"]
290 |> DateTime.from_iso8601()
293 |> DateTime.to_iso8601()
296 {:ok, second_update_data, []} = Builder.update(user, second_updated_note)
297 {:ok, update, _meta} = ActivityPub.persist(second_update_data, local: true)
298 {:ok, _, _} = SideEffects.handle(update, object_data: second_updated_note)
299 %{data: new_note} = Pleroma.Object.get_by_id(object_id)
300 assert %{"summary" => "edited summary 2", "content" => "edited content 2"} = new_note
302 original_version = Map.drop(note.data, ["id", "formerRepresentations"])
303 first_edit = Map.drop(first_edit, ["id", "formerRepresentations"])
305 assert [first_edit, original_version] ==
306 new_note["formerRepresentations"]["orderedItems"]
308 assert new_note["formerRepresentations"]["totalItems"] == 2
311 test "it does not prepend to formerRepresentations if no actual changes are made", %{
313 object_id: object_id,
315 updated_note: updated_note
317 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
318 %{data: first_edit} = Pleroma.Object.get_by_id(object_id)
324 first_edit["updated"]
325 |> DateTime.from_iso8601()
328 |> DateTime.to_iso8601()
331 {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
332 %{data: new_note} = Pleroma.Object.get_by_id(object_id)
333 assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
335 original_version = Map.drop(note.data, ["id", "formerRepresentations"])
337 assert [original_version] ==
338 new_note["formerRepresentations"]["orderedItems"]
340 assert new_note["formerRepresentations"]["totalItems"] == 1
344 describe "update questions" do
351 data: %{"published" => Pleroma.Web.ActivityPub.Utils.make_date()}
354 %{user: user, data: question.data, id: question.id}
357 test "allows updating choice count without generating edit history", %{
364 |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
368 |> Map.put("oneOf", new_choices)
369 |> Map.put("updated", Pleroma.Web.ActivityPub.Utils.make_date())
371 {:ok, update_data, []} = Builder.update(user, updated_question)
372 {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
374 {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
376 %{data: new_question} = Pleroma.Object.get_by_id(id)
378 assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
379 new_question["oneOf"]
381 refute Map.has_key?(new_question, "formerRepresentations")
384 test "allows updating choice count without updated field", %{
391 |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
395 |> Map.put("oneOf", new_choices)
397 {:ok, update_data, []} = Builder.update(user, updated_question)
398 {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
400 {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
402 %{data: new_question} = Pleroma.Object.get_by_id(id)
404 assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
405 new_question["oneOf"]
407 refute Map.has_key?(new_question, "formerRepresentations")
410 test "allows updating choice count with updated field same as the creation date", %{
417 |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
421 |> Map.put("oneOf", new_choices)
422 |> Map.put("updated", data["published"])
424 {:ok, update_data, []} = Builder.update(user, updated_question)
425 {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
427 {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
429 %{data: new_question} = Pleroma.Object.get_by_id(id)
431 assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
432 new_question["oneOf"]
434 refute Map.has_key?(new_question, "formerRepresentations")
438 describe "EmojiReact objects" do
440 poster = insert(:user)
443 {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
445 {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
446 {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
448 %{emoji_react: emoji_react, user: user, poster: poster}
451 test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
452 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
453 object = Object.get_by_ap_id(emoji_react.data["object"])
455 assert object.data["reaction_count"] == 1
456 assert ["👌", [user.ap_id]] in object.data["reactions"]
459 test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
460 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
461 assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
465 describe "Question objects" do
468 question = build(:question, user: user)
469 question_activity = build(:question_activity, question: question)
470 activity_data = Map.put(question_activity.data, "object", question.data["id"])
471 meta = [object_data: question.data, local: false]
473 {:ok, activity, meta} = ActivityPub.persist(activity_data, meta)
475 %{activity: activity, meta: meta}
478 test "enqueues the poll end", %{activity: activity, meta: meta} do
479 {:ok, activity, meta} = SideEffects.handle(activity, meta)
482 worker: Pleroma.Workers.PollWorker,
483 args: %{op: "poll_end", activity_id: activity.id},
484 scheduled_at: NaiveDateTime.from_iso8601!(meta[:object_data]["closed"])
489 describe "delete users with confirmation pending" do
491 user = insert(:user, is_confirmed: false)
492 {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
493 {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
494 {:ok, delete: delete_user, user: user}
497 test "when activation is required", %{delete: delete, user: user} do
498 clear_config([:instance, :account_activation_required], true)
499 {:ok, _, _} = SideEffects.handle(delete)
500 ObanHelpers.perform_all()
502 refute User.get_cached_by_id(user.id)
506 describe "Undo objects" do
508 poster = insert(:user)
510 {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
511 {:ok, like} = CommonAPI.favorite(user, post.id)
512 {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
513 {:ok, announce} = CommonAPI.repeat(post.id, user)
514 {:ok, block} = CommonAPI.block(user, poster)
516 {:ok, undo_data, _meta} = Builder.undo(user, like)
517 {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
519 {:ok, undo_data, _meta} = Builder.undo(user, reaction)
520 {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
522 {:ok, undo_data, _meta} = Builder.undo(user, announce)
523 {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
525 {:ok, undo_data, _meta} = Builder.undo(user, block)
526 {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
529 like_undo: like_undo,
532 reaction_undo: reaction_undo,
534 announce_undo: announce_undo,
536 block_undo: block_undo,
543 test "deletes the original block", %{
544 block_undo: block_undo,
547 {:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
549 refute Activity.get_by_id(block.id)
552 test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
553 blocker = User.get_by_ap_id(block.data["actor"])
554 blocked = User.get_by_ap_id(block.data["object"])
556 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
557 refute User.blocks?(blocker, blocked)
560 test "an announce undo removes the announce from the object", %{
561 announce_undo: announce_undo,
564 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
566 object = Object.get_by_ap_id(post.data["object"])
568 assert object.data["announcement_count"] == 0
569 assert object.data["announcements"] == []
572 test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
573 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
574 refute Activity.get_by_id(announce.id)
577 test "a reaction undo removes the reaction from the object", %{
578 reaction_undo: reaction_undo,
581 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
583 object = Object.get_by_ap_id(post.data["object"])
585 assert object.data["reaction_count"] == 0
586 assert object.data["reactions"] == []
589 test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
590 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
591 refute Activity.get_by_id(reaction.id)
594 test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
595 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
597 object = Object.get_by_ap_id(post.data["object"])
599 assert object.data["like_count"] == 0
600 assert object.data["likes"] == []
603 test "deletes the original like", %{like_undo: like_undo, like: like} do
604 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
605 refute Activity.get_by_id(like.id)
609 describe "like objects" do
611 poster = insert(:user)
613 {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
615 {:ok, like_data, _meta} = Builder.like(user, post.object)
616 {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
618 %{like: like, user: user, poster: poster}
621 test "add the like to the original object", %{like: like, user: user} do
622 {:ok, like, _} = SideEffects.handle(like)
623 object = Object.get_by_ap_id(like.data["object"])
624 assert object.data["like_count"] == 1
625 assert user.ap_id in object.data["likes"]
628 test "creates a notification", %{like: like, poster: poster} do
629 {:ok, like, _} = SideEffects.handle(like)
630 assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
634 describe "creation of ChatMessages" do
635 test "notifies the recipient" do
636 author = insert(:user, local: false)
637 recipient = insert(:user, local: true)
639 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
641 {:ok, create_activity_data, _meta} =
642 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
644 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
646 {:ok, _create_activity, _meta} =
647 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
649 assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id)
652 test "it streams the created ChatMessage" do
653 author = insert(:user, local: true)
654 recipient = insert(:user, local: true)
656 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
658 {:ok, create_activity_data, _meta} =
659 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
661 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
663 {:ok, _create_activity, meta} =
664 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
666 assert [_, _] = meta[:streamables]
669 test "it creates a Chat and MessageReferences for the local users and bumps the unread count, except for the author" do
670 author = insert(:user, local: true)
671 recipient = insert(:user, local: true)
673 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
675 {:ok, create_activity_data, _meta} =
676 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
678 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
682 Pleroma.Web.Streamer,
685 stream: fn _, _ -> nil end
692 send: fn _ -> nil end
696 {:ok, _create_activity, meta} =
697 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
699 # The notification gets created
700 assert [notification] = meta[:notifications]
701 assert notification.activity_id == create_activity.id
703 # But it is not sent out
704 refute called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
705 refute called(Pleroma.Web.Push.send(notification))
707 # Same for the user chat stream
708 assert [{topics, _}, _] = meta[:streamables]
709 assert topics == ["user", "user:pleroma_chat"]
710 refute called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
712 chat = Chat.get(author.id, recipient.ap_id)
714 [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
716 assert cm_ref.object.data["content"] == "hey"
717 assert cm_ref.unread == false
719 chat = Chat.get(recipient.id, author.ap_id)
721 [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
723 assert cm_ref.object.data["content"] == "hey"
724 assert cm_ref.unread == true
728 test "it creates a Chat for the local users and bumps the unread count" do
729 author = insert(:user, local: false)
730 recipient = insert(:user, local: true)
732 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
734 {:ok, create_activity_data, _meta} =
735 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
737 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
739 {:ok, _create_activity, _meta} =
740 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
742 # An object is created
743 assert Object.get_by_ap_id(chat_message_data["id"])
745 # The remote user won't get a chat
746 chat = Chat.get(author.id, recipient.ap_id)
749 # The local user will get a chat
750 chat = Chat.get(recipient.id, author.ap_id)
753 author = insert(:user, local: true)
754 recipient = insert(:user, local: true)
756 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
758 {:ok, create_activity_data, _meta} =
759 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
761 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
763 {:ok, _create_activity, _meta} =
764 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
766 # Both users are local and get the chat
767 chat = Chat.get(author.id, recipient.ap_id)
770 chat = Chat.get(recipient.id, author.ap_id)
775 describe "announce objects" do
777 poster = insert(:user)
779 {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
780 {:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
782 {:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
784 {:ok, private_announce_data, _meta} =
785 Builder.announce(user, private_post.object, public: false)
787 {:ok, relay_announce_data, _meta} =
788 Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
790 {:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
791 {:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
792 {:ok, relay_announce, _meta} = ActivityPub.persist(relay_announce_data, local: true)
798 private_announce: private_announce,
799 relay_announce: relay_announce
803 test "adds the announce to the original object", %{announce: announce, user: user} do
804 {:ok, announce, _} = SideEffects.handle(announce)
805 object = Object.get_by_ap_id(announce.data["object"])
806 assert object.data["announcement_count"] == 1
807 assert user.ap_id in object.data["announcements"]
810 test "does not add the announce to the original object if the actor is a service actor", %{
811 relay_announce: announce
813 {:ok, announce, _} = SideEffects.handle(announce)
814 object = Object.get_by_ap_id(announce.data["object"])
815 assert object.data["announcement_count"] == nil
818 test "creates a notification", %{announce: announce, poster: poster} do
819 {:ok, announce, _} = SideEffects.handle(announce)
820 assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
823 test "it streams out the announce", %{announce: announce} do
826 Pleroma.Web.Streamer,
829 stream: fn _, _ -> nil end
836 send: fn _ -> nil end
840 {:ok, announce, _} = SideEffects.handle(announce)
842 assert called(Pleroma.Web.Streamer.stream(["user", "list"], announce))
844 assert called(Pleroma.Web.Push.send(:_))
849 describe "removing a follower" do
852 followed = insert(:user)
854 {:ok, _, _, follow_activity} = CommonAPI.follow(user, followed)
856 {:ok, reject_data, []} = Builder.reject(followed, follow_activity)
857 {:ok, reject, _meta} = ActivityPub.persist(reject_data, local: true)
859 %{user: user, followed: followed, reject: reject}
862 test "", %{user: user, followed: followed, reject: reject} do
863 assert User.following?(user, followed)
864 assert Pleroma.FollowingRelationship.get(user, followed)
866 {:ok, _, _} = SideEffects.handle(reject)
868 refute User.following?(user, followed)
869 refute Pleroma.FollowingRelationship.get(user, followed)
870 assert User.get_follow_state(user, followed) == nil
871 assert User.get_follow_state(user, followed, nil) == nil
875 describe "removing a follower from remote" do
878 followed = insert(:user, local: false)
880 # Mock a local-to-remote follow
881 {:ok, follow_data, []} = Builder.follow(user, followed)
885 |> Map.put("state", "accept")
887 {:ok, follow, _meta} = ActivityPub.persist(follow_data, local: true)
888 {:ok, _, _} = SideEffects.handle(follow)
890 # Mock a remote-to-local accept
891 {:ok, accept_data, _} = Builder.accept(followed, follow)
892 {:ok, accept, _} = ActivityPub.persist(accept_data, local: false)
893 {:ok, _, _} = SideEffects.handle(accept)
895 # Mock a remote-to-local reject
896 {:ok, reject_data, []} = Builder.reject(followed, follow)
897 {:ok, reject, _meta} = ActivityPub.persist(reject_data, local: false)
899 %{user: user, followed: followed, reject: reject}
902 test "", %{user: user, followed: followed, reject: reject} do
903 assert User.following?(user, followed)
904 assert Pleroma.FollowingRelationship.get(user, followed)
906 {:ok, _, _} = SideEffects.handle(reject)
908 refute User.following?(user, followed)
909 refute Pleroma.FollowingRelationship.get(user, followed)
911 assert Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, followed).data["state"] ==
914 assert User.get_follow_state(user, followed) == nil
915 assert User.get_follow_state(user, followed, nil) == nil