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 assert Notification.create_notification(activity, muter)
223 test "notification created if user is muted without notifications" do
224 muter = insert(:user)
225 muted = insert(:user)
227 {:ok, _user_relationships} = User.mute(muter, muted, false)
229 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
231 assert Notification.create_notification(activity, muter)
234 test "it creates a notification for an activity from a muted thread" do
235 muter = insert(:user)
236 other_user = insert(:user)
237 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
238 CommonAPI.add_mute(muter, activity)
241 CommonAPI.post(other_user, %{
242 status: "Hi @#{muter.nickname}",
243 in_reply_to_status_id: activity.id
246 assert Notification.create_notification(activity, muter)
249 test "it disables notifications from followers" do
250 follower = insert(:user)
253 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
255 User.follow(follower, followed)
256 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
257 refute Notification.create_notification(activity, followed)
260 test "it disables notifications from non-followers" do
261 follower = insert(:user)
265 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
268 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
269 refute Notification.create_notification(activity, followed)
272 test "it disables notifications from people the user follows" do
274 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
276 followed = insert(:user)
277 User.follow(follower, followed)
278 follower = Repo.get(User, follower.id)
279 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
280 refute Notification.create_notification(activity, follower)
283 test "it disables notifications from people the user does not follow" do
285 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
287 followed = insert(:user)
288 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
289 refute Notification.create_notification(activity, follower)
292 test "it doesn't create a notification for user if he is the activity author" do
293 activity = insert(:note_activity)
294 author = User.get_cached_by_ap_id(activity.data["actor"])
296 refute Notification.create_notification(activity, author)
299 test "it doesn't create duplicate notifications for follow+subscribed users" do
301 subscriber = insert(:user)
303 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
304 User.subscribe(subscriber, user)
305 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
306 {:ok, [_notif]} = Notification.create_notifications(status)
309 test "it doesn't create subscription notifications if the recipient cannot see the status" do
311 subscriber = insert(:user)
313 User.subscribe(subscriber, user)
315 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
317 assert {:ok, []} == Notification.create_notifications(status)
320 test "it disables notifications from people who are invisible" do
321 author = insert(:user, invisible: true)
324 {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
325 refute Notification.create_notification(status, user)
329 describe "follow / follow_request notifications" do
330 test "it creates `follow` notification for approved Follow activity" do
332 followed_user = insert(:user, locked: false)
334 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
335 assert FollowingRelationship.following?(user, followed_user)
336 assert [notification] = Notification.for_user(followed_user)
338 assert %{type: "follow"} =
339 NotificationView.render("show.json", %{
340 notification: notification,
345 test "it creates `follow_request` notification for pending Follow activity" do
347 followed_user = insert(:user, locked: true)
349 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
350 refute FollowingRelationship.following?(user, followed_user)
351 assert [notification] = Notification.for_user(followed_user)
353 render_opts = %{notification: notification, for: followed_user}
354 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
356 # After request is accepted, the same notification is rendered with type "follow":
357 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
360 Repo.get(Notification, notification.id)
361 |> Repo.preload(:activity)
363 assert %{type: "follow"} =
364 NotificationView.render("show.json", notification: notification, for: followed_user)
367 test "it doesn't create a notification for follow-unfollow-follow chains" do
369 followed_user = insert(:user, locked: false)
371 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
372 assert FollowingRelationship.following?(user, followed_user)
373 assert [notification] = Notification.for_user(followed_user)
375 CommonAPI.unfollow(user, followed_user)
376 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
378 notification_id = notification.id
379 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
382 test "dismisses the notification on follow request rejection" do
383 user = insert(:user, locked: true)
384 follower = insert(:user)
385 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
386 assert [notification] = Notification.for_user(user)
387 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
388 assert [] = Notification.for_user(user)
392 describe "get notification" do
393 test "it gets a notification that belongs to the user" do
395 other_user = insert(:user)
397 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
399 {:ok, [notification]} = Notification.create_notifications(activity)
400 {:ok, notification} = Notification.get(other_user, notification.id)
402 assert notification.user_id == other_user.id
405 test "it returns error if the notification doesn't belong to the user" do
407 other_user = insert(:user)
409 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
411 {:ok, [notification]} = Notification.create_notifications(activity)
412 {:error, _notification} = Notification.get(user, notification.id)
416 describe "dismiss notification" do
417 test "it dismisses a notification that belongs to the user" do
419 other_user = insert(:user)
421 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
423 {:ok, [notification]} = Notification.create_notifications(activity)
424 {:ok, notification} = Notification.dismiss(other_user, notification.id)
426 assert notification.user_id == other_user.id
429 test "it returns error if the notification doesn't belong to the user" do
431 other_user = insert(:user)
433 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
435 {:ok, [notification]} = Notification.create_notifications(activity)
436 {:error, _notification} = Notification.dismiss(user, notification.id)
440 describe "clear notification" do
441 test "it clears all notifications belonging to the user" do
443 other_user = insert(:user)
444 third_user = insert(:user)
447 CommonAPI.post(user, %{
448 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
451 {:ok, _notifs} = Notification.create_notifications(activity)
454 CommonAPI.post(user, %{
455 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
458 {:ok, _notifs} = Notification.create_notifications(activity)
459 Notification.clear(other_user)
461 assert Notification.for_user(other_user) == []
462 assert Notification.for_user(third_user) != []
466 describe "set_read_up_to()" do
467 test "it sets all notifications as read up to a specified notification ID" do
469 other_user = insert(:user)
472 CommonAPI.post(user, %{
473 status: "hey @#{other_user.nickname}!"
477 CommonAPI.post(user, %{
478 status: "hey again @#{other_user.nickname}!"
481 [n2, n1] = Notification.for_user(other_user)
486 CommonAPI.post(user, %{
487 status: "hey yet again @#{other_user.nickname}!"
490 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
492 assert read_notification.activity.object
494 [n3, n2, n1] = Notification.for_user(other_user)
496 assert n1.seen == true
497 assert n2.seen == true
498 assert n3.seen == false
500 assert %Pleroma.Marker{} =
504 user_id: other_user.id,
505 timeline: "notifications"
508 assert m.last_read_id == to_string(n2.id)
512 describe "for_user_since/2" do
513 defp days_ago(days) do
515 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
516 -days * 60 * 60 * 24,
521 test "Returns recent notifications" do
522 user1 = insert(:user)
523 user2 = insert(:user)
525 Enum.each(0..10, fn i ->
527 CommonAPI.post(user1, %{
528 status: "hey ##{i} @#{user2.nickname}!"
532 {old, new} = Enum.split(Notification.for_user(user2), 5)
534 Enum.each(old, fn notification ->
536 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
537 |> Pleroma.Repo.update!()
540 recent_notifications_ids =
542 |> Notification.for_user_since(
543 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
547 Enum.each(old, fn %{id: id} ->
548 refute id in recent_notifications_ids
551 Enum.each(new, fn %{id: id} ->
552 assert id in recent_notifications_ids
557 describe "notification target determination / get_notified_from_activity/2" do
558 test "it sends notifications to addressed users in new messages" do
560 other_user = insert(:user)
563 CommonAPI.post(user, %{
564 status: "hey @#{other_user.nickname}!"
567 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
569 assert other_user in enabled_receivers
572 test "it sends notifications to mentioned users in new messages" do
574 other_user = insert(:user)
577 "@context" => "https://www.w3.org/ns/activitystreams",
579 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
580 "actor" => user.ap_id,
583 "content" => "message with a Mention tag, but no explicit tagging",
587 "href" => other_user.ap_id,
588 "name" => other_user.nickname
591 "attributedTo" => user.ap_id
595 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
597 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
599 assert other_user in enabled_receivers
602 test "it does not send notifications to users who are only cc in new messages" do
604 other_user = insert(:user)
607 "@context" => "https://www.w3.org/ns/activitystreams",
609 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
610 "cc" => [other_user.ap_id],
611 "actor" => user.ap_id,
614 "content" => "hi everyone",
615 "attributedTo" => user.ap_id
619 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
621 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
623 assert other_user not in enabled_receivers
626 test "it does not send notification to mentioned users 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, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
638 {enabled_receivers, _disabled_receivers} =
639 Notification.get_notified_from_activity(activity_two)
641 assert other_user not in enabled_receivers
644 test "it only notifies the post's author in likes" do
646 other_user = insert(:user)
647 third_user = insert(:user)
649 {:ok, activity_one} =
650 CommonAPI.post(user, %{
651 status: "hey @#{other_user.nickname}!"
654 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
658 |> Map.put("to", [other_user.ap_id | like_data["to"]])
659 |> ActivityPub.persist(local: true)
661 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
663 assert other_user not in enabled_receivers
666 test "it does not send notification to mentioned users in announces" do
668 other_user = insert(:user)
669 third_user = insert(:user)
671 {:ok, activity_one} =
672 CommonAPI.post(user, %{
673 status: "hey @#{other_user.nickname}!"
676 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
678 {enabled_receivers, _disabled_receivers} =
679 Notification.get_notified_from_activity(activity_two)
681 assert other_user not in enabled_receivers
684 test "it returns blocking recipient in disabled recipients list" do
686 other_user = insert(:user)
687 {:ok, _user_relationship} = User.block(other_user, user)
689 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
691 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
693 assert [] == enabled_receivers
694 assert [other_user] == disabled_receivers
697 test "it returns notification-muting recipient in disabled recipients list" do
699 other_user = insert(:user)
700 {:ok, _user_relationships} = User.mute(other_user, user)
702 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
704 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
706 assert [] == enabled_receivers
707 assert [other_user] == disabled_receivers
710 test "it returns thread-muting recipient in disabled recipients list" do
712 other_user = insert(:user)
714 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
716 {:ok, _} = CommonAPI.add_mute(other_user, activity)
718 {:ok, same_context_activity} =
719 CommonAPI.post(user, %{
720 status: "hey-hey-hey @#{other_user.nickname}!",
721 in_reply_to_status_id: activity.id
724 {enabled_receivers, disabled_receivers} =
725 Notification.get_notified_from_activity(same_context_activity)
727 assert [other_user] == disabled_receivers
728 refute other_user in enabled_receivers
731 test "it returns non-following domain-blocking recipient in disabled recipients list" do
732 blocked_domain = "blocked.domain"
733 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
734 other_user = insert(:user)
736 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
738 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
740 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
742 assert [] == enabled_receivers
743 assert [other_user] == disabled_receivers
746 test "it returns following domain-blocking recipient in enabled 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)
752 {:ok, other_user} = User.follow(other_user, user)
754 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
756 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
758 assert [other_user] == enabled_receivers
759 assert [] == disabled_receivers
763 describe "notification lifecycle" do
764 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
766 other_user = insert(:user)
768 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
770 assert Enum.empty?(Notification.for_user(user))
772 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
774 assert length(Notification.for_user(user)) == 1
776 {:ok, _} = CommonAPI.delete(activity.id, user)
778 assert Enum.empty?(Notification.for_user(user))
781 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
783 other_user = insert(:user)
785 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
787 assert Enum.empty?(Notification.for_user(user))
789 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
791 assert length(Notification.for_user(user)) == 1
793 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
795 assert Enum.empty?(Notification.for_user(user))
798 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
800 other_user = insert(:user)
802 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
804 assert Enum.empty?(Notification.for_user(user))
806 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
808 assert length(Notification.for_user(user)) == 1
810 {:ok, _} = CommonAPI.delete(activity.id, user)
812 assert Enum.empty?(Notification.for_user(user))
815 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
817 other_user = insert(:user)
819 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
821 assert Enum.empty?(Notification.for_user(user))
823 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
825 assert length(Notification.for_user(user)) == 1
827 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
829 assert Enum.empty?(Notification.for_user(user))
832 test "liking an activity which is already deleted does not generate a notification" do
834 other_user = insert(:user)
836 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
838 assert Enum.empty?(Notification.for_user(user))
840 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
842 assert Enum.empty?(Notification.for_user(user))
844 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
846 assert Enum.empty?(Notification.for_user(user))
849 test "repeating an activity which is already deleted does not generate a notification" do
851 other_user = insert(:user)
853 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
855 assert Enum.empty?(Notification.for_user(user))
857 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
859 assert Enum.empty?(Notification.for_user(user))
861 {:error, _} = CommonAPI.repeat(activity.id, other_user)
863 assert Enum.empty?(Notification.for_user(user))
866 test "replying to a deleted post without tagging does not generate a notification" do
868 other_user = insert(:user)
870 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
871 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
873 {:ok, _reply_activity} =
874 CommonAPI.post(other_user, %{
875 status: "test reply",
876 in_reply_to_status_id: activity.id
879 assert Enum.empty?(Notification.for_user(user))
882 test "notifications are deleted if a local user is deleted" do
884 other_user = insert(:user)
887 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
889 refute Enum.empty?(Notification.for_user(other_user))
891 {:ok, job} = User.delete(user)
892 ObanHelpers.perform(job)
894 assert Enum.empty?(Notification.for_user(other_user))
897 test "notifications are deleted if a remote user is deleted" do
898 remote_user = insert(:user)
899 local_user = insert(:user)
902 "@context" => "https://www.w3.org/ns/activitystreams",
904 "actor" => remote_user.ap_id,
905 "id" => remote_user.ap_id <> "/activities/test",
906 "to" => [local_user.ap_id],
910 "content" => "Hello!",
914 "href" => local_user.ap_id,
915 "name" => "@#{local_user.nickname}"
918 "to" => [local_user.ap_id],
920 "attributedTo" => remote_user.ap_id
924 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
926 refute Enum.empty?(Notification.for_user(local_user))
928 delete_user_message = %{
929 "@context" => "https://www.w3.org/ns/activitystreams",
930 "id" => remote_user.ap_id <> "/activities/delete",
931 "actor" => remote_user.ap_id,
933 "object" => remote_user.ap_id
936 remote_user_url = remote_user.ap_id
939 %{method: :get, url: ^remote_user_url} ->
940 %Tesla.Env{status: 404, body: ""}
943 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
944 ObanHelpers.perform_all()
946 assert Enum.empty?(Notification.for_user(local_user))
949 @tag capture_log: true
950 test "move activity generates a notification" do
951 %{ap_id: old_ap_id} = old_user = insert(:user)
952 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
953 follower = insert(:user)
954 other_follower = insert(:user, %{allow_following_move: false})
956 User.follow(follower, old_user)
957 User.follow(other_follower, old_user)
959 old_user_url = old_user.ap_id
962 File.read!("test/fixtures/users_mock/localhost.json")
963 |> String.replace("{{nickname}}", old_user.nickname)
967 %{method: :get, url: ^old_user_url} ->
968 %Tesla.Env{status: 200, body: body}
971 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
972 ObanHelpers.perform_all()
977 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
980 ] = Notification.for_user(follower)
985 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
988 ] = Notification.for_user(other_follower)
992 describe "for_user" do
993 test "it returns notifications for muted user without notifications" do
995 muted = insert(:user)
996 {:ok, _user_relationships} = User.mute(user, muted, false)
998 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1000 [notification] = Notification.for_user(user)
1002 assert notification.activity.object
1005 test "it doesn't return notifications for muted user with notifications" do
1006 user = insert(:user)
1007 muted = insert(:user)
1008 {:ok, _user_relationships} = User.mute(user, muted)
1010 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1012 assert Notification.for_user(user) == []
1015 test "it doesn't return notifications for blocked user" do
1016 user = insert(:user)
1017 blocked = insert(:user)
1018 {:ok, _user_relationship} = User.block(user, blocked)
1020 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1022 assert Notification.for_user(user) == []
1025 test "it doesn't return notifications for domain-blocked non-followed user" do
1026 user = insert(:user)
1027 blocked = insert(:user, ap_id: "http://some-domain.com")
1028 {:ok, user} = User.block_domain(user, "some-domain.com")
1030 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1032 assert Notification.for_user(user) == []
1035 test "it returns notifications for domain-blocked but followed user" do
1036 user = insert(:user)
1037 blocked = insert(:user, ap_id: "http://some-domain.com")
1039 {:ok, user} = User.block_domain(user, "some-domain.com")
1040 {:ok, _} = User.follow(user, blocked)
1042 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1044 assert length(Notification.for_user(user)) == 1
1047 test "it doesn't return notifications for muted thread" do
1048 user = insert(:user)
1049 another_user = insert(:user)
1051 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1053 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1054 assert Notification.for_user(user) == []
1057 test "it returns notifications from a muted user when with_muted is set" do
1058 user = insert(:user)
1059 muted = insert(:user)
1060 {:ok, _user_relationships} = User.mute(user, muted)
1062 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1064 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1067 test "it doesn't return notifications from a blocked user when with_muted is set" do
1068 user = insert(:user)
1069 blocked = insert(:user)
1070 {:ok, _user_relationship} = User.block(user, blocked)
1072 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1074 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1077 test "when with_muted is set, " <>
1078 "it doesn't return notifications from a domain-blocked non-followed user" do
1079 user = insert(:user)
1080 blocked = insert(:user, ap_id: "http://some-domain.com")
1081 {:ok, user} = User.block_domain(user, "some-domain.com")
1083 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1085 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1088 test "it returns notifications from muted threads when with_muted is set" do
1089 user = insert(:user)
1090 another_user = insert(:user)
1092 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1094 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1095 assert length(Notification.for_user(user, %{with_muted: true})) == 1