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 # TODO: Test there's no nil notifications
26 describe "create_notifications" do
27 test "never returns nil" do
29 other_user = insert(:user, %{invisible: true})
31 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
32 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
34 refute {:ok, [nil]} == Notification.create_notifications(activity)
37 test "creates a notification for an emoji reaction" do
39 other_user = insert(:user)
41 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
42 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
44 {:ok, [notification]} = Notification.create_notifications(activity)
46 assert notification.user_id == user.id
47 assert notification.type == "pleroma:emoji_reaction"
50 test "notifies someone when they are directly addressed" do
52 other_user = insert(:user)
53 third_user = insert(:user)
56 CommonAPI.post(user, %{
57 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
60 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
62 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
63 assert notified_ids == [other_user.id, third_user.id]
64 assert notification.activity_id == activity.id
65 assert notification.type == "mention"
66 assert other_notification.activity_id == activity.id
68 assert [%Pleroma.Marker{unread_count: 2}] =
69 Pleroma.Marker.get_markers(other_user, ["notifications"])
72 test "it creates a notification for subscribed users" do
74 subscriber = insert(:user)
76 User.subscribe(subscriber, user)
78 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
79 {:ok, [notification]} = Notification.create_notifications(status)
81 assert notification.user_id == subscriber.id
84 test "does not create a notification for subscribed users if status is a reply" do
86 other_user = insert(:user)
87 subscriber = insert(:user)
89 User.subscribe(subscriber, other_user)
91 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
93 {:ok, _reply_activity} =
94 CommonAPI.post(other_user, %{
96 in_reply_to_status_id: activity.id
99 user_notifications = Notification.for_user(user)
100 assert length(user_notifications) == 1
102 subscriber_notifications = Notification.for_user(subscriber)
103 assert Enum.empty?(subscriber_notifications)
107 describe "CommonApi.post/2 notification-related functionality" do
108 test_with_mock "creates but does NOT send notification to blocker user",
113 blocker = insert(:user)
114 {:ok, _user_relationship} = User.block(blocker, user)
116 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
118 blocker_id = blocker.id
119 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
120 refute called(Push.send(:_))
123 test_with_mock "creates but does NOT send notification to notification-muter user",
128 muter = insert(:user)
129 {:ok, _user_relationships} = User.mute(muter, user)
131 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
134 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
135 refute called(Push.send(:_))
138 test_with_mock "creates but does NOT send notification to thread-muter user",
143 thread_muter = insert(:user)
145 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
147 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
149 {:ok, _same_context_activity} =
150 CommonAPI.post(user, %{
151 status: "hey-hey-hey @#{thread_muter.nickname}!",
152 in_reply_to_status_id: activity.id
155 [pre_mute_notification, post_mute_notification] =
156 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
158 pre_mute_notification_id = pre_mute_notification.id
159 post_mute_notification_id = post_mute_notification.id
164 %Notification{id: ^pre_mute_notification_id} -> true
173 %Notification{id: ^post_mute_notification_id} -> true
181 describe "create_notification" do
182 @tag needs_streamer: true
183 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
188 Streamer.get_topic_and_add_socket("user", user)
189 assert_receive {:render_with_user, _, _, _}, 4_000
192 task_user_notification =
194 Streamer.get_topic_and_add_socket("user:notification", user)
195 assert_receive {:render_with_user, _, _, _}, 4_000
198 activity = insert(:note_activity)
200 notify = Notification.create_notification(activity, user)
201 assert notify.user_id == user.id
203 Task.await(task_user_notification)
206 test "it creates a notification for user if the user blocks the activity author" do
207 activity = insert(:note_activity)
208 author = User.get_cached_by_ap_id(activity.data["actor"])
210 {:ok, _user_relationship} = User.block(user, author)
212 assert Notification.create_notification(activity, user)
215 test "it creates a notification for the user if the user mutes the activity author" do
216 muter = insert(:user)
217 muted = insert(:user)
218 {:ok, _} = User.mute(muter, muted)
219 muter = Repo.get(User, muter.id)
220 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
222 assert Notification.create_notification(activity, muter)
225 test "notification created if user is muted without notifications" do
226 muter = insert(:user)
227 muted = insert(:user)
229 {:ok, _user_relationships} = User.mute(muter, muted, false)
231 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
233 assert Notification.create_notification(activity, muter)
236 test "it creates a notification for an activity from a muted thread" do
237 muter = insert(:user)
238 other_user = insert(:user)
239 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
240 CommonAPI.add_mute(muter, activity)
243 CommonAPI.post(other_user, %{
244 status: "Hi @#{muter.nickname}",
245 in_reply_to_status_id: activity.id
248 assert Notification.create_notification(activity, muter)
251 test "it disables notifications from followers" do
252 follower = insert(:user)
255 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
257 User.follow(follower, followed)
258 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
259 refute Notification.create_notification(activity, followed)
262 test "it disables notifications from non-followers" do
263 follower = insert(:user)
267 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
270 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
271 refute Notification.create_notification(activity, followed)
274 test "it disables notifications from people the user follows" do
276 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
278 followed = insert(:user)
279 User.follow(follower, followed)
280 follower = Repo.get(User, follower.id)
281 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
282 refute Notification.create_notification(activity, follower)
285 test "it disables notifications from people the user does not follow" do
287 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
289 followed = insert(:user)
290 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
291 refute Notification.create_notification(activity, follower)
294 test "it doesn't create a notification for user if he is the activity author" do
295 activity = insert(:note_activity)
296 author = User.get_cached_by_ap_id(activity.data["actor"])
298 refute Notification.create_notification(activity, author)
301 test "it doesn't create duplicate notifications for follow+subscribed users" do
303 subscriber = insert(:user)
305 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
306 User.subscribe(subscriber, user)
307 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
308 {:ok, [_notif]} = Notification.create_notifications(status)
311 test "it doesn't create subscription notifications if the recipient cannot see the status" do
313 subscriber = insert(:user)
315 User.subscribe(subscriber, user)
317 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
319 assert {:ok, []} == Notification.create_notifications(status)
322 test "it disables notifications from people who are invisible" do
323 author = insert(:user, invisible: true)
326 {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
327 refute Notification.create_notification(status, user)
331 describe "follow / follow_request notifications" do
332 test "it creates `follow` notification for approved Follow activity" do
334 followed_user = insert(:user, locked: false)
336 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
337 assert FollowingRelationship.following?(user, followed_user)
338 assert [notification] = Notification.for_user(followed_user)
340 assert %{type: "follow"} =
341 NotificationView.render("show.json", %{
342 notification: notification,
347 test "it creates `follow_request` notification for pending Follow activity" do
349 followed_user = insert(:user, locked: true)
351 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
352 refute FollowingRelationship.following?(user, followed_user)
353 assert [notification] = Notification.for_user(followed_user)
355 render_opts = %{notification: notification, for: followed_user}
356 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
358 # After request is accepted, the same notification is rendered with type "follow":
359 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
362 Repo.get(Notification, notification.id)
363 |> Repo.preload(:activity)
365 assert %{type: "follow"} =
366 NotificationView.render("show.json", notification: notification, for: followed_user)
369 test "it doesn't create a notification for follow-unfollow-follow chains" do
371 followed_user = insert(:user, locked: false)
373 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
374 assert FollowingRelationship.following?(user, followed_user)
375 assert [notification] = Notification.for_user(followed_user)
377 CommonAPI.unfollow(user, followed_user)
378 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
380 notification_id = notification.id
381 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
384 test "dismisses the notification on follow request rejection" do
385 user = insert(:user, locked: true)
386 follower = insert(:user)
387 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
388 assert [notification] = Notification.for_user(user)
389 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
390 assert [] = Notification.for_user(user)
394 describe "get notification" do
395 test "it gets a notification that belongs to the user" do
397 other_user = insert(:user)
399 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
401 {:ok, [notification]} = Notification.create_notifications(activity)
402 {:ok, notification} = Notification.get(other_user, notification.id)
404 assert notification.user_id == other_user.id
407 test "it returns error if the notification doesn't belong to the user" do
409 other_user = insert(:user)
411 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
413 {:ok, [notification]} = Notification.create_notifications(activity)
414 {:error, _notification} = Notification.get(user, notification.id)
418 describe "dismiss notification" do
419 test "it dismisses a notification that belongs to the user" do
421 other_user = insert(:user)
423 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
425 {:ok, [notification]} = Notification.create_notifications(activity)
426 {:ok, notification} = Notification.dismiss(other_user, notification.id)
428 assert notification.user_id == other_user.id
431 test "it returns error if the notification doesn't belong to the user" do
433 other_user = insert(:user)
435 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
437 {:ok, [notification]} = Notification.create_notifications(activity)
438 {:error, _notification} = Notification.dismiss(user, notification.id)
442 describe "clear notification" do
443 test "it clears all notifications belonging to the user" do
445 other_user = insert(:user)
446 third_user = insert(:user)
449 CommonAPI.post(user, %{
450 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
453 {:ok, _notifs} = Notification.create_notifications(activity)
456 CommonAPI.post(user, %{
457 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
460 {:ok, _notifs} = Notification.create_notifications(activity)
461 Notification.clear(other_user)
463 assert Notification.for_user(other_user) == []
464 assert Notification.for_user(third_user) != []
468 describe "set_read_up_to()" do
469 test "it sets all notifications as read up to a specified notification ID" do
471 other_user = insert(:user)
474 CommonAPI.post(user, %{
475 status: "hey @#{other_user.nickname}!"
479 CommonAPI.post(user, %{
480 status: "hey again @#{other_user.nickname}!"
483 [n2, n1] = Notification.for_user(other_user)
488 CommonAPI.post(user, %{
489 status: "hey yet again @#{other_user.nickname}!"
492 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
494 assert read_notification.activity.object
496 [n3, n2, n1] = Notification.for_user(other_user)
498 assert n1.seen == true
499 assert n2.seen == true
500 assert n3.seen == false
502 assert %Pleroma.Marker{} =
506 user_id: other_user.id,
507 timeline: "notifications"
510 assert m.last_read_id == to_string(n2.id)
514 describe "for_user_since/2" do
515 defp days_ago(days) do
517 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
518 -days * 60 * 60 * 24,
523 test "Returns recent notifications" do
524 user1 = insert(:user)
525 user2 = insert(:user)
527 Enum.each(0..10, fn i ->
529 CommonAPI.post(user1, %{
530 status: "hey ##{i} @#{user2.nickname}!"
534 {old, new} = Enum.split(Notification.for_user(user2), 5)
536 Enum.each(old, fn notification ->
538 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
539 |> Pleroma.Repo.update!()
542 recent_notifications_ids =
544 |> Notification.for_user_since(
545 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
549 Enum.each(old, fn %{id: id} ->
550 refute id in recent_notifications_ids
553 Enum.each(new, fn %{id: id} ->
554 assert id in recent_notifications_ids
559 describe "notification target determination / get_notified_from_activity/2" do
560 test "it sends notifications to addressed users in new messages" do
562 other_user = insert(:user)
565 CommonAPI.post(user, %{
566 status: "hey @#{other_user.nickname}!"
569 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
571 assert other_user in enabled_receivers
574 test "it sends notifications to mentioned users in new messages" do
576 other_user = insert(:user)
579 "@context" => "https://www.w3.org/ns/activitystreams",
581 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
582 "actor" => user.ap_id,
585 "content" => "message with a Mention tag, but no explicit tagging",
589 "href" => other_user.ap_id,
590 "name" => other_user.nickname
593 "attributedTo" => user.ap_id
597 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
599 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
601 assert other_user in enabled_receivers
604 test "it does not send notifications to users who are only cc in new messages" do
606 other_user = insert(:user)
609 "@context" => "https://www.w3.org/ns/activitystreams",
611 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
612 "cc" => [other_user.ap_id],
613 "actor" => user.ap_id,
616 "content" => "hi everyone",
617 "attributedTo" => user.ap_id
621 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
623 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
625 assert other_user not in enabled_receivers
628 test "it does not send notification to mentioned users in likes" do
630 other_user = insert(:user)
631 third_user = insert(:user)
633 {:ok, activity_one} =
634 CommonAPI.post(user, %{
635 status: "hey @#{other_user.nickname}!"
638 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
640 {enabled_receivers, _disabled_receivers} =
641 Notification.get_notified_from_activity(activity_two)
643 assert other_user not in enabled_receivers
646 test "it only notifies the post's author in likes" do
648 other_user = insert(:user)
649 third_user = insert(:user)
651 {:ok, activity_one} =
652 CommonAPI.post(user, %{
653 status: "hey @#{other_user.nickname}!"
656 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
660 |> Map.put("to", [other_user.ap_id | like_data["to"]])
661 |> ActivityPub.persist(local: true)
663 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
665 assert other_user not in enabled_receivers
668 test "it does not send notification to mentioned users in announces" do
670 other_user = insert(:user)
671 third_user = insert(:user)
673 {:ok, activity_one} =
674 CommonAPI.post(user, %{
675 status: "hey @#{other_user.nickname}!"
678 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
680 {enabled_receivers, _disabled_receivers} =
681 Notification.get_notified_from_activity(activity_two)
683 assert other_user not in enabled_receivers
686 test "it returns blocking recipient in disabled recipients list" do
688 other_user = insert(:user)
689 {:ok, _user_relationship} = User.block(other_user, user)
691 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
693 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
695 assert [] == enabled_receivers
696 assert [other_user] == disabled_receivers
699 test "it returns notification-muting recipient in disabled recipients list" do
701 other_user = insert(:user)
702 {:ok, _user_relationships} = User.mute(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 thread-muting recipient in disabled recipients list" do
714 other_user = insert(:user)
716 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
718 {:ok, _} = CommonAPI.add_mute(other_user, activity)
720 {:ok, same_context_activity} =
721 CommonAPI.post(user, %{
722 status: "hey-hey-hey @#{other_user.nickname}!",
723 in_reply_to_status_id: activity.id
726 {enabled_receivers, disabled_receivers} =
727 Notification.get_notified_from_activity(same_context_activity)
729 assert [other_user] == disabled_receivers
730 refute other_user in enabled_receivers
733 test "it returns non-following domain-blocking recipient in disabled recipients list" do
734 blocked_domain = "blocked.domain"
735 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
736 other_user = insert(:user)
738 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
740 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
742 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
744 assert [] == enabled_receivers
745 assert [other_user] == disabled_receivers
748 test "it returns following domain-blocking recipient in enabled recipients list" do
749 blocked_domain = "blocked.domain"
750 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
751 other_user = insert(:user)
753 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
754 {:ok, other_user} = User.follow(other_user, user)
756 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
758 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
760 assert [other_user] == enabled_receivers
761 assert [] == disabled_receivers
765 describe "notification lifecycle" do
766 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
768 other_user = insert(:user)
770 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
772 assert Enum.empty?(Notification.for_user(user))
774 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
776 assert length(Notification.for_user(user)) == 1
778 {:ok, _} = CommonAPI.delete(activity.id, user)
780 assert Enum.empty?(Notification.for_user(user))
783 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
785 other_user = insert(:user)
787 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
789 assert Enum.empty?(Notification.for_user(user))
791 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
793 assert length(Notification.for_user(user)) == 1
795 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
797 assert Enum.empty?(Notification.for_user(user))
800 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
802 other_user = insert(:user)
804 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
806 assert Enum.empty?(Notification.for_user(user))
808 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
810 assert length(Notification.for_user(user)) == 1
812 {:ok, _} = CommonAPI.delete(activity.id, user)
814 assert Enum.empty?(Notification.for_user(user))
817 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
819 other_user = insert(:user)
821 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
823 assert Enum.empty?(Notification.for_user(user))
825 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
827 assert length(Notification.for_user(user)) == 1
829 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
831 assert Enum.empty?(Notification.for_user(user))
834 test "liking an activity which is already deleted does not generate a notification" do
836 other_user = insert(:user)
838 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
840 assert Enum.empty?(Notification.for_user(user))
842 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
844 assert Enum.empty?(Notification.for_user(user))
846 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
848 assert Enum.empty?(Notification.for_user(user))
851 test "repeating an activity which is already deleted does not generate a notification" do
853 other_user = insert(:user)
855 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
857 assert Enum.empty?(Notification.for_user(user))
859 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
861 assert Enum.empty?(Notification.for_user(user))
863 {:error, _} = CommonAPI.repeat(activity.id, other_user)
865 assert Enum.empty?(Notification.for_user(user))
868 test "replying to a deleted post without tagging does not generate a notification" do
870 other_user = insert(:user)
872 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
873 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
875 {:ok, _reply_activity} =
876 CommonAPI.post(other_user, %{
877 status: "test reply",
878 in_reply_to_status_id: activity.id
881 assert Enum.empty?(Notification.for_user(user))
884 test "notifications are deleted if a local user is deleted" do
886 other_user = insert(:user)
889 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
891 refute Enum.empty?(Notification.for_user(other_user))
893 {:ok, job} = User.delete(user)
894 ObanHelpers.perform(job)
896 assert Enum.empty?(Notification.for_user(other_user))
899 test "notifications are deleted if a remote user is deleted" do
900 remote_user = insert(:user)
901 local_user = insert(:user)
904 "@context" => "https://www.w3.org/ns/activitystreams",
906 "actor" => remote_user.ap_id,
907 "id" => remote_user.ap_id <> "/activities/test",
908 "to" => [local_user.ap_id],
912 "content" => "Hello!",
916 "href" => local_user.ap_id,
917 "name" => "@#{local_user.nickname}"
920 "to" => [local_user.ap_id],
922 "attributedTo" => remote_user.ap_id
926 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
928 refute Enum.empty?(Notification.for_user(local_user))
930 delete_user_message = %{
931 "@context" => "https://www.w3.org/ns/activitystreams",
932 "id" => remote_user.ap_id <> "/activities/delete",
933 "actor" => remote_user.ap_id,
935 "object" => remote_user.ap_id
938 remote_user_url = remote_user.ap_id
941 %{method: :get, url: ^remote_user_url} ->
942 %Tesla.Env{status: 404, body: ""}
945 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
946 ObanHelpers.perform_all()
948 assert Enum.empty?(Notification.for_user(local_user))
951 @tag capture_log: true
952 test "move activity generates a notification" do
953 %{ap_id: old_ap_id} = old_user = insert(:user)
954 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
955 follower = insert(:user)
956 other_follower = insert(:user, %{allow_following_move: false})
958 User.follow(follower, old_user)
959 User.follow(other_follower, old_user)
961 old_user_url = old_user.ap_id
964 File.read!("test/fixtures/users_mock/localhost.json")
965 |> String.replace("{{nickname}}", old_user.nickname)
969 %{method: :get, url: ^old_user_url} ->
970 %Tesla.Env{status: 200, body: body}
973 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
974 ObanHelpers.perform_all()
979 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
982 ] = Notification.for_user(follower)
987 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
990 ] = Notification.for_user(other_follower)
994 describe "for_user" do
995 test "it returns notifications for muted user without notifications" do
997 muted = insert(:user)
998 {:ok, _user_relationships} = User.mute(user, muted, false)
1000 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1002 [notification] = Notification.for_user(user)
1004 assert notification.activity.object
1007 test "it doesn't return notifications for muted user with notifications" do
1008 user = insert(:user)
1009 muted = insert(:user)
1010 {:ok, _user_relationships} = User.mute(user, muted)
1012 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1014 assert Notification.for_user(user) == []
1017 test "it doesn't return notifications for blocked user" do
1018 user = insert(:user)
1019 blocked = insert(:user)
1020 {:ok, _user_relationship} = User.block(user, blocked)
1022 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1024 assert Notification.for_user(user) == []
1027 test "it doesn't return notifications for domain-blocked non-followed user" do
1028 user = insert(:user)
1029 blocked = insert(:user, ap_id: "http://some-domain.com")
1030 {:ok, user} = User.block_domain(user, "some-domain.com")
1032 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1034 assert Notification.for_user(user) == []
1037 test "it returns notifications for domain-blocked but followed user" do
1038 user = insert(:user)
1039 blocked = insert(:user, ap_id: "http://some-domain.com")
1041 {:ok, user} = User.block_domain(user, "some-domain.com")
1042 {:ok, _} = User.follow(user, blocked)
1044 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1046 assert length(Notification.for_user(user)) == 1
1049 test "it doesn't return notifications for muted thread" do
1050 user = insert(:user)
1051 another_user = insert(:user)
1053 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1055 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1056 assert Notification.for_user(user) == []
1059 test "it returns notifications from a muted user when with_muted is set" do
1060 user = insert(:user)
1061 muted = insert(:user)
1062 {:ok, _user_relationships} = User.mute(user, muted)
1064 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1066 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1069 test "it doesn't return notifications from a blocked user when with_muted is set" do
1070 user = insert(:user)
1071 blocked = insert(:user)
1072 {:ok, _user_relationship} = User.block(user, blocked)
1074 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1076 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1079 test "when with_muted is set, " <>
1080 "it doesn't return notifications from a domain-blocked non-followed user" do
1081 user = insert(:user)
1082 blocked = insert(:user, ap_id: "http://some-domain.com")
1083 {:ok, user} = User.block_domain(user, "some-domain.com")
1085 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1087 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1090 test "it returns notifications from muted threads when with_muted is set" do
1091 user = insert(:user)
1092 another_user = insert(:user)
1094 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1096 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1097 assert length(Notification.for_user(user, %{with_muted: true})) == 1