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 strangers" do
250 follower = insert(:user)
254 notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
257 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
258 refute Notification.create_notification(activity, followed)
261 test "it doesn't create a notification for user if he is the activity author" do
262 activity = insert(:note_activity)
263 author = User.get_cached_by_ap_id(activity.data["actor"])
265 refute Notification.create_notification(activity, author)
268 test "it doesn't create duplicate notifications for follow+subscribed users" do
270 subscriber = insert(:user)
272 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
273 User.subscribe(subscriber, user)
274 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
275 {:ok, [_notif]} = Notification.create_notifications(status)
278 test "it doesn't create subscription notifications if the recipient cannot see the status" do
280 subscriber = insert(:user)
282 User.subscribe(subscriber, user)
284 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
286 assert {:ok, []} == Notification.create_notifications(status)
289 test "it disables notifications from people who are invisible" do
290 author = insert(:user, invisible: true)
293 {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
294 refute Notification.create_notification(status, user)
297 test "it doesn't create notifications if content matches with an irreversible filter" do
299 subscriber = insert(:user)
301 User.subscribe(subscriber, user)
302 insert(:filter, user: subscriber, phrase: "cofe", hide: true)
304 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
306 assert {:ok, []} == Notification.create_notifications(status)
309 test "it creates notifications if content matches with a not irreversible filter" do
311 subscriber = insert(:user)
313 User.subscribe(subscriber, user)
314 insert(:filter, user: subscriber, phrase: "cofe", hide: false)
316 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
317 {:ok, [notification]} = Notification.create_notifications(status)
322 test "it creates notifications when someone likes user's status with a filtered word" do
324 other_user = insert(:user)
325 insert(:filter, user: user, phrase: "tesla", hide: true)
327 {:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"})
328 {:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id)
330 {:ok, [notification]} = Notification.create_notifications(activity_two)
336 describe "follow / follow_request notifications" do
337 test "it creates `follow` notification for approved Follow activity" do
339 followed_user = insert(:user, locked: false)
341 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
342 assert FollowingRelationship.following?(user, followed_user)
343 assert [notification] = Notification.for_user(followed_user)
345 assert %{type: "follow"} =
346 NotificationView.render("show.json", %{
347 notification: notification,
352 test "it creates `follow_request` notification for pending Follow activity" do
354 followed_user = insert(:user, locked: true)
356 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
357 refute FollowingRelationship.following?(user, followed_user)
358 assert [notification] = Notification.for_user(followed_user)
360 render_opts = %{notification: notification, for: followed_user}
361 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
363 # After request is accepted, the same notification is rendered with type "follow":
364 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
367 Repo.get(Notification, notification.id)
368 |> Repo.preload(:activity)
370 assert %{type: "follow"} =
371 NotificationView.render("show.json", notification: notification, for: followed_user)
374 test "it doesn't create a notification for follow-unfollow-follow chains" do
376 followed_user = insert(:user, locked: false)
378 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
379 assert FollowingRelationship.following?(user, followed_user)
380 assert [notification] = Notification.for_user(followed_user)
382 CommonAPI.unfollow(user, followed_user)
383 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
385 notification_id = notification.id
386 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
389 test "dismisses the notification on follow request rejection" do
390 user = insert(:user, locked: true)
391 follower = insert(:user)
392 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
393 assert [notification] = Notification.for_user(user)
394 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
395 assert [] = Notification.for_user(user)
399 describe "get notification" do
400 test "it gets a notification that belongs to the user" do
402 other_user = insert(:user)
404 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
406 {:ok, [notification]} = Notification.create_notifications(activity)
407 {:ok, notification} = Notification.get(other_user, notification.id)
409 assert notification.user_id == other_user.id
412 test "it returns error if the notification doesn't belong to the user" do
414 other_user = insert(:user)
416 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
418 {:ok, [notification]} = Notification.create_notifications(activity)
419 {:error, _notification} = Notification.get(user, notification.id)
423 describe "dismiss notification" do
424 test "it dismisses a notification that belongs to the user" do
426 other_user = insert(:user)
428 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
430 {:ok, [notification]} = Notification.create_notifications(activity)
431 {:ok, notification} = Notification.dismiss(other_user, notification.id)
433 assert notification.user_id == other_user.id
436 test "it returns error if the notification doesn't belong to the user" do
438 other_user = insert(:user)
440 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
442 {:ok, [notification]} = Notification.create_notifications(activity)
443 {:error, _notification} = Notification.dismiss(user, notification.id)
447 describe "clear notification" do
448 test "it clears all notifications belonging to the user" do
450 other_user = insert(:user)
451 third_user = insert(:user)
454 CommonAPI.post(user, %{
455 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
458 {:ok, _notifs} = Notification.create_notifications(activity)
461 CommonAPI.post(user, %{
462 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
465 {:ok, _notifs} = Notification.create_notifications(activity)
466 Notification.clear(other_user)
468 assert Notification.for_user(other_user) == []
469 assert Notification.for_user(third_user) != []
473 describe "set_read_up_to()" do
474 test "it sets all notifications as read up to a specified notification ID" do
476 other_user = insert(:user)
479 CommonAPI.post(user, %{
480 status: "hey @#{other_user.nickname}!"
484 CommonAPI.post(user, %{
485 status: "hey again @#{other_user.nickname}!"
488 [n2, n1] = Notification.for_user(other_user)
493 CommonAPI.post(user, %{
494 status: "hey yet again @#{other_user.nickname}!"
497 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
499 assert read_notification.activity.object
501 [n3, n2, n1] = Notification.for_user(other_user)
503 assert n1.seen == true
504 assert n2.seen == true
505 assert n3.seen == false
507 assert %Pleroma.Marker{} =
511 user_id: other_user.id,
512 timeline: "notifications"
515 assert m.last_read_id == to_string(n2.id)
519 describe "for_user_since/2" do
520 defp days_ago(days) do
522 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
523 -days * 60 * 60 * 24,
528 test "Returns recent notifications" do
529 user1 = insert(:user)
530 user2 = insert(:user)
532 Enum.each(0..10, fn i ->
534 CommonAPI.post(user1, %{
535 status: "hey ##{i} @#{user2.nickname}!"
539 {old, new} = Enum.split(Notification.for_user(user2), 5)
541 Enum.each(old, fn notification ->
543 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
544 |> Pleroma.Repo.update!()
547 recent_notifications_ids =
549 |> Notification.for_user_since(
550 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
554 Enum.each(old, fn %{id: id} ->
555 refute id in recent_notifications_ids
558 Enum.each(new, fn %{id: id} ->
559 assert id in recent_notifications_ids
564 describe "notification target determination / get_notified_from_activity/2" do
565 test "it sends notifications to addressed users in new messages" do
567 other_user = insert(:user)
570 CommonAPI.post(user, %{
571 status: "hey @#{other_user.nickname}!"
574 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
576 assert other_user in enabled_receivers
579 test "it sends notifications to mentioned users in new messages" do
581 other_user = insert(:user)
584 "@context" => "https://www.w3.org/ns/activitystreams",
586 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
587 "actor" => user.ap_id,
590 "content" => "message with a Mention tag, but no explicit tagging",
594 "href" => other_user.ap_id,
595 "name" => other_user.nickname
598 "attributedTo" => user.ap_id
602 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
604 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
606 assert other_user in enabled_receivers
609 test "it does not send notifications to users who are only cc in new messages" do
611 other_user = insert(:user)
614 "@context" => "https://www.w3.org/ns/activitystreams",
616 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
617 "cc" => [other_user.ap_id],
618 "actor" => user.ap_id,
621 "content" => "hi everyone",
622 "attributedTo" => user.ap_id
626 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
628 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
630 assert other_user not in enabled_receivers
633 test "it does not send notification to mentioned users in likes" do
635 other_user = insert(:user)
636 third_user = insert(:user)
638 {:ok, activity_one} =
639 CommonAPI.post(user, %{
640 status: "hey @#{other_user.nickname}!"
643 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
645 {enabled_receivers, _disabled_receivers} =
646 Notification.get_notified_from_activity(activity_two)
648 assert other_user not in enabled_receivers
651 test "it only notifies the post's author in likes" do
653 other_user = insert(:user)
654 third_user = insert(:user)
656 {:ok, activity_one} =
657 CommonAPI.post(user, %{
658 status: "hey @#{other_user.nickname}!"
661 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
665 |> Map.put("to", [other_user.ap_id | like_data["to"]])
666 |> ActivityPub.persist(local: true)
668 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
670 assert other_user not in enabled_receivers
673 test "it does not send notification to mentioned users in announces" do
675 other_user = insert(:user)
676 third_user = insert(:user)
678 {:ok, activity_one} =
679 CommonAPI.post(user, %{
680 status: "hey @#{other_user.nickname}!"
683 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
685 {enabled_receivers, _disabled_receivers} =
686 Notification.get_notified_from_activity(activity_two)
688 assert other_user not in enabled_receivers
691 test "it returns blocking recipient in disabled recipients list" do
693 other_user = insert(:user)
694 {:ok, _user_relationship} = User.block(other_user, user)
696 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
698 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
700 assert [] == enabled_receivers
701 assert [other_user] == disabled_receivers
704 test "it returns notification-muting recipient in disabled recipients list" do
706 other_user = insert(:user)
707 {:ok, _user_relationships} = User.mute(other_user, user)
709 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
711 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
713 assert [] == enabled_receivers
714 assert [other_user] == disabled_receivers
717 test "it returns thread-muting recipient in disabled recipients list" do
719 other_user = insert(:user)
721 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
723 {:ok, _} = CommonAPI.add_mute(other_user, activity)
725 {:ok, same_context_activity} =
726 CommonAPI.post(user, %{
727 status: "hey-hey-hey @#{other_user.nickname}!",
728 in_reply_to_status_id: activity.id
731 {enabled_receivers, disabled_receivers} =
732 Notification.get_notified_from_activity(same_context_activity)
734 assert [other_user] == disabled_receivers
735 refute other_user in enabled_receivers
738 test "it returns non-following domain-blocking recipient in disabled recipients list" do
739 blocked_domain = "blocked.domain"
740 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
741 other_user = insert(:user)
743 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
745 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
747 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
749 assert [] == enabled_receivers
750 assert [other_user] == disabled_receivers
753 test "it returns following domain-blocking recipient in enabled recipients list" do
754 blocked_domain = "blocked.domain"
755 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
756 other_user = insert(:user)
758 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
759 {:ok, other_user} = User.follow(other_user, user)
761 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
763 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
765 assert [other_user] == enabled_receivers
766 assert [] == disabled_receivers
770 describe "notification lifecycle" do
771 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
773 other_user = insert(:user)
775 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
777 assert Enum.empty?(Notification.for_user(user))
779 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
781 assert length(Notification.for_user(user)) == 1
783 {:ok, _} = CommonAPI.delete(activity.id, user)
785 assert Enum.empty?(Notification.for_user(user))
788 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
790 other_user = insert(:user)
792 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
794 assert Enum.empty?(Notification.for_user(user))
796 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
798 assert length(Notification.for_user(user)) == 1
800 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
802 assert Enum.empty?(Notification.for_user(user))
805 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
807 other_user = insert(:user)
809 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
811 assert Enum.empty?(Notification.for_user(user))
813 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
815 assert length(Notification.for_user(user)) == 1
817 {:ok, _} = CommonAPI.delete(activity.id, user)
819 assert Enum.empty?(Notification.for_user(user))
822 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
824 other_user = insert(:user)
826 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
828 assert Enum.empty?(Notification.for_user(user))
830 {:ok, _} = CommonAPI.repeat(activity.id, other_user)
832 assert length(Notification.for_user(user)) == 1
834 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
836 assert Enum.empty?(Notification.for_user(user))
839 test "liking an activity which is already deleted does not generate a notification" do
841 other_user = insert(:user)
843 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
845 assert Enum.empty?(Notification.for_user(user))
847 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
849 assert Enum.empty?(Notification.for_user(user))
851 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
853 assert Enum.empty?(Notification.for_user(user))
856 test "repeating an activity which is already deleted does not generate a notification" do
858 other_user = insert(:user)
860 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
862 assert Enum.empty?(Notification.for_user(user))
864 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
866 assert Enum.empty?(Notification.for_user(user))
868 {:error, _} = CommonAPI.repeat(activity.id, other_user)
870 assert Enum.empty?(Notification.for_user(user))
873 test "replying to a deleted post without tagging does not generate a notification" do
875 other_user = insert(:user)
877 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
878 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
880 {:ok, _reply_activity} =
881 CommonAPI.post(other_user, %{
882 status: "test reply",
883 in_reply_to_status_id: activity.id
886 assert Enum.empty?(Notification.for_user(user))
889 test "notifications are deleted if a local user is deleted" do
891 other_user = insert(:user)
894 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
896 refute Enum.empty?(Notification.for_user(other_user))
898 {:ok, job} = User.delete(user)
899 ObanHelpers.perform(job)
901 assert Enum.empty?(Notification.for_user(other_user))
904 test "notifications are deleted if a remote user is deleted" do
905 remote_user = insert(:user)
906 local_user = insert(:user)
909 "@context" => "https://www.w3.org/ns/activitystreams",
911 "actor" => remote_user.ap_id,
912 "id" => remote_user.ap_id <> "/activities/test",
913 "to" => [local_user.ap_id],
917 "content" => "Hello!",
921 "href" => local_user.ap_id,
922 "name" => "@#{local_user.nickname}"
925 "to" => [local_user.ap_id],
927 "attributedTo" => remote_user.ap_id
931 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
933 refute Enum.empty?(Notification.for_user(local_user))
935 delete_user_message = %{
936 "@context" => "https://www.w3.org/ns/activitystreams",
937 "id" => remote_user.ap_id <> "/activities/delete",
938 "actor" => remote_user.ap_id,
940 "object" => remote_user.ap_id
943 remote_user_url = remote_user.ap_id
946 %{method: :get, url: ^remote_user_url} ->
947 %Tesla.Env{status: 404, body: ""}
950 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
951 ObanHelpers.perform_all()
953 assert Enum.empty?(Notification.for_user(local_user))
956 @tag capture_log: true
957 test "move activity generates a notification" do
958 %{ap_id: old_ap_id} = old_user = insert(:user)
959 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
960 follower = insert(:user)
961 other_follower = insert(:user, %{allow_following_move: false})
963 User.follow(follower, old_user)
964 User.follow(other_follower, old_user)
966 old_user_url = old_user.ap_id
969 File.read!("test/fixtures/users_mock/localhost.json")
970 |> String.replace("{{nickname}}", old_user.nickname)
974 %{method: :get, url: ^old_user_url} ->
975 %Tesla.Env{status: 200, body: body}
978 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
979 ObanHelpers.perform_all()
984 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
987 ] = Notification.for_user(follower)
992 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
995 ] = Notification.for_user(other_follower)
999 describe "for_user" do
1001 user = insert(:user)
1003 {:ok, %{user: user}}
1006 test "it returns notifications for muted user without notifications", %{user: user} do
1007 muted = insert(:user)
1008 {:ok, _user_relationships} = User.mute(user, muted, false)
1010 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1012 [notification] = Notification.for_user(user)
1014 assert notification.activity.object
1017 test "it doesn't return notifications for muted user with notifications", %{user: user} do
1018 muted = insert(:user)
1019 {:ok, _user_relationships} = User.mute(user, muted)
1021 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1023 assert Notification.for_user(user) == []
1026 test "it doesn't return notifications for blocked user", %{user: user} do
1027 blocked = insert(:user)
1028 {:ok, _user_relationship} = User.block(user, blocked)
1030 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1032 assert Notification.for_user(user) == []
1035 test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do
1036 blocked = insert(:user, ap_id: "http://some-domain.com")
1037 {:ok, user} = User.block_domain(user, "some-domain.com")
1039 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1041 assert Notification.for_user(user) == []
1044 test "it returns notifications for domain-blocked but followed user" do
1045 user = insert(:user)
1046 blocked = insert(:user, ap_id: "http://some-domain.com")
1048 {:ok, user} = User.block_domain(user, "some-domain.com")
1049 {:ok, _} = User.follow(user, blocked)
1051 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1053 assert length(Notification.for_user(user)) == 1
1056 test "it doesn't return notifications for muted thread", %{user: user} do
1057 another_user = insert(:user)
1059 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1061 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1062 assert Notification.for_user(user) == []
1065 test "it returns notifications from a muted user when with_muted is set", %{user: user} do
1066 muted = insert(:user)
1067 {:ok, _user_relationships} = User.mute(user, muted)
1069 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1071 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1074 test "it doesn't return notifications from a blocked user when with_muted is set", %{
1077 blocked = insert(:user)
1078 {:ok, _user_relationship} = User.block(user, blocked)
1080 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1082 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1085 test "when with_muted is set, " <>
1086 "it doesn't return notifications from a domain-blocked non-followed user",
1088 blocked = insert(:user, ap_id: "http://some-domain.com")
1089 {:ok, user} = User.block_domain(user, "some-domain.com")
1091 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1093 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1096 test "it returns notifications from muted threads when with_muted is set", %{user: user} do
1097 another_user = insert(:user)
1099 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1101 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1102 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1105 test "it doesn't return notifications about mentions with filtered word", %{user: user} do
1106 insert(:filter, user: user, phrase: "cofe", hide: true)
1107 another_user = insert(:user)
1109 {:ok, _activity} = CommonAPI.post(another_user, %{status: "@#{user.nickname} got cofe?"})
1111 assert Enum.empty?(Notification.for_user(user))
1114 test "it returns notifications about mentions with not hidden filtered word", %{user: user} do
1115 insert(:filter, user: user, phrase: "test", hide: false)
1116 another_user = insert(:user)
1118 {:ok, _} = CommonAPI.post(another_user, %{status: "@#{user.nickname} test"})
1120 assert length(Notification.for_user(user)) == 1
1123 test "it returns notifications about favorites with filtered word", %{user: user} do
1124 insert(:filter, user: user, phrase: "cofe", hide: true)
1125 another_user = insert(:user)
1127 {:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"})
1128 {:ok, _} = CommonAPI.favorite(another_user, activity.id)
1130 assert length(Notification.for_user(user)) == 1