1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.NotificationTest do
11 alias Pleroma.FollowingRelationship
12 alias Pleroma.Notification
13 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Builder
17 alias Pleroma.Web.ActivityPub.Transmogrifier
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.MastodonAPI.NotificationView
20 alias Pleroma.Web.Push
21 alias Pleroma.Web.Streamer
23 describe "create_notifications" do
24 test "creates a notification for an emoji reaction" do
26 other_user = insert(:user)
28 {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
29 {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
31 {:ok, [notification]} = Notification.create_notifications(activity)
33 assert notification.user_id == user.id
34 assert notification.type == "pleroma:emoji_reaction"
37 test "notifies someone when they are directly addressed" do
39 other_user = insert(:user)
40 third_user = insert(:user)
43 CommonAPI.post(user, %{
44 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
47 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
49 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
50 assert notified_ids == [other_user.id, third_user.id]
51 assert notification.activity_id == activity.id
52 assert notification.type == "mention"
53 assert other_notification.activity_id == activity.id
55 assert [%Pleroma.Marker{unread_count: 2}] =
56 Pleroma.Marker.get_markers(other_user, ["notifications"])
59 test "it creates a notification for subscribed users" do
61 subscriber = insert(:user)
63 User.subscribe(subscriber, user)
65 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
66 {:ok, [notification]} = Notification.create_notifications(status)
68 assert notification.user_id == subscriber.id
71 test "does not create a notification for subscribed users if status is a reply" do
73 other_user = insert(:user)
74 subscriber = insert(:user)
76 User.subscribe(subscriber, other_user)
78 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
80 {:ok, _reply_activity} =
81 CommonAPI.post(other_user, %{
83 in_reply_to_status_id: activity.id
86 user_notifications = Notification.for_user(user)
87 assert length(user_notifications) == 1
89 subscriber_notifications = Notification.for_user(subscriber)
90 assert Enum.empty?(subscriber_notifications)
94 describe "CommonApi.post/2 notification-related functionality" do
95 test_with_mock "creates but does NOT send notification to blocker user",
100 blocker = insert(:user)
101 {:ok, _user_relationship} = User.block(blocker, user)
103 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
105 blocker_id = blocker.id
106 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
107 refute called(Push.send(:_))
110 test_with_mock "creates but does NOT send notification to notification-muter user",
115 muter = insert(:user)
116 {:ok, _user_relationships} = User.mute(muter, user)
118 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
121 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
122 refute called(Push.send(:_))
125 test_with_mock "creates but does NOT send notification to thread-muter user",
130 thread_muter = insert(:user)
132 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
134 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
136 {:ok, _same_context_activity} =
137 CommonAPI.post(user, %{
138 status: "hey-hey-hey @#{thread_muter.nickname}!",
139 in_reply_to_status_id: activity.id
142 [pre_mute_notification, post_mute_notification] =
143 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
145 pre_mute_notification_id = pre_mute_notification.id
146 post_mute_notification_id = post_mute_notification.id
151 %Notification{id: ^pre_mute_notification_id} -> true
160 %Notification{id: ^post_mute_notification_id} -> true
168 describe "create_notification" do
169 @tag needs_streamer: true
170 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
175 Streamer.get_topic_and_add_socket("user", user)
176 assert_receive {:render_with_user, _, _, _}, 4_000
179 task_user_notification =
181 Streamer.get_topic_and_add_socket("user:notification", user)
182 assert_receive {:render_with_user, _, _, _}, 4_000
185 activity = insert(:note_activity)
187 notify = Notification.create_notification(activity, user)
188 assert notify.user_id == user.id
190 Task.await(task_user_notification)
193 test "it creates a notification for user if the user blocks the activity author" do
194 activity = insert(:note_activity)
195 author = User.get_cached_by_ap_id(activity.data["actor"])
197 {:ok, _user_relationship} = User.block(user, author)
199 assert Notification.create_notification(activity, user)
202 test "it creates a notification for the user if the user mutes the activity author" do
203 muter = insert(:user)
204 muted = insert(:user)
205 {:ok, _} = User.mute(muter, muted)
206 muter = Repo.get(User, muter.id)
207 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
209 assert Notification.create_notification(activity, muter)
212 test "notification created if user is muted without notifications" do
213 muter = insert(:user)
214 muted = insert(:user)
216 {:ok, _user_relationships} = User.mute(muter, muted, false)
218 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
220 assert Notification.create_notification(activity, muter)
223 test "it creates a notification for an activity from a muted thread" do
224 muter = insert(:user)
225 other_user = insert(:user)
226 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
227 CommonAPI.add_mute(muter, activity)
230 CommonAPI.post(other_user, %{
231 status: "Hi @#{muter.nickname}",
232 in_reply_to_status_id: activity.id
235 assert Notification.create_notification(activity, muter)
238 test "it disables notifications from followers" do
239 follower = insert(:user)
242 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
244 User.follow(follower, followed)
245 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
246 refute Notification.create_notification(activity, followed)
249 test "it disables notifications from non-followers" do
250 follower = insert(:user)
254 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
257 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
258 refute Notification.create_notification(activity, followed)
261 test "it disables notifications from people the user follows" do
263 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
265 followed = insert(:user)
266 User.follow(follower, followed)
267 follower = Repo.get(User, follower.id)
268 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
269 refute Notification.create_notification(activity, follower)
272 test "it disables notifications from people the user does not follow" do
274 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
276 followed = insert(:user)
277 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
278 refute Notification.create_notification(activity, follower)
281 test "it doesn't create a notification for user if he is the activity author" do
282 activity = insert(:note_activity)
283 author = User.get_cached_by_ap_id(activity.data["actor"])
285 refute Notification.create_notification(activity, author)
288 test "it doesn't create duplicate notifications for follow+subscribed users" do
290 subscriber = insert(:user)
292 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
293 User.subscribe(subscriber, user)
294 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
295 {:ok, [_notif]} = Notification.create_notifications(status)
298 test "it doesn't create subscription notifications if the recipient cannot see the status" do
300 subscriber = insert(:user)
302 User.subscribe(subscriber, user)
304 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
306 assert {:ok, []} == Notification.create_notifications(status)
310 describe "follow / follow_request notifications" do
311 test "it creates `follow` notification for approved Follow activity" do
313 followed_user = insert(:user, locked: false)
315 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
316 assert FollowingRelationship.following?(user, followed_user)
317 assert [notification] = Notification.for_user(followed_user)
319 assert %{type: "follow"} =
320 NotificationView.render("show.json", %{
321 notification: notification,
326 test "it creates `follow_request` notification for pending Follow activity" do
328 followed_user = insert(:user, locked: true)
330 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
331 refute FollowingRelationship.following?(user, followed_user)
332 assert [notification] = Notification.for_user(followed_user)
334 render_opts = %{notification: notification, for: followed_user}
335 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
337 # After request is accepted, the same notification is rendered with type "follow":
338 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
341 Repo.get(Notification, notification.id)
342 |> Repo.preload(:activity)
344 assert %{type: "follow"} =
345 NotificationView.render("show.json", notification: notification, for: followed_user)
348 test "it doesn't create a notification for follow-unfollow-follow chains" do
350 followed_user = insert(:user, locked: false)
352 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
353 assert FollowingRelationship.following?(user, followed_user)
354 assert [notification] = Notification.for_user(followed_user)
356 CommonAPI.unfollow(user, followed_user)
357 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
359 notification_id = notification.id
360 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
363 test "dismisses the notification on follow request rejection" do
364 user = insert(:user, locked: true)
365 follower = insert(:user)
366 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
367 assert [notification] = Notification.for_user(user)
368 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
369 assert [] = Notification.for_user(user)
373 describe "get notification" do
374 test "it gets a notification that belongs to the user" do
376 other_user = insert(:user)
378 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
380 {:ok, [notification]} = Notification.create_notifications(activity)
381 {:ok, notification} = Notification.get(other_user, notification.id)
383 assert notification.user_id == other_user.id
386 test "it returns error if the notification doesn't belong to the user" do
388 other_user = insert(:user)
390 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
392 {:ok, [notification]} = Notification.create_notifications(activity)
393 {:error, _notification} = Notification.get(user, notification.id)
397 describe "dismiss notification" do
398 test "it dismisses a notification that belongs to the user" do
400 other_user = insert(:user)
402 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
404 {:ok, [notification]} = Notification.create_notifications(activity)
405 {:ok, notification} = Notification.dismiss(other_user, notification.id)
407 assert notification.user_id == other_user.id
410 test "it returns error if the notification doesn't belong to the user" do
412 other_user = insert(:user)
414 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
416 {:ok, [notification]} = Notification.create_notifications(activity)
417 {:error, _notification} = Notification.dismiss(user, notification.id)
421 describe "clear notification" do
422 test "it clears all notifications belonging to the user" do
424 other_user = insert(:user)
425 third_user = insert(:user)
428 CommonAPI.post(user, %{
429 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
432 {:ok, _notifs} = Notification.create_notifications(activity)
435 CommonAPI.post(user, %{
436 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
439 {:ok, _notifs} = Notification.create_notifications(activity)
440 Notification.clear(other_user)
442 assert Notification.for_user(other_user) == []
443 assert Notification.for_user(third_user) != []
447 describe "set_read_up_to()" do
448 test "it sets all notifications as read up to a specified notification ID" do
450 other_user = insert(:user)
453 CommonAPI.post(user, %{
454 status: "hey @#{other_user.nickname}!"
458 CommonAPI.post(user, %{
459 status: "hey again @#{other_user.nickname}!"
462 [n2, n1] = Notification.for_user(other_user)
467 CommonAPI.post(user, %{
468 status: "hey yet again @#{other_user.nickname}!"
471 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
473 assert read_notification.activity.object
475 [n3, n2, n1] = Notification.for_user(other_user)
477 assert n1.seen == true
478 assert n2.seen == true
479 assert n3.seen == false
481 assert %Pleroma.Marker{} =
485 user_id: other_user.id,
486 timeline: "notifications"
489 assert m.last_read_id == to_string(n2.id)
493 describe "for_user_since/2" do
494 defp days_ago(days) do
496 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
497 -days * 60 * 60 * 24,
502 test "Returns recent notifications" do
503 user1 = insert(:user)
504 user2 = insert(:user)
506 Enum.each(0..10, fn i ->
508 CommonAPI.post(user1, %{
509 status: "hey ##{i} @#{user2.nickname}!"
513 {old, new} = Enum.split(Notification.for_user(user2), 5)
515 Enum.each(old, fn notification ->
517 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
518 |> Pleroma.Repo.update!()
521 recent_notifications_ids =
523 |> Notification.for_user_since(
524 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
528 Enum.each(old, fn %{id: id} ->
529 refute id in recent_notifications_ids
532 Enum.each(new, fn %{id: id} ->
533 assert id in recent_notifications_ids
538 describe "notification target determination / get_notified_from_activity/2" do
539 test "it sends notifications to addressed users in new messages" do
541 other_user = insert(:user)
544 CommonAPI.post(user, %{
545 status: "hey @#{other_user.nickname}!"
548 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
550 assert other_user in enabled_receivers
553 test "it sends notifications to mentioned users in new messages" do
555 other_user = insert(:user)
558 "@context" => "https://www.w3.org/ns/activitystreams",
560 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
561 "actor" => user.ap_id,
564 "content" => "message with a Mention tag, but no explicit tagging",
568 "href" => other_user.ap_id,
569 "name" => other_user.nickname
572 "attributedTo" => user.ap_id
576 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
578 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
580 assert other_user in enabled_receivers
583 test "it does not send notifications to users who are only cc in new messages" do
585 other_user = insert(:user)
588 "@context" => "https://www.w3.org/ns/activitystreams",
590 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
591 "cc" => [other_user.ap_id],
592 "actor" => user.ap_id,
595 "content" => "hi everyone",
596 "attributedTo" => user.ap_id
600 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
602 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
604 assert other_user not in enabled_receivers
607 test "it does not send notification to mentioned users in likes" do
609 other_user = insert(:user)
610 third_user = insert(:user)
612 {:ok, activity_one} =
613 CommonAPI.post(user, %{
614 status: "hey @#{other_user.nickname}!"
617 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
619 {enabled_receivers, _disabled_receivers} =
620 Notification.get_notified_from_activity(activity_two)
622 assert other_user not in enabled_receivers
625 test "it only notifies the post's author in likes" do
627 other_user = insert(:user)
628 third_user = insert(:user)
630 {:ok, activity_one} =
631 CommonAPI.post(user, %{
632 status: "hey @#{other_user.nickname}!"
635 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
639 |> Map.put("to", [other_user.ap_id | like_data["to"]])
640 |> ActivityPub.persist(local: true)
642 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
644 assert other_user not in enabled_receivers
647 test "it does not send notification to mentioned users in announces" do
649 other_user = insert(:user)
650 third_user = insert(:user)
652 {:ok, activity_one} =
653 CommonAPI.post(user, %{
654 status: "hey @#{other_user.nickname}!"
657 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
659 {enabled_receivers, _disabled_receivers} =
660 Notification.get_notified_from_activity(activity_two)
662 assert other_user not in enabled_receivers
665 test "it returns blocking recipient in disabled recipients list" do
667 other_user = insert(:user)
668 {:ok, _user_relationship} = User.block(other_user, user)
670 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
672 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
674 assert [] == enabled_receivers
675 assert [other_user] == disabled_receivers
678 test "it returns notification-muting recipient in disabled recipients list" do
680 other_user = insert(:user)
681 {:ok, _user_relationships} = User.mute(other_user, user)
683 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
685 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
687 assert [] == enabled_receivers
688 assert [other_user] == disabled_receivers
691 test "it returns thread-muting recipient in disabled recipients list" do
693 other_user = insert(:user)
695 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
697 {:ok, _} = CommonAPI.add_mute(other_user, activity)
699 {:ok, same_context_activity} =
700 CommonAPI.post(user, %{
701 status: "hey-hey-hey @#{other_user.nickname}!",
702 in_reply_to_status_id: activity.id
705 {enabled_receivers, disabled_receivers} =
706 Notification.get_notified_from_activity(same_context_activity)
708 assert [other_user] == disabled_receivers
709 refute other_user in enabled_receivers
712 test "it returns non-following domain-blocking recipient in disabled recipients list" do
713 blocked_domain = "blocked.domain"
714 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
715 other_user = insert(:user)
717 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
719 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
721 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
723 assert [] == enabled_receivers
724 assert [other_user] == disabled_receivers
727 test "it returns following domain-blocking recipient in enabled recipients list" do
728 blocked_domain = "blocked.domain"
729 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
730 other_user = insert(:user)
732 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
733 {:ok, other_user} = User.follow(other_user, user)
735 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
737 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
739 assert [other_user] == enabled_receivers
740 assert [] == disabled_receivers
744 describe "notification lifecycle" do
745 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
747 other_user = insert(:user)
749 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
751 assert Enum.empty?(Notification.for_user(user))
753 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
755 assert length(Notification.for_user(user)) == 1
757 {:ok, _} = CommonAPI.delete(activity.id, user)
759 assert Enum.empty?(Notification.for_user(user))
762 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
764 other_user = insert(:user)
766 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
768 assert Enum.empty?(Notification.for_user(user))
770 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
772 assert length(Notification.for_user(user)) == 1
774 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
776 assert Enum.empty?(Notification.for_user(user))
779 test "repeating 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.repeat(activity.id, other_user)
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 "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" 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.repeat(activity.id, other_user)
806 assert length(Notification.for_user(user)) == 1
808 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
810 assert Enum.empty?(Notification.for_user(user))
813 test "liking an activity which is already deleted does not generate a notification" 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, _deletion_activity} = CommonAPI.delete(activity.id, user)
823 assert Enum.empty?(Notification.for_user(user))
825 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
827 assert Enum.empty?(Notification.for_user(user))
830 test "repeating an activity which is already deleted does not generate a notification" 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, _deletion_activity} = CommonAPI.delete(activity.id, user)
840 assert Enum.empty?(Notification.for_user(user))
842 {:error, _} = CommonAPI.repeat(activity.id, other_user)
844 assert Enum.empty?(Notification.for_user(user))
847 test "replying to a deleted post without tagging does not generate a notification" do
849 other_user = insert(:user)
851 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
852 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
854 {:ok, _reply_activity} =
855 CommonAPI.post(other_user, %{
856 status: "test reply",
857 in_reply_to_status_id: activity.id
860 assert Enum.empty?(Notification.for_user(user))
863 test "notifications are deleted if a local user is deleted" do
865 other_user = insert(:user)
868 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
870 refute Enum.empty?(Notification.for_user(other_user))
872 {:ok, job} = User.delete(user)
873 ObanHelpers.perform(job)
875 assert Enum.empty?(Notification.for_user(other_user))
878 test "notifications are deleted if a remote user is deleted" do
879 remote_user = insert(:user)
880 local_user = insert(:user)
883 "@context" => "https://www.w3.org/ns/activitystreams",
885 "actor" => remote_user.ap_id,
886 "id" => remote_user.ap_id <> "/activities/test",
887 "to" => [local_user.ap_id],
891 "content" => "Hello!",
895 "href" => local_user.ap_id,
896 "name" => "@#{local_user.nickname}"
899 "to" => [local_user.ap_id],
901 "attributedTo" => remote_user.ap_id
905 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
907 refute Enum.empty?(Notification.for_user(local_user))
909 delete_user_message = %{
910 "@context" => "https://www.w3.org/ns/activitystreams",
911 "id" => remote_user.ap_id <> "/activities/delete",
912 "actor" => remote_user.ap_id,
914 "object" => remote_user.ap_id
917 remote_user_url = remote_user.ap_id
920 %{method: :get, url: ^remote_user_url} ->
921 %Tesla.Env{status: 404, body: ""}
924 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
925 ObanHelpers.perform_all()
927 assert Enum.empty?(Notification.for_user(local_user))
930 @tag capture_log: true
931 test "move activity generates a notification" do
932 %{ap_id: old_ap_id} = old_user = insert(:user)
933 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
934 follower = insert(:user)
935 other_follower = insert(:user, %{allow_following_move: false})
937 User.follow(follower, old_user)
938 User.follow(other_follower, old_user)
940 old_user_url = old_user.ap_id
943 File.read!("test/fixtures/users_mock/localhost.json")
944 |> String.replace("{{nickname}}", old_user.nickname)
948 %{method: :get, url: ^old_user_url} ->
949 %Tesla.Env{status: 200, body: body}
952 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
953 ObanHelpers.perform_all()
958 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
961 ] = Notification.for_user(follower)
966 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
969 ] = Notification.for_user(other_follower)
973 describe "for_user" do
974 test "it returns notifications for muted user without notifications" do
976 muted = insert(:user)
977 {:ok, _user_relationships} = User.mute(user, muted, false)
979 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
981 [notification] = Notification.for_user(user)
983 assert notification.activity.object
986 test "it doesn't return notifications for muted user with notifications" do
988 muted = insert(:user)
989 {:ok, _user_relationships} = User.mute(user, muted)
991 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
993 assert Notification.for_user(user) == []
996 test "it doesn't return notifications for blocked user" do
998 blocked = insert(:user)
999 {:ok, _user_relationship} = User.block(user, blocked)
1001 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1003 assert Notification.for_user(user) == []
1006 test "it doesn't return notifications for domain-blocked non-followed user" do
1007 user = insert(:user)
1008 blocked = insert(:user, ap_id: "http://some-domain.com")
1009 {:ok, user} = User.block_domain(user, "some-domain.com")
1011 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1013 assert Notification.for_user(user) == []
1016 test "it returns notifications for domain-blocked but followed user" do
1017 user = insert(:user)
1018 blocked = insert(:user, ap_id: "http://some-domain.com")
1020 {:ok, user} = User.block_domain(user, "some-domain.com")
1021 {:ok, _} = User.follow(user, blocked)
1023 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1025 assert length(Notification.for_user(user)) == 1
1028 test "it doesn't return notifications for muted thread" do
1029 user = insert(:user)
1030 another_user = insert(:user)
1032 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1034 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1035 assert Notification.for_user(user) == []
1038 test "it returns notifications from a muted user when with_muted is set" do
1039 user = insert(:user)
1040 muted = insert(:user)
1041 {:ok, _user_relationships} = User.mute(user, muted)
1043 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1045 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1048 test "it doesn't return notifications from a blocked user when with_muted is set" do
1049 user = insert(:user)
1050 blocked = insert(:user)
1051 {:ok, _user_relationship} = User.block(user, blocked)
1053 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1055 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1058 test "when with_muted is set, " <>
1059 "it doesn't return notifications from a domain-blocked non-followed user" do
1060 user = insert(:user)
1061 blocked = insert(:user, ap_id: "http://some-domain.com")
1062 {:ok, user} = User.block_domain(user, "some-domain.com")
1064 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1066 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1069 test "it returns notifications from muted threads when with_muted is set" do
1070 user = insert(:user)
1071 another_user = insert(:user)
1073 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1075 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1076 assert length(Notification.for_user(user, %{with_muted: true})) == 1