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
36 test "notifies someone when they are directly addressed" do
38 other_user = insert(:user)
39 third_user = insert(:user)
42 CommonAPI.post(user, %{
43 status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
46 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
48 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
49 assert notified_ids == [other_user.id, third_user.id]
50 assert notification.activity_id == activity.id
51 assert other_notification.activity_id == activity.id
53 assert [%Pleroma.Marker{unread_count: 2}] =
54 Pleroma.Marker.get_markers(other_user, ["notifications"])
57 test "it creates a notification for subscribed users" do
59 subscriber = insert(:user)
61 User.subscribe(subscriber, user)
63 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
64 {:ok, [notification]} = Notification.create_notifications(status)
66 assert notification.user_id == subscriber.id
69 test "does not create a notification for subscribed users if status is a reply" do
71 other_user = insert(:user)
72 subscriber = insert(:user)
74 User.subscribe(subscriber, other_user)
76 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
78 {:ok, _reply_activity} =
79 CommonAPI.post(other_user, %{
81 in_reply_to_status_id: activity.id
84 user_notifications = Notification.for_user(user)
85 assert length(user_notifications) == 1
87 subscriber_notifications = Notification.for_user(subscriber)
88 assert Enum.empty?(subscriber_notifications)
92 describe "CommonApi.post/2 notification-related functionality" do
93 test_with_mock "creates but does NOT send notification to blocker user",
98 blocker = insert(:user)
99 {:ok, _user_relationship} = User.block(blocker, user)
101 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
103 blocker_id = blocker.id
104 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
105 refute called(Push.send(:_))
108 test_with_mock "creates but does NOT send notification to notification-muter user",
113 muter = insert(:user)
114 {:ok, _user_relationships} = User.mute(muter, user)
116 {:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
119 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
120 refute called(Push.send(:_))
123 test_with_mock "creates but does NOT send notification to thread-muter user",
128 thread_muter = insert(:user)
130 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
132 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
134 {:ok, _same_context_activity} =
135 CommonAPI.post(user, %{
136 status: "hey-hey-hey @#{thread_muter.nickname}!",
137 in_reply_to_status_id: activity.id
140 [pre_mute_notification, post_mute_notification] =
141 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
143 pre_mute_notification_id = pre_mute_notification.id
144 post_mute_notification_id = post_mute_notification.id
149 %Notification{id: ^pre_mute_notification_id} -> true
158 %Notification{id: ^post_mute_notification_id} -> true
166 describe "create_notification" do
167 @tag needs_streamer: true
168 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
173 Streamer.get_topic_and_add_socket("user", user)
174 assert_receive {:render_with_user, _, _, _}, 4_000
177 task_user_notification =
179 Streamer.get_topic_and_add_socket("user:notification", user)
180 assert_receive {:render_with_user, _, _, _}, 4_000
183 activity = insert(:note_activity)
185 notify = Notification.create_notification(activity, user)
186 assert notify.user_id == user.id
188 Task.await(task_user_notification)
191 test "it creates a notification for user if the user blocks the activity author" do
192 activity = insert(:note_activity)
193 author = User.get_cached_by_ap_id(activity.data["actor"])
195 {:ok, _user_relationship} = User.block(user, author)
197 assert Notification.create_notification(activity, user)
200 test "it creates a notification for the user if the user mutes the activity author" do
201 muter = insert(:user)
202 muted = insert(:user)
203 {:ok, _} = User.mute(muter, muted)
204 muter = Repo.get(User, muter.id)
205 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
207 assert Notification.create_notification(activity, muter)
210 test "notification created if user is muted without notifications" do
211 muter = insert(:user)
212 muted = insert(:user)
214 {:ok, _user_relationships} = User.mute(muter, muted, false)
216 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
218 assert Notification.create_notification(activity, muter)
221 test "it creates a notification for an activity from a muted thread" do
222 muter = insert(:user)
223 other_user = insert(:user)
224 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
225 CommonAPI.add_mute(muter, activity)
228 CommonAPI.post(other_user, %{
229 status: "Hi @#{muter.nickname}",
230 in_reply_to_status_id: activity.id
233 assert Notification.create_notification(activity, muter)
236 test "it disables notifications from followers" do
237 follower = insert(:user)
240 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
242 User.follow(follower, followed)
243 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
244 refute Notification.create_notification(activity, followed)
247 test "it disables notifications from non-followers" do
248 follower = insert(:user)
252 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
255 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
256 refute Notification.create_notification(activity, followed)
259 test "it disables notifications from people the user follows" do
261 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
263 followed = insert(:user)
264 User.follow(follower, followed)
265 follower = Repo.get(User, follower.id)
266 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
267 refute Notification.create_notification(activity, follower)
270 test "it disables notifications from people the user does not follow" do
272 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
274 followed = insert(:user)
275 {:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
276 refute Notification.create_notification(activity, follower)
279 test "it doesn't create a notification for user if he is the activity author" do
280 activity = insert(:note_activity)
281 author = User.get_cached_by_ap_id(activity.data["actor"])
283 refute Notification.create_notification(activity, author)
286 test "it doesn't create duplicate notifications for follow+subscribed users" do
288 subscriber = insert(:user)
290 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
291 User.subscribe(subscriber, user)
292 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
293 {:ok, [_notif]} = Notification.create_notifications(status)
296 test "it doesn't create subscription notifications if the recipient cannot see the status" do
298 subscriber = insert(:user)
300 User.subscribe(subscriber, user)
302 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
304 assert {:ok, []} == Notification.create_notifications(status)
308 describe "follow / follow_request notifications" do
309 test "it creates `follow` notification for approved Follow activity" do
311 followed_user = insert(:user, locked: false)
313 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
314 assert FollowingRelationship.following?(user, followed_user)
315 assert [notification] = Notification.for_user(followed_user)
317 assert %{type: "follow"} =
318 NotificationView.render("show.json", %{
319 notification: notification,
324 test "it creates `follow_request` notification for pending Follow activity" do
326 followed_user = insert(:user, locked: true)
328 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
329 refute FollowingRelationship.following?(user, followed_user)
330 assert [notification] = Notification.for_user(followed_user)
332 render_opts = %{notification: notification, for: followed_user}
333 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
335 # After request is accepted, the same notification is rendered with type "follow":
336 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
338 notification_id = notification.id
339 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
340 assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
343 test "it doesn't create a notification for follow-unfollow-follow chains" do
345 followed_user = insert(:user, locked: false)
347 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
348 assert FollowingRelationship.following?(user, followed_user)
349 assert [notification] = Notification.for_user(followed_user)
351 CommonAPI.unfollow(user, followed_user)
352 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
354 notification_id = notification.id
355 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
358 test "dismisses the notification on follow request rejection" do
359 user = insert(:user, locked: true)
360 follower = insert(:user)
361 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
362 assert [notification] = Notification.for_user(user)
363 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
364 assert [] = Notification.for_user(user)
368 describe "get notification" do
369 test "it gets a notification that belongs to the user" do
371 other_user = insert(:user)
373 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
375 {:ok, [notification]} = Notification.create_notifications(activity)
376 {:ok, notification} = Notification.get(other_user, notification.id)
378 assert notification.user_id == other_user.id
381 test "it returns error if the notification doesn't belong to the user" do
383 other_user = insert(:user)
385 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
387 {:ok, [notification]} = Notification.create_notifications(activity)
388 {:error, _notification} = Notification.get(user, notification.id)
392 describe "dismiss notification" do
393 test "it dismisses 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.dismiss(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.dismiss(user, notification.id)
416 describe "clear notification" do
417 test "it clears all notifications belonging to the user" do
419 other_user = insert(:user)
420 third_user = insert(:user)
423 CommonAPI.post(user, %{
424 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
427 {:ok, _notifs} = Notification.create_notifications(activity)
430 CommonAPI.post(user, %{
431 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
434 {:ok, _notifs} = Notification.create_notifications(activity)
435 Notification.clear(other_user)
437 assert Notification.for_user(other_user) == []
438 assert Notification.for_user(third_user) != []
442 describe "set_read_up_to()" do
443 test "it sets all notifications as read up to a specified notification ID" do
445 other_user = insert(:user)
448 CommonAPI.post(user, %{
449 status: "hey @#{other_user.nickname}!"
453 CommonAPI.post(user, %{
454 status: "hey again @#{other_user.nickname}!"
457 [n2, n1] = Notification.for_user(other_user)
462 CommonAPI.post(user, %{
463 status: "hey yet again @#{other_user.nickname}!"
466 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
468 assert read_notification.activity.object
470 [n3, n2, n1] = Notification.for_user(other_user)
472 assert n1.seen == true
473 assert n2.seen == true
474 assert n3.seen == false
476 assert %Pleroma.Marker{} =
480 user_id: other_user.id,
481 timeline: "notifications"
484 assert m.last_read_id == to_string(n2.id)
488 describe "for_user_since/2" do
489 defp days_ago(days) do
491 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
492 -days * 60 * 60 * 24,
497 test "Returns recent notifications" do
498 user1 = insert(:user)
499 user2 = insert(:user)
501 Enum.each(0..10, fn i ->
503 CommonAPI.post(user1, %{
504 status: "hey ##{i} @#{user2.nickname}!"
508 {old, new} = Enum.split(Notification.for_user(user2), 5)
510 Enum.each(old, fn notification ->
512 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
513 |> Pleroma.Repo.update!()
516 recent_notifications_ids =
518 |> Notification.for_user_since(
519 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
523 Enum.each(old, fn %{id: id} ->
524 refute id in recent_notifications_ids
527 Enum.each(new, fn %{id: id} ->
528 assert id in recent_notifications_ids
533 describe "notification target determination / get_notified_from_activity/2" do
534 test "it sends notifications to addressed users in new messages" do
536 other_user = insert(:user)
539 CommonAPI.post(user, %{
540 status: "hey @#{other_user.nickname}!"
543 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
545 assert other_user in enabled_receivers
548 test "it sends notifications to mentioned users in new messages" do
550 other_user = insert(:user)
553 "@context" => "https://www.w3.org/ns/activitystreams",
555 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
556 "actor" => user.ap_id,
559 "content" => "message with a Mention tag, but no explicit tagging",
563 "href" => other_user.ap_id,
564 "name" => other_user.nickname
567 "attributedTo" => user.ap_id
571 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
573 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
575 assert other_user in enabled_receivers
578 test "it does not send notifications to users who are only cc in new messages" do
580 other_user = insert(:user)
583 "@context" => "https://www.w3.org/ns/activitystreams",
585 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
586 "cc" => [other_user.ap_id],
587 "actor" => user.ap_id,
590 "content" => "hi everyone",
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 not in enabled_receivers
602 test "it does not send notification to mentioned users in likes" do
604 other_user = insert(:user)
605 third_user = insert(:user)
607 {:ok, activity_one} =
608 CommonAPI.post(user, %{
609 status: "hey @#{other_user.nickname}!"
612 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
614 {enabled_receivers, _disabled_receivers} =
615 Notification.get_notified_from_activity(activity_two)
617 assert other_user not in enabled_receivers
620 test "it only notifies the post's author in likes" do
622 other_user = insert(:user)
623 third_user = insert(:user)
625 {:ok, activity_one} =
626 CommonAPI.post(user, %{
627 status: "hey @#{other_user.nickname}!"
630 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
634 |> Map.put("to", [other_user.ap_id | like_data["to"]])
635 |> ActivityPub.persist(local: true)
637 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
639 assert other_user not in enabled_receivers
642 test "it does not send notification to mentioned users in announces" do
644 other_user = insert(:user)
645 third_user = insert(:user)
647 {:ok, activity_one} =
648 CommonAPI.post(user, %{
649 status: "hey @#{other_user.nickname}!"
652 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
654 {enabled_receivers, _disabled_receivers} =
655 Notification.get_notified_from_activity(activity_two)
657 assert other_user not in enabled_receivers
660 test "it returns blocking recipient in disabled recipients list" do
662 other_user = insert(:user)
663 {:ok, _user_relationship} = User.block(other_user, user)
665 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
667 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
669 assert [] == enabled_receivers
670 assert [other_user] == disabled_receivers
673 test "it returns notification-muting recipient in disabled recipients list" do
675 other_user = insert(:user)
676 {:ok, _user_relationships} = User.mute(other_user, user)
678 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
680 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
682 assert [] == enabled_receivers
683 assert [other_user] == disabled_receivers
686 test "it returns thread-muting recipient in disabled recipients list" do
688 other_user = insert(:user)
690 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
692 {:ok, _} = CommonAPI.add_mute(other_user, activity)
694 {:ok, same_context_activity} =
695 CommonAPI.post(user, %{
696 status: "hey-hey-hey @#{other_user.nickname}!",
697 in_reply_to_status_id: activity.id
700 {enabled_receivers, disabled_receivers} =
701 Notification.get_notified_from_activity(same_context_activity)
703 assert [other_user] == disabled_receivers
704 refute other_user in enabled_receivers
707 test "it returns non-following domain-blocking recipient in disabled recipients list" do
708 blocked_domain = "blocked.domain"
709 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
710 other_user = insert(:user)
712 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
714 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
716 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
718 assert [] == enabled_receivers
719 assert [other_user] == disabled_receivers
722 test "it returns following domain-blocking recipient in enabled recipients list" do
723 blocked_domain = "blocked.domain"
724 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
725 other_user = insert(:user)
727 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
728 {:ok, other_user} = User.follow(other_user, user)
730 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
732 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
734 assert [other_user] == enabled_receivers
735 assert [] == disabled_receivers
739 describe "notification lifecycle" do
740 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
742 other_user = insert(:user)
744 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
746 assert Enum.empty?(Notification.for_user(user))
748 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
750 assert length(Notification.for_user(user)) == 1
752 {:ok, _} = CommonAPI.delete(activity.id, user)
754 assert Enum.empty?(Notification.for_user(user))
757 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
759 other_user = insert(:user)
761 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
763 assert Enum.empty?(Notification.for_user(user))
765 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
767 assert length(Notification.for_user(user)) == 1
769 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
771 assert Enum.empty?(Notification.for_user(user))
774 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
776 other_user = insert(:user)
778 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
780 assert Enum.empty?(Notification.for_user(user))
782 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
784 assert length(Notification.for_user(user)) == 1
786 {:ok, _} = CommonAPI.delete(activity.id, user)
788 assert Enum.empty?(Notification.for_user(user))
791 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
793 other_user = insert(:user)
795 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
797 assert Enum.empty?(Notification.for_user(user))
799 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
801 assert length(Notification.for_user(user)) == 1
803 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
805 assert Enum.empty?(Notification.for_user(user))
808 test "liking an activity which is already deleted does not generate a notification" do
810 other_user = insert(:user)
812 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
814 assert Enum.empty?(Notification.for_user(user))
816 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
818 assert Enum.empty?(Notification.for_user(user))
820 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
822 assert Enum.empty?(Notification.for_user(user))
825 test "repeating an activity which is already deleted does not generate a notification" do
827 other_user = insert(:user)
829 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
831 assert Enum.empty?(Notification.for_user(user))
833 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
835 assert Enum.empty?(Notification.for_user(user))
837 {:error, _} = CommonAPI.repeat(activity.id, other_user)
839 assert Enum.empty?(Notification.for_user(user))
842 test "replying to a deleted post without tagging does not generate a notification" do
844 other_user = insert(:user)
846 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
847 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
849 {:ok, _reply_activity} =
850 CommonAPI.post(other_user, %{
851 status: "test reply",
852 in_reply_to_status_id: activity.id
855 assert Enum.empty?(Notification.for_user(user))
858 test "notifications are deleted if a local user is deleted" do
860 other_user = insert(:user)
863 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
865 refute Enum.empty?(Notification.for_user(other_user))
867 {:ok, job} = User.delete(user)
868 ObanHelpers.perform(job)
870 assert Enum.empty?(Notification.for_user(other_user))
873 test "notifications are deleted if a remote user is deleted" do
874 remote_user = insert(:user)
875 local_user = insert(:user)
878 "@context" => "https://www.w3.org/ns/activitystreams",
880 "actor" => remote_user.ap_id,
881 "id" => remote_user.ap_id <> "/activities/test",
882 "to" => [local_user.ap_id],
886 "content" => "Hello!",
890 "href" => local_user.ap_id,
891 "name" => "@#{local_user.nickname}"
894 "to" => [local_user.ap_id],
896 "attributedTo" => remote_user.ap_id
900 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
902 refute Enum.empty?(Notification.for_user(local_user))
904 delete_user_message = %{
905 "@context" => "https://www.w3.org/ns/activitystreams",
906 "id" => remote_user.ap_id <> "/activities/delete",
907 "actor" => remote_user.ap_id,
909 "object" => remote_user.ap_id
912 remote_user_url = remote_user.ap_id
915 %{method: :get, url: ^remote_user_url} ->
916 %Tesla.Env{status: 404, body: ""}
919 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
920 ObanHelpers.perform_all()
922 assert Enum.empty?(Notification.for_user(local_user))
925 @tag capture_log: true
926 test "move activity generates a notification" do
927 %{ap_id: old_ap_id} = old_user = insert(:user)
928 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
929 follower = insert(:user)
930 other_follower = insert(:user, %{allow_following_move: false})
932 User.follow(follower, old_user)
933 User.follow(other_follower, old_user)
935 old_user_url = old_user.ap_id
938 File.read!("test/fixtures/users_mock/localhost.json")
939 |> String.replace("{{nickname}}", old_user.nickname)
943 %{method: :get, url: ^old_user_url} ->
944 %Tesla.Env{status: 200, body: body}
947 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
948 ObanHelpers.perform_all()
953 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
956 ] = Notification.for_user(follower)
961 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
964 ] = Notification.for_user(other_follower)
968 describe "for_user" do
969 test "it returns notifications for muted user without notifications" do
971 muted = insert(:user)
972 {:ok, _user_relationships} = User.mute(user, muted, false)
974 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
976 [notification] = Notification.for_user(user)
978 assert notification.activity.object
981 test "it doesn't return notifications for muted user with notifications" do
983 muted = insert(:user)
984 {:ok, _user_relationships} = User.mute(user, muted)
986 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
988 assert Notification.for_user(user) == []
991 test "it doesn't return notifications for blocked user" do
993 blocked = insert(:user)
994 {:ok, _user_relationship} = User.block(user, blocked)
996 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
998 assert Notification.for_user(user) == []
1001 test "it doesn't return notifications for domain-blocked non-followed user" do
1002 user = insert(:user)
1003 blocked = insert(:user, ap_id: "http://some-domain.com")
1004 {:ok, user} = User.block_domain(user, "some-domain.com")
1006 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1008 assert Notification.for_user(user) == []
1011 test "it returns notifications for domain-blocked but followed user" do
1012 user = insert(:user)
1013 blocked = insert(:user, ap_id: "http://some-domain.com")
1015 {:ok, user} = User.block_domain(user, "some-domain.com")
1016 {:ok, _} = User.follow(user, blocked)
1018 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1020 assert length(Notification.for_user(user)) == 1
1023 test "it doesn't return notifications for muted thread" do
1024 user = insert(:user)
1025 another_user = insert(:user)
1027 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1029 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1030 assert Notification.for_user(user) == []
1033 test "it returns notifications from a muted user when with_muted is set" do
1034 user = insert(:user)
1035 muted = insert(:user)
1036 {:ok, _user_relationships} = User.mute(user, muted)
1038 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1040 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1043 test "it doesn't return notifications from a blocked user when with_muted is set" do
1044 user = insert(:user)
1045 blocked = insert(:user)
1046 {:ok, _user_relationship} = User.block(user, blocked)
1048 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1050 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1053 test "when with_muted is set, " <>
1054 "it doesn't return notifications from a domain-blocked non-followed user" do
1055 user = insert(:user)
1056 blocked = insert(:user, ap_id: "http://some-domain.com")
1057 {:ok, user} = User.block_domain(user, "some-domain.com")
1059 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1061 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1064 test "it returns notifications from muted threads when with_muted is set" do
1065 user = insert(:user)
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 length(Notification.for_user(user, %{with_muted: true})) == 1