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 "never returns nil" do
27 other_user = insert(:user, %{invisible: true})
29 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
30 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
32 refute {:ok, [nil]} == Notification.create_notifications(activity)
35 test "creates a notification for an emoji reaction" do
37 other_user = insert(:user)
39 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
40 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
42 {:ok, [notification]} = Notification.create_notifications(activity)
44 assert notification.user_id == user.id
45 assert notification.type == "pleroma:emoji_reaction"
48 test "notifies someone when they are directly addressed" do
50 other_user = insert(:user)
51 third_user = insert(:user)
54 CommonAPI.post(user, %{
55 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
58 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
60 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
61 assert notified_ids == [other_user.id, third_user.id]
62 assert notification.activity_id == activity.id
63 assert notification.type == "mention"
64 assert other_notification.activity_id == activity.id
66 assert [%Pleroma.Marker{unread_count: 2}] =
67 Pleroma.Marker.get_markers(other_user, ["notifications"])
70 test "it creates a notification for subscribed users" do
72 subscriber = insert(:user)
74 User.subscribe(subscriber, user)
76 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
77 {:ok, [notification]} = Notification.create_notifications(status)
79 assert notification.user_id == subscriber.id
82 test "does not create a notification for subscribed users if status is a reply" do
84 other_user = insert(:user)
85 subscriber = insert(:user)
87 User.subscribe(subscriber, other_user)
89 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
91 {:ok, _reply_activity} =
92 CommonAPI.post(other_user, %{
94 in_reply_to_status_id: activity.id
97 user_notifications = Notification.for_user(user)
98 assert length(user_notifications) == 1
100 subscriber_notifications = Notification.for_user(subscriber)
101 assert Enum.empty?(subscriber_notifications)
105 describe "CommonApi.post/2 notification-related functionality" do
106 test_with_mock "creates but does NOT send notification to blocker user",
111 blocker = insert(:user)
112 {:ok, _user_relationship} = User.block(blocker, user)
114 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
116 blocker_id = blocker.id
117 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
118 refute called(Push.send(:_))
121 test_with_mock "creates but does NOT send notification to notification-muter user",
126 muter = insert(:user)
127 {:ok, _user_relationships} = User.mute(muter, user)
129 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
132 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
133 refute called(Push.send(:_))
136 test_with_mock "creates but does NOT send notification to thread-muter user",
141 thread_muter = insert(:user)
143 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
145 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
147 {:ok, _same_context_activity} =
148 CommonAPI.post(user, %{
149 status: "hey-hey-hey @#{thread_muter.nickname}!",
150 in_reply_to_status_id: activity.id
153 [pre_mute_notification, post_mute_notification] =
154 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
156 pre_mute_notification_id = pre_mute_notification.id
157 post_mute_notification_id = post_mute_notification.id
162 %Notification{id: ^pre_mute_notification_id} -> true
171 %Notification{id: ^post_mute_notification_id} -> true
179 describe "create_notification" do
180 @tag needs_streamer: true
181 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
186 Streamer.get_topic_and_add_socket("user", user)
187 assert_receive {:render_with_user, _, _, _}, 4_000
190 task_user_notification =
192 Streamer.get_topic_and_add_socket("user:notification", user)
193 assert_receive {:render_with_user, _, _, _}, 4_000
196 activity = insert(:note_activity)
198 notify = Notification.create_notification(activity, user)
199 assert notify.user_id == user.id
201 Task.await(task_user_notification)
204 test "it creates a notification for user if the user blocks the activity author" do
205 activity = insert(:note_activity)
206 author = User.get_cached_by_ap_id(activity.data["actor"])
208 {:ok, _user_relationship} = User.block(user, author)
210 assert Notification.create_notification(activity, user)
213 test "it creates a notification for the user if the user mutes the activity author" do
214 muter = insert(:user)
215 muted = insert(:user)
216 {:ok, _} = User.mute(muter, muted)
217 muter = Repo.get(User, muter.id)
218 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
220 notification = Notification.create_notification(activity, muter)
222 assert notification.id
223 assert notification.seen
226 test "notification created if user is muted without notifications" do
227 muter = insert(:user)
228 muted = insert(:user)
230 {:ok, _user_relationships} = User.mute(muter, muted, %{notifications: false})
232 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
234 assert Notification.create_notification(activity, muter)
237 test "it creates a notification for an activity from a muted thread" do
238 muter = insert(:user)
239 other_user = insert(:user)
240 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
241 CommonAPI.add_mute(muter, activity)
244 CommonAPI.post(other_user, %{
245 status: "Hi @#{muter.nickname}",
246 in_reply_to_status_id: activity.id
249 notification = Notification.create_notification(activity, muter)
251 assert notification.id
252 assert notification.seen
255 test "it disables notifications from strangers" do
256 follower = insert(:user)
260 notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
263 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
264 refute Notification.create_notification(activity, followed)
267 test "it doesn't create a notification for user if he is the activity author" do
268 activity = insert(:note_activity)
269 author = User.get_cached_by_ap_id(activity.data["actor"])
271 refute Notification.create_notification(activity, author)
274 test "it doesn't create duplicate notifications for follow+subscribed users" do
276 subscriber = insert(:user)
278 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
279 User.subscribe(subscriber, user)
280 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
281 {:ok, [_notif]} = Notification.create_notifications(status)
284 test "it doesn't create subscription notifications if the recipient cannot see the status" do
286 subscriber = insert(:user)
288 User.subscribe(subscriber, user)
290 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
292 assert {:ok, []} == Notification.create_notifications(status)
295 test "it disables notifications from people who are invisible" do
296 author = insert(:user, invisible: true)
299 {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
300 refute Notification.create_notification(status, user)
303 test "it doesn't create notifications if content matches with an irreversible filter" do
305 subscriber = insert(:user)
307 User.subscribe(subscriber, user)
308 insert(:filter, user: subscriber, phrase: "cofe", hide: true)
310 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
312 assert {:ok, []} == Notification.create_notifications(status)
315 test "it creates notifications if content matches with a not irreversible filter" do
317 subscriber = insert(:user)
319 User.subscribe(subscriber, user)
320 insert(:filter, user: subscriber, phrase: "cofe", hide: false)
322 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
323 {:ok, [notification]} = Notification.create_notifications(status)
326 refute notification.seen
329 test "it creates notifications when someone likes user's status with a filtered word" do
331 other_user = insert(:user)
332 insert(:filter, user: user, phrase: "tesla", hide: true)
334 {:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"})
335 {:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id)
337 {:ok, [notification]} = Notification.create_notifications(activity_two)
340 refute notification.seen
344 describe "follow / follow_request notifications" do
345 test "it creates `follow` notification for approved Follow activity" do
347 followed_user = insert(:user, locked: false)
349 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
350 assert FollowingRelationship.following?(user, followed_user)
351 assert [notification] = Notification.for_user(followed_user)
353 assert %{type: "follow"} =
354 NotificationView.render("show.json", %{
355 notification: notification,
360 test "it creates `follow_request` notification for pending Follow activity" do
362 followed_user = insert(:user, locked: true)
364 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
365 refute FollowingRelationship.following?(user, followed_user)
366 assert [notification] = Notification.for_user(followed_user)
368 render_opts = %{notification: notification, for: followed_user}
369 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
371 # After request is accepted, the same notification is rendered with type "follow":
372 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
375 Repo.get(Notification, notification.id)
376 |> Repo.preload(:activity)
378 assert %{type: "follow"} =
379 NotificationView.render("show.json", notification: notification, for: followed_user)
382 test "it doesn't create a notification for follow-unfollow-follow chains" do
384 followed_user = insert(:user, locked: false)
386 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
387 assert FollowingRelationship.following?(user, followed_user)
388 assert [notification] = Notification.for_user(followed_user)
390 CommonAPI.unfollow(user, followed_user)
391 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
393 notification_id = notification.id
394 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
397 test "dismisses the notification on follow request rejection" do
398 user = insert(:user, locked: true)
399 follower = insert(:user)
400 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
401 assert [notification] = Notification.for_user(user)
402 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
403 assert [] = Notification.for_user(user)
407 describe "get notification" do
408 test "it gets a notification that belongs to the user" do
410 other_user = insert(:user)
412 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
414 {:ok, [notification]} = Notification.create_notifications(activity)
415 {:ok, notification} = Notification.get(other_user, notification.id)
417 assert notification.user_id == other_user.id
420 test "it returns error if the notification doesn't belong to the user" do
422 other_user = insert(:user)
424 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
426 {:ok, [notification]} = Notification.create_notifications(activity)
427 {:error, _notification} = Notification.get(user, notification.id)
431 describe "dismiss notification" do
432 test "it dismisses a notification that belongs to the user" do
434 other_user = insert(:user)
436 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
438 {:ok, [notification]} = Notification.create_notifications(activity)
439 {:ok, notification} = Notification.dismiss(other_user, notification.id)
441 assert notification.user_id == other_user.id
444 test "it returns error if the notification doesn't belong to the user" do
446 other_user = insert(:user)
448 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
450 {:ok, [notification]} = Notification.create_notifications(activity)
451 {:error, _notification} = Notification.dismiss(user, notification.id)
455 describe "clear notification" do
456 test "it clears all notifications belonging to the user" do
458 other_user = insert(:user)
459 third_user = insert(:user)
462 CommonAPI.post(user, %{
463 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
466 {:ok, _notifs} = Notification.create_notifications(activity)
469 CommonAPI.post(user, %{
470 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
473 {:ok, _notifs} = Notification.create_notifications(activity)
474 Notification.clear(other_user)
476 assert Notification.for_user(other_user) == []
477 assert Notification.for_user(third_user) != []
481 describe "set_read_up_to()" do
482 test "it sets all notifications as read up to a specified notification ID" do
484 other_user = insert(:user)
487 CommonAPI.post(user, %{
488 status: "hey @#{other_user.nickname}!"
492 CommonAPI.post(user, %{
493 status: "hey again @#{other_user.nickname}!"
496 [n2, n1] = Notification.for_user(other_user)
501 CommonAPI.post(user, %{
502 status: "hey yet again @#{other_user.nickname}!"
505 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
507 assert read_notification.activity.object
509 [n3, n2, n1] = Notification.for_user(other_user)
511 assert n1.seen == true
512 assert n2.seen == true
513 assert n3.seen == false
515 assert %Pleroma.Marker{} =
519 user_id: other_user.id,
520 timeline: "notifications"
523 assert m.last_read_id == to_string(n2.id)
527 describe "for_user_since/2" do
528 defp days_ago(days) do
530 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
531 -days * 60 * 60 * 24,
536 test "Returns recent notifications" do
537 user1 = insert(:user)
538 user2 = insert(:user)
540 Enum.each(0..10, fn i ->
542 CommonAPI.post(user1, %{
543 status: "hey ##{i} @#{user2.nickname}!"
547 {old, new} = Enum.split(Notification.for_user(user2), 5)
549 Enum.each(old, fn notification ->
551 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
552 |> Pleroma.Repo.update!()
555 recent_notifications_ids =
557 |> Notification.for_user_since(
558 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
562 Enum.each(old, fn %{id: id} ->
563 refute id in recent_notifications_ids
566 Enum.each(new, fn %{id: id} ->
567 assert id in recent_notifications_ids
572 describe "notification target determination / get_notified_from_activity/2" do
573 test "it sends notifications to addressed users in new messages" do
575 other_user = insert(:user)
578 CommonAPI.post(user, %{
579 status: "hey @#{other_user.nickname}!"
582 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
584 assert other_user in enabled_receivers
587 test "it sends notifications to mentioned users in new messages" do
589 other_user = insert(:user)
592 "@context" => "https://www.w3.org/ns/activitystreams",
594 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
595 "actor" => user.ap_id,
598 "content" => "message with a Mention tag, but no explicit tagging",
602 "href" => other_user.ap_id,
603 "name" => other_user.nickname
606 "attributedTo" => user.ap_id
610 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
612 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
614 assert other_user in enabled_receivers
617 test "it does not send notifications to users who are only cc in new messages" do
619 other_user = insert(:user)
622 "@context" => "https://www.w3.org/ns/activitystreams",
624 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
625 "cc" => [other_user.ap_id],
626 "actor" => user.ap_id,
629 "content" => "hi everyone",
630 "attributedTo" => user.ap_id
634 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
636 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
638 assert other_user not in enabled_receivers
641 test "it does not send notification to mentioned users in likes" do
643 other_user = insert(:user)
644 third_user = insert(:user)
646 {:ok, activity_one} =
647 CommonAPI.post(user, %{
648 status: "hey @#{other_user.nickname}!"
651 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
653 {enabled_receivers, _disabled_receivers} =
654 Notification.get_notified_from_activity(activity_two)
656 assert other_user not in enabled_receivers
659 test "it only notifies the post's author in likes" do
661 other_user = insert(:user)
662 third_user = insert(:user)
664 {:ok, activity_one} =
665 CommonAPI.post(user, %{
666 status: "hey @#{other_user.nickname}!"
669 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
673 |> Map.put("to", [other_user.ap_id | like_data["to"]])
674 |> ActivityPub.persist(local: true)
676 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
678 assert other_user not in enabled_receivers
681 test "it does not send notification to mentioned users in announces" do
683 other_user = insert(:user)
684 third_user = insert(:user)
686 {:ok, activity_one} =
687 CommonAPI.post(user, %{
688 status: "hey @#{other_user.nickname}!"
691 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
693 {enabled_receivers, _disabled_receivers} =
694 Notification.get_notified_from_activity(activity_two)
696 assert other_user not in enabled_receivers
699 test "it returns blocking recipient in disabled recipients list" do
701 other_user = insert(:user)
702 {:ok, _user_relationship} = User.block(other_user, user)
704 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
706 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
708 assert [] == enabled_receivers
709 assert [other_user] == disabled_receivers
712 test "it returns notification-muting recipient in disabled recipients list" do
714 other_user = insert(:user)
715 {:ok, _user_relationships} = User.mute(other_user, user)
717 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
719 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
721 assert [] == enabled_receivers
722 assert [other_user] == disabled_receivers
725 test "it returns thread-muting recipient in disabled recipients list" do
727 other_user = insert(:user)
729 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
731 {:ok, _} = CommonAPI.add_mute(other_user, activity)
733 {:ok, same_context_activity} =
734 CommonAPI.post(user, %{
735 status: "hey-hey-hey @#{other_user.nickname}!",
736 in_reply_to_status_id: activity.id
739 {enabled_receivers, disabled_receivers} =
740 Notification.get_notified_from_activity(same_context_activity)
742 assert [other_user] == disabled_receivers
743 refute other_user in enabled_receivers
746 test "it returns non-following domain-blocking recipient in disabled recipients list" do
747 blocked_domain = "blocked.domain"
748 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
749 other_user = insert(:user)
751 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
753 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
755 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
757 assert [] == enabled_receivers
758 assert [other_user] == disabled_receivers
761 test "it returns following domain-blocking recipient in enabled recipients list" do
762 blocked_domain = "blocked.domain"
763 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
764 other_user = insert(:user)
766 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
767 {:ok, other_user} = User.follow(other_user, user)
769 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
771 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
773 assert [other_user] == enabled_receivers
774 assert [] == disabled_receivers
778 describe "notification lifecycle" do
779 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
781 other_user = insert(:user)
783 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
785 assert Enum.empty?(Notification.for_user(user))
787 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
789 assert length(Notification.for_user(user)) == 1
791 {:ok, _} = CommonAPI.delete(activity.id, user)
793 assert Enum.empty?(Notification.for_user(user))
796 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
798 other_user = insert(:user)
800 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
802 assert Enum.empty?(Notification.for_user(user))
804 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
806 assert length(Notification.for_user(user)) == 1
808 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
810 assert Enum.empty?(Notification.for_user(user))
813 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
815 other_user = insert(:user)
817 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
819 assert Enum.empty?(Notification.for_user(user))
821 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
823 assert length(Notification.for_user(user)) == 1
825 {:ok, _} = CommonAPI.delete(activity.id, user)
827 assert Enum.empty?(Notification.for_user(user))
830 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
832 other_user = insert(:user)
834 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
836 assert Enum.empty?(Notification.for_user(user))
838 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
840 assert length(Notification.for_user(user)) == 1
842 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
844 assert Enum.empty?(Notification.for_user(user))
847 test "liking an activity which is already deleted does not generate a notification" do
849 other_user = insert(:user)
851 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
853 assert Enum.empty?(Notification.for_user(user))
855 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
857 assert Enum.empty?(Notification.for_user(user))
859 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
861 assert Enum.empty?(Notification.for_user(user))
864 test "repeating an activity which is already deleted does not generate a notification" do
866 other_user = insert(:user)
868 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
870 assert Enum.empty?(Notification.for_user(user))
872 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
874 assert Enum.empty?(Notification.for_user(user))
876 {:error, _} = CommonAPI.repeat(activity.id, other_user)
878 assert Enum.empty?(Notification.for_user(user))
881 test "replying to a deleted post without tagging does not generate a notification" do
883 other_user = insert(:user)
885 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
886 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
888 {:ok, _reply_activity} =
889 CommonAPI.post(other_user, %{
890 status: "test reply",
891 in_reply_to_status_id: activity.id
894 assert Enum.empty?(Notification.for_user(user))
897 test "notifications are deleted if a local user is deleted" do
899 other_user = insert(:user)
902 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
904 refute Enum.empty?(Notification.for_user(other_user))
906 {:ok, job} = User.delete(user)
907 ObanHelpers.perform(job)
909 assert Enum.empty?(Notification.for_user(other_user))
912 test "notifications are deleted if a remote user is deleted" do
913 remote_user = insert(:user)
914 local_user = insert(:user)
917 "@context" => "https://www.w3.org/ns/activitystreams",
919 "actor" => remote_user.ap_id,
920 "id" => remote_user.ap_id <> "/activities/test",
921 "to" => [local_user.ap_id],
925 "content" => "Hello!",
929 "href" => local_user.ap_id,
930 "name" => "@#{local_user.nickname}"
933 "to" => [local_user.ap_id],
935 "attributedTo" => remote_user.ap_id
939 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
941 refute Enum.empty?(Notification.for_user(local_user))
943 delete_user_message = %{
944 "@context" => "https://www.w3.org/ns/activitystreams",
945 "id" => remote_user.ap_id <> "/activities/delete",
946 "actor" => remote_user.ap_id,
948 "object" => remote_user.ap_id
951 remote_user_url = remote_user.ap_id
954 %{method: :get, url: ^remote_user_url} ->
955 %Tesla.Env{status: 404, body: ""}
958 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
959 ObanHelpers.perform_all()
961 assert Enum.empty?(Notification.for_user(local_user))
964 @tag capture_log: true
965 test "move activity generates a notification" do
966 %{ap_id: old_ap_id} = old_user = insert(:user)
967 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
968 follower = insert(:user)
969 other_follower = insert(:user, %{allow_following_move: false})
971 User.follow(follower, old_user)
972 User.follow(other_follower, old_user)
974 old_user_url = old_user.ap_id
977 File.read!("test/fixtures/users_mock/localhost.json")
978 |> String.replace("{{nickname}}", old_user.nickname)
982 %{method: :get, url: ^old_user_url} ->
983 %Tesla.Env{status: 200, body: body}
986 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
987 ObanHelpers.perform_all()
992 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
995 ] = Notification.for_user(follower)
1000 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
1003 ] = Notification.for_user(other_follower)
1007 describe "for_user" do
1009 user = insert(:user)
1011 {:ok, %{user: user}}
1014 test "it returns notifications for muted user without notifications", %{user: user} do
1015 muted = insert(:user)
1016 {:ok, _user_relationships} = User.mute(user, muted, %{notifications: false})
1018 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1020 [notification] = Notification.for_user(user)
1022 assert notification.activity.object
1023 assert notification.seen
1026 test "it doesn't return notifications for muted user with notifications", %{user: user} do
1027 muted = insert(:user)
1028 {:ok, _user_relationships} = User.mute(user, muted)
1030 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1032 assert Notification.for_user(user) == []
1035 test "it doesn't return notifications for blocked user", %{user: user} do
1036 blocked = insert(:user)
1037 {:ok, _user_relationship} = User.block(user, blocked)
1039 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1041 assert Notification.for_user(user) == []
1044 test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do
1045 blocked = insert(:user, ap_id: "http://some-domain.com")
1046 {:ok, user} = User.block_domain(user, "some-domain.com")
1048 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1050 assert Notification.for_user(user) == []
1053 test "it returns notifications for domain-blocked but followed user" do
1054 user = insert(:user)
1055 blocked = insert(:user, ap_id: "http://some-domain.com")
1057 {:ok, user} = User.block_domain(user, "some-domain.com")
1058 {:ok, _} = User.follow(user, blocked)
1060 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1062 assert length(Notification.for_user(user)) == 1
1065 test "it doesn't return notifications for muted thread", %{user: user} do
1066 another_user = insert(:user)
1068 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1070 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1071 assert Notification.for_user(user) == []
1074 test "it returns notifications from a muted user when with_muted is set", %{user: user} do
1075 muted = insert(:user)
1076 {:ok, _user_relationships} = User.mute(user, muted)
1078 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1080 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1083 test "it doesn't return notifications from a blocked user when with_muted is set", %{
1086 blocked = insert(:user)
1087 {:ok, _user_relationship} = User.block(user, blocked)
1089 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1091 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1094 test "when with_muted is set, " <>
1095 "it doesn't return notifications from a domain-blocked non-followed user",
1097 blocked = insert(:user, ap_id: "http://some-domain.com")
1098 {:ok, user} = User.block_domain(user, "some-domain.com")
1100 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1102 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1105 test "it returns notifications from muted threads when with_muted is set", %{user: user} do
1106 another_user = insert(:user)
1108 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1110 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1111 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1114 test "it doesn't return notifications about mentions with filtered word", %{user: user} do
1115 insert(:filter, user: user, phrase: "cofe", hide: true)
1116 another_user = insert(:user)
1118 {:ok, _activity} = CommonAPI.post(another_user, %{status: "@#{user.nickname} got cofe?"})
1120 assert Enum.empty?(Notification.for_user(user))
1123 test "it returns notifications about mentions with not hidden filtered word", %{user: user} do
1124 insert(:filter, user: user, phrase: "test", hide: false)
1125 another_user = insert(:user)
1127 {:ok, _} = CommonAPI.post(another_user, %{status: "@#{user.nickname} test"})
1129 assert length(Notification.for_user(user)) == 1
1132 test "it returns notifications about favorites with filtered word", %{user: user} do
1133 insert(:filter, user: user, phrase: "cofe", hide: true)
1134 another_user = insert(:user)
1136 {:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"})
1137 {:ok, _} = CommonAPI.favorite(another_user, activity.id)
1139 assert length(Notification.for_user(user)) == 1