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
14 alias Pleroma.Tests.ObanHelpers
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.ActivityPub.Builder
18 alias Pleroma.Web.ActivityPub.Transmogrifier
19 alias Pleroma.Web.CommonAPI
20 alias Pleroma.Web.MastodonAPI.NotificationView
21 alias Pleroma.Web.Push
22 alias Pleroma.Web.Streamer
24 describe "create_notifications" do
25 test "creates a notification for an emoji reaction" do
27 other_user = insert(:user)
29 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
30 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
32 {:ok, [notification]} = Notification.create_notifications(activity)
34 assert notification.user_id == user.id
35 assert notification.type == "pleroma:emoji_reaction"
38 test "notifies someone when they are directly addressed" do
40 other_user = insert(:user)
41 third_user = insert(:user)
44 CommonAPI.post(user, %{
45 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
48 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
50 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
51 assert notified_ids == [other_user.id, third_user.id]
52 assert notification.activity_id == activity.id
53 assert notification.type == "mention"
54 assert other_notification.activity_id == activity.id
56 assert [%Pleroma.Marker{unread_count: 2}] =
57 Pleroma.Marker.get_markers(other_user, ["notifications"])
60 test "it creates a notification for subscribed users" do
62 subscriber = insert(:user)
64 User.subscribe(subscriber, user)
66 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
67 {:ok, [notification]} = Notification.create_notifications(status)
69 assert notification.user_id == subscriber.id
72 test "does not create a notification for subscribed users if status is a reply" do
74 other_user = insert(:user)
75 subscriber = insert(:user)
77 User.subscribe(subscriber, other_user)
79 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
81 {:ok, _reply_activity} =
82 CommonAPI.post(other_user, %{
84 in_reply_to_status_id: activity.id
87 user_notifications = Notification.for_user(user)
88 assert length(user_notifications) == 1
90 subscriber_notifications = Notification.for_user(subscriber)
91 assert Enum.empty?(subscriber_notifications)
95 describe "CommonApi.post/2 notification-related functionality" do
96 test_with_mock "creates but does NOT send notification to blocker user",
101 blocker = insert(:user)
102 {:ok, _user_relationship} = User.block(blocker, user)
104 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
106 blocker_id = blocker.id
107 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
108 refute called(Push.send(:_))
111 test_with_mock "creates but does NOT send notification to notification-muter user",
116 muter = insert(:user)
117 {:ok, _user_relationships} = User.mute(muter, user)
119 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
122 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
123 refute called(Push.send(:_))
126 test_with_mock "creates but does NOT send notification to thread-muter user",
131 thread_muter = insert(:user)
133 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
135 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
137 {:ok, _same_context_activity} =
138 CommonAPI.post(user, %{
139 status: "hey-hey-hey @#{thread_muter.nickname}!",
140 in_reply_to_status_id: activity.id
143 [pre_mute_notification, post_mute_notification] =
144 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
146 pre_mute_notification_id = pre_mute_notification.id
147 post_mute_notification_id = post_mute_notification.id
152 %Notification{id: ^pre_mute_notification_id} -> true
161 %Notification{id: ^post_mute_notification_id} -> true
169 describe "create_notification" do
170 @tag needs_streamer: true
171 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
176 Streamer.get_topic_and_add_socket("user", user)
177 assert_receive {:render_with_user, _, _, _}, 4_000
180 task_user_notification =
182 Streamer.get_topic_and_add_socket("user:notification", user)
183 assert_receive {:render_with_user, _, _, _}, 4_000
186 activity = insert(:note_activity)
188 notify = Notification.create_notification(activity, user)
189 assert notify.user_id == user.id
191 Task.await(task_user_notification)
194 test "it creates a notification for user if the user blocks the activity author" do
195 activity = insert(:note_activity)
196 author = User.get_cached_by_ap_id(activity.data["actor"])
198 {:ok, _user_relationship} = User.block(user, author)
200 assert Notification.create_notification(activity, user)
203 test "it creates a notification for the user if the user mutes the activity author" do
204 muter = insert(:user)
205 muted = insert(:user)
206 {:ok, _} = User.mute(muter, muted)
207 muter = Repo.get(User, muter.id)
208 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
210 assert Notification.create_notification(activity, muter)
213 test "notification created if user is muted without notifications" do
214 muter = insert(:user)
215 muted = insert(:user)
217 {:ok, _user_relationships} = User.mute(muter, muted, false)
219 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
221 assert Notification.create_notification(activity, muter)
224 test "it creates a notification for an activity from a muted thread" do
225 muter = insert(:user)
226 other_user = insert(:user)
227 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
228 CommonAPI.add_mute(muter, activity)
231 CommonAPI.post(other_user, %{
232 status: "Hi @#{muter.nickname}",
233 in_reply_to_status_id: activity.id
236 assert Notification.create_notification(activity, muter)
239 test "it disables notifications from followers" do
240 follower = insert(:user)
243 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
245 User.follow(follower, followed)
246 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
247 refute Notification.create_notification(activity, followed)
250 test "it disables notifications from non-followers" do
251 follower = insert(:user)
255 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
258 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
259 refute Notification.create_notification(activity, followed)
262 test "it disables notifications from people the user follows" do
264 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
266 followed = insert(:user)
267 User.follow(follower, followed)
268 follower = Repo.get(User, follower.id)
269 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
270 refute Notification.create_notification(activity, follower)
273 test "it disables notifications from people the user does not follow" do
275 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
277 followed = insert(:user)
278 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
279 refute Notification.create_notification(activity, follower)
282 test "it doesn't create a notification for user if he is the activity author" do
283 activity = insert(:note_activity)
284 author = User.get_cached_by_ap_id(activity.data["actor"])
286 refute Notification.create_notification(activity, author)
289 test "it doesn't create duplicate notifications for follow+subscribed users" do
291 subscriber = insert(:user)
293 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
294 User.subscribe(subscriber, user)
295 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
296 {:ok, [_notif]} = Notification.create_notifications(status)
299 test "it doesn't create subscription notifications if the recipient cannot see the status" do
301 subscriber = insert(:user)
303 User.subscribe(subscriber, user)
305 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
307 assert {:ok, []} == Notification.create_notifications(status)
311 describe "follow / follow_request notifications" do
312 test "it creates `follow` notification for approved Follow activity" do
314 followed_user = insert(:user, locked: false)
316 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
317 assert FollowingRelationship.following?(user, followed_user)
318 assert [notification] = Notification.for_user(followed_user)
320 assert %{type: "follow"} =
321 NotificationView.render("show.json", %{
322 notification: notification,
327 test "it creates `follow_request` notification for pending Follow activity" do
329 followed_user = insert(:user, locked: true)
331 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
332 refute FollowingRelationship.following?(user, followed_user)
333 assert [notification] = Notification.for_user(followed_user)
335 render_opts = %{notification: notification, for: followed_user}
336 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
338 # After request is accepted, the same notification is rendered with type "follow":
339 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
342 Repo.get(Notification, notification.id)
343 |> Repo.preload(:activity)
345 assert %{type: "follow"} =
346 NotificationView.render("show.json", notification: notification, for: followed_user)
349 test "it doesn't create a notification for follow-unfollow-follow chains" do
351 followed_user = insert(:user, locked: false)
353 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
354 assert FollowingRelationship.following?(user, followed_user)
355 assert [notification] = Notification.for_user(followed_user)
357 CommonAPI.unfollow(user, followed_user)
358 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
360 notification_id = notification.id
361 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
364 test "dismisses the notification on follow request rejection" do
365 user = insert(:user, locked: true)
366 follower = insert(:user)
367 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
368 assert [notification] = Notification.for_user(user)
369 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
370 assert [] = Notification.for_user(user)
374 describe "get notification" do
375 test "it gets a notification that belongs to the user" do
377 other_user = insert(:user)
379 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
381 {:ok, [notification]} = Notification.create_notifications(activity)
382 {:ok, notification} = Notification.get(other_user, notification.id)
384 assert notification.user_id == other_user.id
387 test "it returns error if the notification doesn't belong to the user" do
389 other_user = insert(:user)
391 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
393 {:ok, [notification]} = Notification.create_notifications(activity)
394 {:error, _notification} = Notification.get(user, notification.id)
398 describe "dismiss notification" do
399 test "it dismisses a notification that belongs to the user" do
401 other_user = insert(:user)
403 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
405 {:ok, [notification]} = Notification.create_notifications(activity)
406 {:ok, notification} = Notification.dismiss(other_user, notification.id)
408 assert notification.user_id == other_user.id
411 test "it returns error if the notification doesn't belong to the user" do
413 other_user = insert(:user)
415 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
417 {:ok, [notification]} = Notification.create_notifications(activity)
418 {:error, _notification} = Notification.dismiss(user, notification.id)
422 describe "clear notification" do
423 test "it clears all notifications belonging to the user" do
425 other_user = insert(:user)
426 third_user = insert(:user)
429 CommonAPI.post(user, %{
430 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
433 {:ok, _notifs} = Notification.create_notifications(activity)
436 CommonAPI.post(user, %{
437 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
440 {:ok, _notifs} = Notification.create_notifications(activity)
441 Notification.clear(other_user)
443 assert Notification.for_user(other_user) == []
444 assert Notification.for_user(third_user) != []
448 describe "set_read_up_to()" do
449 test "it sets all notifications as read up to a specified notification ID" do
451 other_user = insert(:user)
454 CommonAPI.post(user, %{
455 status: "hey @#{other_user.nickname}!"
459 CommonAPI.post(user, %{
460 status: "hey again @#{other_user.nickname}!"
463 [n2, n1] = Notification.for_user(other_user)
468 CommonAPI.post(user, %{
469 status: "hey yet again @#{other_user.nickname}!"
472 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
474 assert read_notification.activity.object
476 [n3, n2, n1] = Notification.for_user(other_user)
478 assert n1.seen == true
479 assert n2.seen == true
480 assert n3.seen == false
482 assert %Pleroma.Marker{} =
486 user_id: other_user.id,
487 timeline: "notifications"
490 assert m.last_read_id == to_string(n2.id)
494 describe "for_user_since/2" do
495 defp days_ago(days) do
497 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
498 -days * 60 * 60 * 24,
503 test "Returns recent notifications" do
504 user1 = insert(:user)
505 user2 = insert(:user)
507 Enum.each(0..10, fn i ->
509 CommonAPI.post(user1, %{
510 status: "hey ##{i} @#{user2.nickname}!"
514 {old, new} = Enum.split(Notification.for_user(user2), 5)
516 Enum.each(old, fn notification ->
518 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
519 |> Pleroma.Repo.update!()
522 recent_notifications_ids =
524 |> Notification.for_user_since(
525 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
529 Enum.each(old, fn %{id: id} ->
530 refute id in recent_notifications_ids
533 Enum.each(new, fn %{id: id} ->
534 assert id in recent_notifications_ids
539 describe "notification target determination / get_notified_from_activity/2" do
540 test "it sends notifications to addressed users in new messages" do
542 other_user = insert(:user)
545 CommonAPI.post(user, %{
546 status: "hey @#{other_user.nickname}!"
549 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
551 assert other_user in enabled_receivers
554 test "it sends notifications to mentioned users in new messages" do
556 other_user = insert(:user)
559 "@context" => "https://www.w3.org/ns/activitystreams",
561 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
562 "actor" => user.ap_id,
565 "content" => "message with a Mention tag, but no explicit tagging",
569 "href" => other_user.ap_id,
570 "name" => other_user.nickname
573 "attributedTo" => user.ap_id
577 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
579 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
581 assert other_user in enabled_receivers
584 test "it does not send notifications to users who are only cc in new messages" do
586 other_user = insert(:user)
589 "@context" => "https://www.w3.org/ns/activitystreams",
591 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
592 "cc" => [other_user.ap_id],
593 "actor" => user.ap_id,
596 "content" => "hi everyone",
597 "attributedTo" => user.ap_id
601 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
603 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
605 assert other_user not in enabled_receivers
608 test "it does not send notification to mentioned users in likes" do
610 other_user = insert(:user)
611 third_user = insert(:user)
613 {:ok, activity_one} =
614 CommonAPI.post(user, %{
615 status: "hey @#{other_user.nickname}!"
618 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
620 {enabled_receivers, _disabled_receivers} =
621 Notification.get_notified_from_activity(activity_two)
623 assert other_user not in enabled_receivers
626 test "it only notifies the post's author in likes" do
628 other_user = insert(:user)
629 third_user = insert(:user)
631 {:ok, activity_one} =
632 CommonAPI.post(user, %{
633 status: "hey @#{other_user.nickname}!"
636 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
640 |> Map.put("to", [other_user.ap_id | like_data["to"]])
641 |> ActivityPub.persist(local: true)
643 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
645 assert other_user not in enabled_receivers
648 test "it does not send notification to mentioned users in announces" do
650 other_user = insert(:user)
651 third_user = insert(:user)
653 {:ok, activity_one} =
654 CommonAPI.post(user, %{
655 status: "hey @#{other_user.nickname}!"
658 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
660 {enabled_receivers, _disabled_receivers} =
661 Notification.get_notified_from_activity(activity_two)
663 assert other_user not in enabled_receivers
666 test "it returns blocking recipient in disabled recipients list" do
668 other_user = insert(:user)
669 {:ok, _user_relationship} = User.block(other_user, user)
671 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
673 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
675 assert [] == enabled_receivers
676 assert [other_user] == disabled_receivers
679 test "it returns notification-muting recipient in disabled recipients list" do
681 other_user = insert(:user)
682 {:ok, _user_relationships} = User.mute(other_user, user)
684 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
686 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
688 assert [] == enabled_receivers
689 assert [other_user] == disabled_receivers
692 test "it returns thread-muting recipient in disabled recipients list" do
694 other_user = insert(:user)
696 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
698 {:ok, _} = CommonAPI.add_mute(other_user, activity)
700 {:ok, same_context_activity} =
701 CommonAPI.post(user, %{
702 status: "hey-hey-hey @#{other_user.nickname}!",
703 in_reply_to_status_id: activity.id
706 {enabled_receivers, disabled_receivers} =
707 Notification.get_notified_from_activity(same_context_activity)
709 assert [other_user] == disabled_receivers
710 refute other_user in enabled_receivers
713 test "it returns non-following domain-blocking recipient in disabled recipients list" do
714 blocked_domain = "blocked.domain"
715 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
716 other_user = insert(:user)
718 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
720 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
722 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
724 assert [] == enabled_receivers
725 assert [other_user] == disabled_receivers
728 test "it returns following domain-blocking recipient in enabled recipients list" do
729 blocked_domain = "blocked.domain"
730 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
731 other_user = insert(:user)
733 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
734 {:ok, other_user} = User.follow(other_user, user)
736 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
738 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
740 assert [other_user] == enabled_receivers
741 assert [] == disabled_receivers
745 describe "notification lifecycle" do
746 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
748 other_user = insert(:user)
750 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
752 assert Enum.empty?(Notification.for_user(user))
754 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
756 assert length(Notification.for_user(user)) == 1
758 {:ok, _} = CommonAPI.delete(activity.id, user)
760 assert Enum.empty?(Notification.for_user(user))
763 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
765 other_user = insert(:user)
767 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
769 assert Enum.empty?(Notification.for_user(user))
771 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
773 assert length(Notification.for_user(user)) == 1
775 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
777 assert Enum.empty?(Notification.for_user(user))
780 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
782 other_user = insert(:user)
784 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
786 assert Enum.empty?(Notification.for_user(user))
788 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
790 assert length(Notification.for_user(user)) == 1
792 {:ok, _} = CommonAPI.delete(activity.id, user)
794 assert Enum.empty?(Notification.for_user(user))
797 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
799 other_user = insert(:user)
801 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
803 assert Enum.empty?(Notification.for_user(user))
805 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
807 assert length(Notification.for_user(user)) == 1
809 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
811 assert Enum.empty?(Notification.for_user(user))
814 test "liking an activity which is already deleted does not generate a notification" do
816 other_user = insert(:user)
818 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
820 assert Enum.empty?(Notification.for_user(user))
822 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
824 assert Enum.empty?(Notification.for_user(user))
826 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
828 assert Enum.empty?(Notification.for_user(user))
831 test "repeating an activity which is already deleted does not generate a notification" do
833 other_user = insert(:user)
835 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
837 assert Enum.empty?(Notification.for_user(user))
839 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
841 assert Enum.empty?(Notification.for_user(user))
843 {:error, _} = CommonAPI.repeat(activity.id, other_user)
845 assert Enum.empty?(Notification.for_user(user))
848 test "replying to a deleted post without tagging does not generate a notification" do
850 other_user = insert(:user)
852 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
853 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
855 {:ok, _reply_activity} =
856 CommonAPI.post(other_user, %{
857 status: "test reply",
858 in_reply_to_status_id: activity.id
861 assert Enum.empty?(Notification.for_user(user))
864 test "notifications are deleted if a local user is deleted" do
866 other_user = insert(:user)
869 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
871 refute Enum.empty?(Notification.for_user(other_user))
873 {:ok, job} = User.delete(user)
874 ObanHelpers.perform(job)
876 assert Enum.empty?(Notification.for_user(other_user))
879 test "notifications are deleted if a remote user is deleted" do
880 remote_user = insert(:user)
881 local_user = insert(:user)
884 "@context" => "https://www.w3.org/ns/activitystreams",
886 "actor" => remote_user.ap_id,
887 "id" => remote_user.ap_id <> "/activities/test",
888 "to" => [local_user.ap_id],
892 "content" => "Hello!",
896 "href" => local_user.ap_id,
897 "name" => "@#{local_user.nickname}"
900 "to" => [local_user.ap_id],
902 "attributedTo" => remote_user.ap_id
906 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
908 refute Enum.empty?(Notification.for_user(local_user))
910 delete_user_message = %{
911 "@context" => "https://www.w3.org/ns/activitystreams",
912 "id" => remote_user.ap_id <> "/activities/delete",
913 "actor" => remote_user.ap_id,
915 "object" => remote_user.ap_id
918 remote_user_url = remote_user.ap_id
921 %{method: :get, url: ^remote_user_url} ->
922 %Tesla.Env{status: 404, body: ""}
925 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
926 ObanHelpers.perform_all()
928 assert Enum.empty?(Notification.for_user(local_user))
931 @tag capture_log: true
932 test "move activity generates a notification" do
933 %{ap_id: old_ap_id} = old_user = insert(:user)
934 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
935 follower = insert(:user)
936 other_follower = insert(:user, %{allow_following_move: false})
938 User.follow(follower, old_user)
939 User.follow(other_follower, old_user)
941 old_user_url = old_user.ap_id
944 File.read!("test/fixtures/users_mock/localhost.json")
945 |> String.replace("{{nickname}}", old_user.nickname)
949 %{method: :get, url: ^old_user_url} ->
950 %Tesla.Env{status: 200, body: body}
953 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
954 ObanHelpers.perform_all()
959 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
962 ] = Notification.for_user(follower)
967 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
970 ] = Notification.for_user(other_follower)
974 describe "for_user" do
975 test "it returns notifications for muted user without notifications" do
977 muted = insert(:user)
978 {:ok, _user_relationships} = User.mute(user, muted, false)
980 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
982 [notification] = Notification.for_user(user)
984 assert notification.activity.object
987 test "it doesn't return notifications for muted user with notifications" do
989 muted = insert(:user)
990 {:ok, _user_relationships} = User.mute(user, muted)
992 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
994 assert Notification.for_user(user) == []
997 test "it doesn't return notifications for blocked user" do
999 blocked = insert(:user)
1000 {:ok, _user_relationship} = User.block(user, blocked)
1002 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1004 assert Notification.for_user(user) == []
1007 test "it doesn't return notifications for domain-blocked non-followed user" do
1008 user = insert(:user)
1009 blocked = insert(:user, ap_id: "http://some-domain.com")
1010 {:ok, user} = User.block_domain(user, "some-domain.com")
1012 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1014 assert Notification.for_user(user) == []
1017 test "it returns notifications for domain-blocked but followed user" do
1018 user = insert(:user)
1019 blocked = insert(:user, ap_id: "http://some-domain.com")
1021 {:ok, user} = User.block_domain(user, "some-domain.com")
1022 {:ok, _} = User.follow(user, blocked)
1024 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1026 assert length(Notification.for_user(user)) == 1
1029 test "it doesn't return notifications for muted thread" do
1030 user = insert(:user)
1031 another_user = insert(:user)
1033 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1035 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1036 assert Notification.for_user(user) == []
1039 test "it returns notifications from a muted user when with_muted is set" do
1040 user = insert(:user)
1041 muted = insert(:user)
1042 {:ok, _user_relationships} = User.mute(user, muted)
1044 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1046 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1049 test "it doesn't return notifications from a blocked user when with_muted is set" do
1050 user = insert(:user)
1051 blocked = insert(:user)
1052 {:ok, _user_relationship} = User.block(user, blocked)
1054 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1056 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1059 test "when with_muted is set, " <>
1060 "it doesn't return notifications from a domain-blocked non-followed user" do
1061 user = insert(:user)
1062 blocked = insert(:user, ap_id: "http://some-domain.com")
1063 {:ok, user} = User.block_domain(user, "some-domain.com")
1065 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1067 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1070 test "it returns notifications from muted threads when with_muted is set" do
1071 user = insert(:user)
1072 another_user = insert(:user)
1074 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1076 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1077 assert length(Notification.for_user(user, %{with_muted: true})) == 1