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 notification = Notification.create_notification(activity, muter)
222 assert notification.id
223 assert notification.seen
226 test "notification created if user is muted without notifications" do
227 muter = insert(:user)
228 muted = insert(:user)
230 {:ok, _user_relationships} = User.mute(muter, muted, false)
232 {:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
234 assert Notification.create_notification(activity, muter)
237 test "it creates a notification for an activity from a muted thread" do
238 muter = insert(:user)
239 other_user = insert(:user)
240 {:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
241 CommonAPI.add_mute(muter, activity)
244 CommonAPI.post(other_user, %{
245 status: "Hi @#{muter.nickname}",
246 in_reply_to_status_id: activity.id
249 assert Notification.create_notification(activity, muter)
252 test "it disables notifications from strangers" do
253 follower = insert(:user)
257 notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
260 {:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
261 refute Notification.create_notification(activity, followed)
264 test "it doesn't create a notification for user if he is the activity author" do
265 activity = insert(:note_activity)
266 author = User.get_cached_by_ap_id(activity.data["actor"])
268 refute Notification.create_notification(activity, author)
271 test "it doesn't create duplicate notifications for follow+subscribed users" do
273 subscriber = insert(:user)
275 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
276 User.subscribe(subscriber, user)
277 {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
278 {:ok, [_notif]} = Notification.create_notifications(status)
281 test "it doesn't create subscription notifications if the recipient cannot see the status" do
283 subscriber = insert(:user)
285 User.subscribe(subscriber, user)
287 {:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
289 assert {:ok, []} == Notification.create_notifications(status)
292 test "it disables notifications from people who are invisible" do
293 author = insert(:user, invisible: true)
296 {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"})
297 refute Notification.create_notification(status, user)
300 test "it doesn't create notifications if content matches with an irreversible filter" do
302 subscriber = insert(:user)
304 User.subscribe(subscriber, user)
305 insert(:filter, user: subscriber, phrase: "cofe", hide: true)
307 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
309 assert {:ok, []} == Notification.create_notifications(status)
312 test "it creates notifications if content matches with a not irreversible filter" do
314 subscriber = insert(:user)
316 User.subscribe(subscriber, user)
317 insert(:filter, user: subscriber, phrase: "cofe", hide: false)
319 {:ok, status} = CommonAPI.post(user, %{status: "got cofe?"})
320 {:ok, [notification]} = Notification.create_notifications(status)
325 test "it creates notifications when someone likes user's status with a filtered word" do
327 other_user = insert(:user)
328 insert(:filter, user: user, phrase: "tesla", hide: true)
330 {:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"})
331 {:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id)
333 {:ok, [notification]} = Notification.create_notifications(activity_two)
339 describe "follow / follow_request notifications" do
340 test "it creates `follow` notification for approved Follow activity" do
342 followed_user = insert(:user, locked: false)
344 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
345 assert FollowingRelationship.following?(user, followed_user)
346 assert [notification] = Notification.for_user(followed_user)
348 assert %{type: "follow"} =
349 NotificationView.render("show.json", %{
350 notification: notification,
355 test "it creates `follow_request` notification for pending Follow activity" do
357 followed_user = insert(:user, locked: true)
359 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
360 refute FollowingRelationship.following?(user, followed_user)
361 assert [notification] = Notification.for_user(followed_user)
363 render_opts = %{notification: notification, for: followed_user}
364 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
366 # After request is accepted, the same notification is rendered with type "follow":
367 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
370 Repo.get(Notification, notification.id)
371 |> Repo.preload(:activity)
373 assert %{type: "follow"} =
374 NotificationView.render("show.json", notification: notification, for: followed_user)
377 test "it doesn't create a notification for follow-unfollow-follow chains" do
379 followed_user = insert(:user, locked: false)
381 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
382 assert FollowingRelationship.following?(user, followed_user)
383 assert [notification] = Notification.for_user(followed_user)
385 CommonAPI.unfollow(user, followed_user)
386 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
388 notification_id = notification.id
389 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
392 test "dismisses the notification on follow request rejection" do
393 user = insert(:user, locked: true)
394 follower = insert(:user)
395 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
396 assert [notification] = Notification.for_user(user)
397 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
398 assert [] = Notification.for_user(user)
402 describe "get notification" do
403 test "it gets a notification that belongs to the user" do
405 other_user = insert(:user)
407 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
409 {:ok, [notification]} = Notification.create_notifications(activity)
410 {:ok, notification} = Notification.get(other_user, notification.id)
412 assert notification.user_id == other_user.id
415 test "it returns error if the notification doesn't belong to the user" do
417 other_user = insert(:user)
419 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
421 {:ok, [notification]} = Notification.create_notifications(activity)
422 {:error, _notification} = Notification.get(user, notification.id)
426 describe "dismiss notification" do
427 test "it dismisses a notification that belongs to the user" do
429 other_user = insert(:user)
431 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
433 {:ok, [notification]} = Notification.create_notifications(activity)
434 {:ok, notification} = Notification.dismiss(other_user, notification.id)
436 assert notification.user_id == other_user.id
439 test "it returns error if the notification doesn't belong to the user" do
441 other_user = insert(:user)
443 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
445 {:ok, [notification]} = Notification.create_notifications(activity)
446 {:error, _notification} = Notification.dismiss(user, notification.id)
450 describe "clear notification" do
451 test "it clears all notifications belonging to the user" do
453 other_user = insert(:user)
454 third_user = insert(:user)
457 CommonAPI.post(user, %{
458 status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
461 {:ok, _notifs} = Notification.create_notifications(activity)
464 CommonAPI.post(user, %{
465 status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
468 {:ok, _notifs} = Notification.create_notifications(activity)
469 Notification.clear(other_user)
471 assert Notification.for_user(other_user) == []
472 assert Notification.for_user(third_user) != []
476 describe "set_read_up_to()" do
477 test "it sets all notifications as read up to a specified notification ID" do
479 other_user = insert(:user)
482 CommonAPI.post(user, %{
483 status: "hey @#{other_user.nickname}!"
487 CommonAPI.post(user, %{
488 status: "hey again @#{other_user.nickname}!"
491 [n2, n1] = Notification.for_user(other_user)
496 CommonAPI.post(user, %{
497 status: "hey yet again @#{other_user.nickname}!"
500 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
502 assert read_notification.activity.object
504 [n3, n2, n1] = Notification.for_user(other_user)
506 assert n1.seen == true
507 assert n2.seen == true
508 assert n3.seen == false
510 assert %Pleroma.Marker{} =
514 user_id: other_user.id,
515 timeline: "notifications"
518 assert m.last_read_id == to_string(n2.id)
522 describe "for_user_since/2" do
523 defp days_ago(days) do
525 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
526 -days * 60 * 60 * 24,
531 test "Returns recent notifications" do
532 user1 = insert(:user)
533 user2 = insert(:user)
535 Enum.each(0..10, fn i ->
537 CommonAPI.post(user1, %{
538 status: "hey ##{i} @#{user2.nickname}!"
542 {old, new} = Enum.split(Notification.for_user(user2), 5)
544 Enum.each(old, fn notification ->
546 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
547 |> Pleroma.Repo.update!()
550 recent_notifications_ids =
552 |> Notification.for_user_since(
553 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
557 Enum.each(old, fn %{id: id} ->
558 refute id in recent_notifications_ids
561 Enum.each(new, fn %{id: id} ->
562 assert id in recent_notifications_ids
567 describe "notification target determination / get_notified_from_activity/2" do
568 test "it sends notifications to addressed users in new messages" do
570 other_user = insert(:user)
573 CommonAPI.post(user, %{
574 status: "hey @#{other_user.nickname}!"
577 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
579 assert other_user in enabled_receivers
582 test "it sends notifications to mentioned users in new messages" do
584 other_user = insert(:user)
587 "@context" => "https://www.w3.org/ns/activitystreams",
589 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
590 "actor" => user.ap_id,
593 "content" => "message with a Mention tag, but no explicit tagging",
597 "href" => other_user.ap_id,
598 "name" => other_user.nickname
601 "attributedTo" => user.ap_id
605 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
607 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
609 assert other_user in enabled_receivers
612 test "it does not send notifications to users who are only cc in new messages" do
614 other_user = insert(:user)
617 "@context" => "https://www.w3.org/ns/activitystreams",
619 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
620 "cc" => [other_user.ap_id],
621 "actor" => user.ap_id,
624 "content" => "hi everyone",
625 "attributedTo" => user.ap_id
629 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
631 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
633 assert other_user not in enabled_receivers
636 test "it does not send notification to mentioned users in likes" do
638 other_user = insert(:user)
639 third_user = insert(:user)
641 {:ok, activity_one} =
642 CommonAPI.post(user, %{
643 status: "hey @#{other_user.nickname}!"
646 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
648 {enabled_receivers, _disabled_receivers} =
649 Notification.get_notified_from_activity(activity_two)
651 assert other_user not in enabled_receivers
654 test "it only notifies the post's author in likes" do
656 other_user = insert(:user)
657 third_user = insert(:user)
659 {:ok, activity_one} =
660 CommonAPI.post(user, %{
661 status: "hey @#{other_user.nickname}!"
664 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
668 |> Map.put("to", [other_user.ap_id | like_data["to"]])
669 |> ActivityPub.persist(local: true)
671 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
673 assert other_user not in enabled_receivers
676 test "it does not send notification to mentioned users in announces" do
678 other_user = insert(:user)
679 third_user = insert(:user)
681 {:ok, activity_one} =
682 CommonAPI.post(user, %{
683 status: "hey @#{other_user.nickname}!"
686 {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
688 {enabled_receivers, _disabled_receivers} =
689 Notification.get_notified_from_activity(activity_two)
691 assert other_user not in enabled_receivers
694 test "it returns blocking recipient in disabled recipients list" do
696 other_user = insert(:user)
697 {:ok, _user_relationship} = User.block(other_user, user)
699 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
701 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
703 assert [] == enabled_receivers
704 assert [other_user] == disabled_receivers
707 test "it returns notification-muting recipient in disabled recipients list" do
709 other_user = insert(:user)
710 {:ok, _user_relationships} = User.mute(other_user, user)
712 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
714 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
716 assert [] == enabled_receivers
717 assert [other_user] == disabled_receivers
720 test "it returns thread-muting recipient in disabled recipients list" do
722 other_user = insert(:user)
724 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
726 {:ok, _} = CommonAPI.add_mute(other_user, activity)
728 {:ok, same_context_activity} =
729 CommonAPI.post(user, %{
730 status: "hey-hey-hey @#{other_user.nickname}!",
731 in_reply_to_status_id: activity.id
734 {enabled_receivers, disabled_receivers} =
735 Notification.get_notified_from_activity(same_context_activity)
737 assert [other_user] == disabled_receivers
738 refute other_user in enabled_receivers
741 test "it returns non-following domain-blocking recipient in disabled recipients list" do
742 blocked_domain = "blocked.domain"
743 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
744 other_user = insert(:user)
746 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
748 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
750 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
752 assert [] == enabled_receivers
753 assert [other_user] == disabled_receivers
756 test "it returns following domain-blocking recipient in enabled recipients list" do
757 blocked_domain = "blocked.domain"
758 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
759 other_user = insert(:user)
761 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
762 {:ok, other_user} = User.follow(other_user, user)
764 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
766 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
768 assert [other_user] == enabled_receivers
769 assert [] == disabled_receivers
773 describe "notification lifecycle" do
774 test "liking 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.favorite(other_user, activity.id)
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 "liking an activity results in 1 notification, then 0 if the activity is unliked" 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.favorite(other_user, activity.id)
801 assert length(Notification.for_user(user)) == 1
803 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
805 assert Enum.empty?(Notification.for_user(user))
808 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" 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, _} = CommonAPI.repeat(activity.id, other_user)
818 assert length(Notification.for_user(user)) == 1
820 {:ok, _} = CommonAPI.delete(activity.id, user)
822 assert Enum.empty?(Notification.for_user(user))
825 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" 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, _} = CommonAPI.repeat(activity.id, other_user)
835 assert length(Notification.for_user(user)) == 1
837 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
839 assert Enum.empty?(Notification.for_user(user))
842 test "liking an activity which is already deleted does not generate a notification" do
844 other_user = insert(:user)
846 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
848 assert Enum.empty?(Notification.for_user(user))
850 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
852 assert Enum.empty?(Notification.for_user(user))
854 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
856 assert Enum.empty?(Notification.for_user(user))
859 test "repeating an activity which is already deleted does not generate a notification" do
861 other_user = insert(:user)
863 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
865 assert Enum.empty?(Notification.for_user(user))
867 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
869 assert Enum.empty?(Notification.for_user(user))
871 {:error, _} = CommonAPI.repeat(activity.id, other_user)
873 assert Enum.empty?(Notification.for_user(user))
876 test "replying to a deleted post without tagging does not generate a notification" do
878 other_user = insert(:user)
880 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
881 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
883 {:ok, _reply_activity} =
884 CommonAPI.post(other_user, %{
885 status: "test reply",
886 in_reply_to_status_id: activity.id
889 assert Enum.empty?(Notification.for_user(user))
892 test "notifications are deleted if a local user is deleted" do
894 other_user = insert(:user)
897 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
899 refute Enum.empty?(Notification.for_user(other_user))
901 {:ok, job} = User.delete(user)
902 ObanHelpers.perform(job)
904 assert Enum.empty?(Notification.for_user(other_user))
907 test "notifications are deleted if a remote user is deleted" do
908 remote_user = insert(:user)
909 local_user = insert(:user)
912 "@context" => "https://www.w3.org/ns/activitystreams",
914 "actor" => remote_user.ap_id,
915 "id" => remote_user.ap_id <> "/activities/test",
916 "to" => [local_user.ap_id],
920 "content" => "Hello!",
924 "href" => local_user.ap_id,
925 "name" => "@#{local_user.nickname}"
928 "to" => [local_user.ap_id],
930 "attributedTo" => remote_user.ap_id
934 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
936 refute Enum.empty?(Notification.for_user(local_user))
938 delete_user_message = %{
939 "@context" => "https://www.w3.org/ns/activitystreams",
940 "id" => remote_user.ap_id <> "/activities/delete",
941 "actor" => remote_user.ap_id,
943 "object" => remote_user.ap_id
946 remote_user_url = remote_user.ap_id
949 %{method: :get, url: ^remote_user_url} ->
950 %Tesla.Env{status: 404, body: ""}
953 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
954 ObanHelpers.perform_all()
956 assert Enum.empty?(Notification.for_user(local_user))
959 @tag capture_log: true
960 test "move activity generates a notification" do
961 %{ap_id: old_ap_id} = old_user = insert(:user)
962 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
963 follower = insert(:user)
964 other_follower = insert(:user, %{allow_following_move: false})
966 User.follow(follower, old_user)
967 User.follow(other_follower, old_user)
969 old_user_url = old_user.ap_id
972 File.read!("test/fixtures/users_mock/localhost.json")
973 |> String.replace("{{nickname}}", old_user.nickname)
977 %{method: :get, url: ^old_user_url} ->
978 %Tesla.Env{status: 200, body: body}
981 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
982 ObanHelpers.perform_all()
987 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
990 ] = Notification.for_user(follower)
995 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
998 ] = Notification.for_user(other_follower)
1002 describe "for_user" do
1004 user = insert(:user)
1006 {:ok, %{user: user}}
1009 test "it returns notifications for muted user without notifications", %{user: user} do
1010 muted = insert(:user)
1011 {:ok, _user_relationships} = User.mute(user, muted, false)
1013 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1015 [notification] = Notification.for_user(user)
1017 assert notification.activity.object
1018 assert notification.seen
1021 test "it doesn't return notifications for muted user with notifications", %{user: user} do
1022 muted = insert(:user)
1023 {:ok, _user_relationships} = User.mute(user, muted)
1025 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1027 assert Notification.for_user(user) == []
1030 test "it doesn't return notifications for blocked user", %{user: user} do
1031 blocked = insert(:user)
1032 {:ok, _user_relationship} = User.block(user, blocked)
1034 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1036 assert Notification.for_user(user) == []
1039 test "it doesn't return notifications for domain-blocked non-followed user", %{user: user} do
1040 blocked = insert(:user, ap_id: "http://some-domain.com")
1041 {:ok, user} = User.block_domain(user, "some-domain.com")
1043 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1045 assert Notification.for_user(user) == []
1048 test "it returns notifications for domain-blocked but followed user" do
1049 user = insert(:user)
1050 blocked = insert(:user, ap_id: "http://some-domain.com")
1052 {:ok, user} = User.block_domain(user, "some-domain.com")
1053 {:ok, _} = User.follow(user, blocked)
1055 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1057 assert length(Notification.for_user(user)) == 1
1060 test "it doesn't return notifications for muted thread", %{user: user} do
1061 another_user = insert(:user)
1063 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1065 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1066 assert Notification.for_user(user) == []
1069 test "it returns notifications from a muted user when with_muted is set", %{user: user} do
1070 muted = insert(:user)
1071 {:ok, _user_relationships} = User.mute(user, muted)
1073 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1075 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1078 test "it doesn't return notifications from a blocked user when with_muted is set", %{
1081 blocked = insert(:user)
1082 {:ok, _user_relationship} = User.block(user, blocked)
1084 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1086 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1089 test "when with_muted is set, " <>
1090 "it doesn't return notifications from a domain-blocked non-followed user",
1092 blocked = insert(:user, ap_id: "http://some-domain.com")
1093 {:ok, user} = User.block_domain(user, "some-domain.com")
1095 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1097 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1100 test "it returns notifications from muted threads when with_muted is set", %{user: user} do
1101 another_user = insert(:user)
1103 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1105 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1106 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1109 test "it doesn't return notifications about mentions with filtered word", %{user: user} do
1110 insert(:filter, user: user, phrase: "cofe", hide: true)
1111 another_user = insert(:user)
1113 {:ok, _activity} = CommonAPI.post(another_user, %{status: "@#{user.nickname} got cofe?"})
1115 assert Enum.empty?(Notification.for_user(user))
1118 test "it returns notifications about mentions with not hidden filtered word", %{user: user} do
1119 insert(:filter, user: user, phrase: "test", hide: false)
1120 another_user = insert(:user)
1122 {:ok, _} = CommonAPI.post(another_user, %{status: "@#{user.nickname} test"})
1124 assert length(Notification.for_user(user)) == 1
1127 test "it returns notifications about favorites with filtered word", %{user: user} do
1128 insert(:filter, user: user, phrase: "cofe", hide: true)
1129 another_user = insert(:user)
1131 {:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"})
1132 {:ok, _} = CommonAPI.favorite(another_user, activity.id)
1134 assert length(Notification.for_user(user)) == 1