1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.NotificationTest do
11 alias Pleroma.FollowingRelationship
12 alias Pleroma.Notification
13 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Builder
17 alias Pleroma.Web.ActivityPub.Transmogrifier
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.MastodonAPI.NotificationView
20 alias Pleroma.Web.Push
21 alias Pleroma.Web.Streamer
23 describe "create_notifications" do
24 test "creates a notification for an emoji reaction" do
26 other_user = insert(:user)
28 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
29 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
31 {:ok, [notification]} = Notification.create_notifications(activity)
33 assert notification.user_id == user.id
36 test "notifies someone when they are directly addressed" do
38 other_user = insert(:user)
39 third_user = insert(:user)
42 CommonAPI.post(user, %{
43 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
46 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
48 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
49 assert notified_ids == [other_user.id, third_user.id]
50 assert notification.activity_id == activity.id
51 assert other_notification.activity_id == activity.id
53 assert [%Pleroma.Marker{unread_count: 2}] =
54 Pleroma.Marker.get_markers(other_user, ["notifications"])
57 test "it creates a notification for subscribed users" do
59 subscriber = insert(:user)
61 User.subscribe(subscriber, user)
63 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
64 {:ok, [notification]} = Notification.create_notifications(status)
66 assert notification.user_id == subscriber.id
69 test "does not create a notification for subscribed users if status is a reply" do
71 other_user = insert(:user)
72 subscriber = insert(:user)
74 User.subscribe(subscriber, other_user)
76 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
78 {:ok, _reply_activity} =
79 CommonAPI.post(other_user, %{
81 in_reply_to_status_id: activity.id
84 user_notifications = Notification.for_user(user)
85 assert length(user_notifications) == 1
87 subscriber_notifications = Notification.for_user(subscriber)
88 assert Enum.empty?(subscriber_notifications)
92 describe "CommonApi.post/2 notification-related functionality" do
93 test_with_mock "creates but does NOT send notification to blocker user",
98 blocker = insert(:user)
99 {:ok, _user_relationship} = User.block(blocker, user)
101 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
103 blocker_id = blocker.id
104 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
105 refute called(Push.send(:_))
108 test_with_mock "creates but does NOT send notification to notification-muter user",
113 muter = insert(:user)
114 {:ok, _user_relationships} = User.mute(muter, user)
116 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
119 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
120 refute called(Push.send(:_))
123 test_with_mock "creates but does NOT send notification to thread-muter user",
128 thread_muter = insert(:user)
130 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
132 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
134 {:ok, _same_context_activity} =
135 CommonAPI.post(user, %{
136 status: "hey-hey-hey @#{thread_muter.nickname}!",
137 in_reply_to_status_id: activity.id
140 [pre_mute_notification, post_mute_notification] =
141 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
143 pre_mute_notification_id = pre_mute_notification.id
144 post_mute_notification_id = post_mute_notification.id
149 %Notification{id: ^pre_mute_notification_id} -> true
158 %Notification{id: ^post_mute_notification_id} -> true
166 describe "create_notification" do
167 @tag needs_streamer: true
168 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
173 Streamer.get_topic_and_add_socket("user", user)
174 assert_receive {:render_with_user, _, _, _}, 4_000
177 task_user_notification =
179 Streamer.get_topic_and_add_socket("user:notification", user)
180 assert_receive {:render_with_user, _, _, _}, 4_000
183 activity = insert(:note_activity)
185 notify = Notification.create_notification(activity, user)
186 assert notify.user_id == user.id
188 Task.await(task_user_notification)
191 test "it creates a notification for user if the user blocks the activity author" do
192 activity = insert(:note_activity)
193 author = User.get_cached_by_ap_id(activity.data["actor"])
195 {:ok, _user_relationship} = User.block(user, author)
197 assert Notification.create_notification(activity, user)
200 test "it creates a notification for the user if the user mutes the activity author" do
201 muter = insert(:user)
202 muted = insert(:user)
203 {:ok, _} = User.mute(muter, muted)
204 muter = Repo.get(User, muter.id)
205 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
207 assert Notification.create_notification(activity, muter)
210 test "notification created if user is muted without notifications" do
211 muter = insert(:user)
212 muted = insert(:user)
214 {:ok, _user_relationships} = User.mute(muter, muted, false)
216 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
218 assert Notification.create_notification(activity, muter)
221 test "it creates a notification for an activity from a muted thread" do
222 muter = insert(:user)
223 other_user = insert(:user)
224 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
225 CommonAPI.add_mute(muter, activity)
228 CommonAPI.post(other_user, %{
229 status: "Hi @#{muter.nickname}",
230 in_reply_to_status_id: activity.id
233 assert Notification.create_notification(activity, muter)
236 test "it disables notifications from followers" do
237 follower = insert(:user)
241 notification_settings: %Pleroma.User.NotificationSetting{from_followers: false}
244 User.follow(follower, followed)
245 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
246 refute Notification.create_notification(activity, followed)
249 test "it disables notifications from strangers" do
250 follower = insert(:user)
254 notification_settings: %Pleroma.User.NotificationSetting{from_strangers: false}
257 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
258 refute Notification.create_notification(activity, followed)
261 test "it disables notifications from people the user follows" do
264 notification_settings: %Pleroma.User.NotificationSetting{from_following: false}
267 followed = insert(:user)
268 User.follow(follower, followed)
269 follower = Repo.get(User, follower.id)
270 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
271 refute Notification.create_notification(activity, follower)
274 test "it doesn't create a notification for user if he is the activity author" do
275 activity = insert(:note_activity)
276 author = User.get_cached_by_ap_id(activity.data["actor"])
278 refute Notification.create_notification(activity, author)
281 test "it doesn't create duplicate notifications for follow+subscribed users" do
283 subscriber = insert(:user)
285 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
286 User.subscribe(subscriber, user)
287 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
288 {:ok, [_notif]} = Notification.create_notifications(status)
291 test "it doesn't create subscription notifications if the recipient cannot see the status" do
293 subscriber = insert(:user)
295 User.subscribe(subscriber, user)
297 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
299 assert {:ok, []} == Notification.create_notifications(status)
303 describe "follow / follow_request notifications" do
304 test "it creates `follow` notification for approved Follow activity" do
306 followed_user = insert(:user, locked: false)
308 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
309 assert FollowingRelationship.following?(user, followed_user)
310 assert [notification] = Notification.for_user(followed_user)
312 assert %{type: "follow"} =
313 NotificationView.render("show.json", %{
314 notification: notification,
319 test "it creates `follow_request` notification for pending Follow activity" do
321 followed_user = insert(:user, locked: true)
323 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
324 refute FollowingRelationship.following?(user, followed_user)
325 assert [notification] = Notification.for_user(followed_user)
327 render_opts = %{notification: notification, for: followed_user}
328 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
330 # After request is accepted, the same notification is rendered with type "follow":
331 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
333 notification_id = notification.id
334 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
335 assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
338 test "it doesn't create a notification for follow-unfollow-follow chains" do
340 followed_user = insert(:user, locked: false)
342 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
343 assert FollowingRelationship.following?(user, followed_user)
344 assert [notification] = Notification.for_user(followed_user)
346 CommonAPI.unfollow(user, followed_user)
347 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
349 notification_id = notification.id
350 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
353 test "dismisses the notification on follow request rejection" do
354 user = insert(:user, locked: true)
355 follower = insert(:user)
356 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
357 assert [notification] = Notification.for_user(user)
358 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
359 assert [] = Notification.for_user(user)
363 describe "get notification" do
364 test "it gets a notification that belongs to the user" do
366 other_user = insert(:user)
368 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
370 {:ok, [notification]} = Notification.create_notifications(activity)
371 {:ok, notification} = Notification.get(other_user, notification.id)
373 assert notification.user_id == other_user.id
376 test "it returns error if the notification doesn't belong to the user" do
378 other_user = insert(:user)
380 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
382 {:ok, [notification]} = Notification.create_notifications(activity)
383 {:error, _notification} = Notification.get(user, notification.id)
387 describe "dismiss notification" do
388 test "it dismisses a notification that belongs to the user" do
390 other_user = insert(:user)
392 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
394 {:ok, [notification]} = Notification.create_notifications(activity)
395 {:ok, notification} = Notification.dismiss(other_user, notification.id)
397 assert notification.user_id == other_user.id
400 test "it returns error if the notification doesn't belong to the user" do
402 other_user = insert(:user)
404 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
406 {:ok, [notification]} = Notification.create_notifications(activity)
407 {:error, _notification} = Notification.dismiss(user, notification.id)
411 describe "clear notification" do
412 test "it clears all notifications belonging to the user" do
414 other_user = insert(:user)
415 third_user = insert(:user)
418 CommonAPI.post(user, %{
419 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
422 {:ok, _notifs} = Notification.create_notifications(activity)
425 CommonAPI.post(user, %{
426 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
429 {:ok, _notifs} = Notification.create_notifications(activity)
430 Notification.clear(other_user)
432 assert Notification.for_user(other_user) == []
433 assert Notification.for_user(third_user) != []
437 describe "set_read_up_to()" do
438 test "it sets all notifications as read up to a specified notification ID" do
440 other_user = insert(:user)
443 CommonAPI.post(user, %{
444 status: "hey @#{other_user.nickname}!"
448 CommonAPI.post(user, %{
449 status: "hey again @#{other_user.nickname}!"
452 [n2, n1] = Notification.for_user(other_user)
457 CommonAPI.post(user, %{
458 status: "hey yet again @#{other_user.nickname}!"
461 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
463 assert read_notification.activity.object
465 [n3, n2, n1] = Notification.for_user(other_user)
467 assert n1.seen == true
468 assert n2.seen == true
469 assert n3.seen == false
471 assert %Pleroma.Marker{} =
475 user_id: other_user.id,
476 timeline: "notifications"
479 assert m.last_read_id == to_string(n2.id)
483 describe "for_user_since/2" do
484 defp days_ago(days) do
486 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
487 -days * 60 * 60 * 24,
492 test "Returns recent notifications" do
493 user1 = insert(:user)
494 user2 = insert(:user)
496 Enum.each(0..10, fn i ->
498 CommonAPI.post(user1, %{
499 status: "hey ##{i} @#{user2.nickname}!"
503 {old, new} = Enum.split(Notification.for_user(user2), 5)
505 Enum.each(old, fn notification ->
507 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
508 |> Pleroma.Repo.update!()
511 recent_notifications_ids =
513 |> Notification.for_user_since(
514 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
518 Enum.each(old, fn %{id: id} ->
519 refute id in recent_notifications_ids
522 Enum.each(new, fn %{id: id} ->
523 assert id in recent_notifications_ids
528 describe "notification target determination / get_notified_from_activity/2" do
529 test "it sends notifications to addressed users in new messages" do
531 other_user = insert(:user)
534 CommonAPI.post(user, %{
535 status: "hey @#{other_user.nickname}!"
538 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
540 assert other_user in enabled_receivers
543 test "it sends notifications to mentioned users in new messages" do
545 other_user = insert(:user)
548 "@context" => "https://www.w3.org/ns/activitystreams",
550 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
551 "actor" => user.ap_id,
554 "content" => "message with a Mention tag, but no explicit tagging",
558 "href" => other_user.ap_id,
559 "name" => other_user.nickname
562 "attributedTo" => user.ap_id
566 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
568 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
570 assert other_user in enabled_receivers
573 test "it does not send notifications to users who are only cc in new messages" do
575 other_user = insert(:user)
578 "@context" => "https://www.w3.org/ns/activitystreams",
580 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
581 "cc" => [other_user.ap_id],
582 "actor" => user.ap_id,
585 "content" => "hi everyone",
586 "attributedTo" => user.ap_id
590 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
592 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
594 assert other_user not in enabled_receivers
597 test "it does not send notification to mentioned users in likes" do
599 other_user = insert(:user)
600 third_user = insert(:user)
602 {:ok, activity_one} =
603 CommonAPI.post(user, %{
604 status: "hey @#{other_user.nickname}!"
607 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
609 {enabled_receivers, _disabled_receivers} =
610 Notification.get_notified_from_activity(activity_two)
612 assert other_user not in enabled_receivers
615 test "it only notifies the post's author in likes" do
617 other_user = insert(:user)
618 third_user = insert(:user)
620 {:ok, activity_one} =
621 CommonAPI.post(user, %{
622 status: "hey @#{other_user.nickname}!"
625 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
629 |> Map.put("to", [other_user.ap_id | like_data["to"]])
630 |> ActivityPub.persist(local: true)
632 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
634 assert other_user not in enabled_receivers
637 test "it does not send notification to mentioned users in announces" do
639 other_user = insert(:user)
640 third_user = insert(:user)
642 {:ok, activity_one} =
643 CommonAPI.post(user, %{
644 status: "hey @#{other_user.nickname}!"
647 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
649 {enabled_receivers, _disabled_receivers} =
650 Notification.get_notified_from_activity(activity_two)
652 assert other_user not in enabled_receivers
655 test "it returns blocking recipient in disabled recipients list" do
657 other_user = insert(:user)
658 {:ok, _user_relationship} = User.block(other_user, user)
660 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
662 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
664 assert [] == enabled_receivers
665 assert [other_user] == disabled_receivers
668 test "it returns notification-muting recipient in disabled recipients list" do
670 other_user = insert(:user)
671 {:ok, _user_relationships} = User.mute(other_user, user)
673 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
675 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
677 assert [] == enabled_receivers
678 assert [other_user] == disabled_receivers
681 test "it returns thread-muting recipient in disabled recipients list" do
683 other_user = insert(:user)
685 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
687 {:ok, _} = CommonAPI.add_mute(other_user, activity)
689 {:ok, same_context_activity} =
690 CommonAPI.post(user, %{
691 status: "hey-hey-hey @#{other_user.nickname}!",
692 in_reply_to_status_id: activity.id
695 {enabled_receivers, disabled_receivers} =
696 Notification.get_notified_from_activity(same_context_activity)
698 assert [other_user] == disabled_receivers
699 refute other_user in enabled_receivers
702 test "it returns non-following domain-blocking recipient in disabled recipients list" do
703 blocked_domain = "blocked.domain"
704 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
705 other_user = insert(:user)
707 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
709 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
711 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
713 assert [] == enabled_receivers
714 assert [other_user] == disabled_receivers
717 test "it returns following domain-blocking recipient in enabled recipients list" do
718 blocked_domain = "blocked.domain"
719 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
720 other_user = insert(:user)
722 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
723 {:ok, other_user} = User.follow(other_user, user)
725 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
727 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
729 assert [other_user] == enabled_receivers
730 assert [] == disabled_receivers
734 describe "notification lifecycle" do
735 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
737 other_user = insert(:user)
739 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
741 assert Enum.empty?(Notification.for_user(user))
743 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
745 assert length(Notification.for_user(user)) == 1
747 {:ok, _} = CommonAPI.delete(activity.id, user)
749 assert Enum.empty?(Notification.for_user(user))
752 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
754 other_user = insert(:user)
756 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
758 assert Enum.empty?(Notification.for_user(user))
760 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
762 assert length(Notification.for_user(user)) == 1
764 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
766 assert Enum.empty?(Notification.for_user(user))
769 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
771 other_user = insert(:user)
773 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
775 assert Enum.empty?(Notification.for_user(user))
777 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
779 assert length(Notification.for_user(user)) == 1
781 {:ok, _} = CommonAPI.delete(activity.id, user)
783 assert Enum.empty?(Notification.for_user(user))
786 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
788 other_user = insert(:user)
790 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
792 assert Enum.empty?(Notification.for_user(user))
794 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
796 assert length(Notification.for_user(user)) == 1
798 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
800 assert Enum.empty?(Notification.for_user(user))
803 test "liking an activity which is already deleted does not generate a notification" do
805 other_user = insert(:user)
807 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
809 assert Enum.empty?(Notification.for_user(user))
811 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
813 assert Enum.empty?(Notification.for_user(user))
815 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
817 assert Enum.empty?(Notification.for_user(user))
820 test "repeating an activity which is already deleted does not generate a notification" do
822 other_user = insert(:user)
824 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
826 assert Enum.empty?(Notification.for_user(user))
828 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
830 assert Enum.empty?(Notification.for_user(user))
832 {:error, _} = CommonAPI.repeat(activity.id, other_user)
834 assert Enum.empty?(Notification.for_user(user))
837 test "replying to a deleted post without tagging does not generate a notification" do
839 other_user = insert(:user)
841 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
842 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
844 {:ok, _reply_activity} =
845 CommonAPI.post(other_user, %{
846 status: "test reply",
847 in_reply_to_status_id: activity.id
850 assert Enum.empty?(Notification.for_user(user))
853 test "notifications are deleted if a local user is deleted" do
855 other_user = insert(:user)
858 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
860 refute Enum.empty?(Notification.for_user(other_user))
862 {:ok, job} = User.delete(user)
863 ObanHelpers.perform(job)
865 assert Enum.empty?(Notification.for_user(other_user))
868 test "notifications are deleted if a remote user is deleted" do
869 remote_user = insert(:user)
870 local_user = insert(:user)
873 "@context" => "https://www.w3.org/ns/activitystreams",
875 "actor" => remote_user.ap_id,
876 "id" => remote_user.ap_id <> "/activities/test",
877 "to" => [local_user.ap_id],
881 "content" => "Hello!",
885 "href" => local_user.ap_id,
886 "name" => "@#{local_user.nickname}"
889 "to" => [local_user.ap_id],
891 "attributedTo" => remote_user.ap_id
895 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
897 refute Enum.empty?(Notification.for_user(local_user))
899 delete_user_message = %{
900 "@context" => "https://www.w3.org/ns/activitystreams",
901 "id" => remote_user.ap_id <> "/activities/delete",
902 "actor" => remote_user.ap_id,
904 "object" => remote_user.ap_id
907 remote_user_url = remote_user.ap_id
910 %{method: :get, url: ^remote_user_url} ->
911 %Tesla.Env{status: 404, body: ""}
914 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
915 ObanHelpers.perform_all()
917 assert Enum.empty?(Notification.for_user(local_user))
920 @tag capture_log: true
921 test "move activity generates a notification" do
922 %{ap_id: old_ap_id} = old_user = insert(:user)
923 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
924 follower = insert(:user)
925 other_follower = insert(:user, %{allow_following_move: false})
927 User.follow(follower, old_user)
928 User.follow(other_follower, old_user)
930 old_user_url = old_user.ap_id
933 File.read!("test/fixtures/users_mock/localhost.json")
934 |> String.replace("{{nickname}}", old_user.nickname)
938 %{method: :get, url: ^old_user_url} ->
939 %Tesla.Env{status: 200, body: body}
942 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
943 ObanHelpers.perform_all()
948 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
951 ] = Notification.for_user(follower)
956 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
959 ] = Notification.for_user(other_follower)
963 describe "for_user" do
964 test "it returns notifications for muted user without notifications" do
966 muted = insert(:user)
967 {:ok, _user_relationships} = User.mute(user, muted, false)
969 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
971 [notification] = Notification.for_user(user)
973 assert notification.activity.object
976 test "it doesn't return notifications for muted user with notifications" do
978 muted = insert(:user)
979 {:ok, _user_relationships} = User.mute(user, muted)
981 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
983 assert Notification.for_user(user) == []
986 test "it doesn't return notifications for blocked user" do
988 blocked = insert(:user)
989 {:ok, _user_relationship} = User.block(user, blocked)
991 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
993 assert Notification.for_user(user) == []
996 test "it doesn't return notifications for domain-blocked non-followed user" do
998 blocked = insert(:user, ap_id: "http://some-domain.com")
999 {:ok, user} = User.block_domain(user, "some-domain.com")
1001 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1003 assert Notification.for_user(user) == []
1006 test "it returns notifications for domain-blocked but followed user" do
1007 user = insert(:user)
1008 blocked = insert(:user, ap_id: "http://some-domain.com")
1010 {:ok, user} = User.block_domain(user, "some-domain.com")
1011 {:ok, _} = User.follow(user, blocked)
1013 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1015 assert length(Notification.for_user(user)) == 1
1018 test "it doesn't return notifications for muted thread" do
1019 user = insert(:user)
1020 another_user = insert(:user)
1022 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1024 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1025 assert Notification.for_user(user) == []
1028 test "it returns notifications from a muted user when with_muted is set" do
1029 user = insert(:user)
1030 muted = insert(:user)
1031 {:ok, _user_relationships} = User.mute(user, muted)
1033 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1035 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1038 test "it doesn't return notifications from a blocked user when with_muted is set" do
1039 user = insert(:user)
1040 blocked = insert(:user)
1041 {:ok, _user_relationship} = User.block(user, blocked)
1043 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1045 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1048 test "when with_muted is set, " <>
1049 "it doesn't return notifications from a domain-blocked non-followed user" do
1050 user = insert(:user)
1051 blocked = insert(:user, ap_id: "http://some-domain.com")
1052 {:ok, user} = User.block_domain(user, "some-domain.com")
1054 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1056 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1059 test "it returns notifications from muted threads when with_muted is set" do
1060 user = insert(:user)
1061 another_user = insert(:user)
1063 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1065 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1066 assert length(Notification.for_user(user, %{with_muted: true})) == 1