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, _object} = 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
54 test "it creates a notification for subscribed users" do
56 subscriber = insert(:user)
58 User.subscribe(subscriber, user)
60 {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
61 {:ok, [notification]} = Notification.create_notifications(status)
63 assert notification.user_id == subscriber.id
66 test "does not create a notification for subscribed users if status is a reply" do
68 other_user = insert(:user)
69 subscriber = insert(:user)
71 User.subscribe(subscriber, other_user)
73 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
75 {:ok, _reply_activity} =
76 CommonAPI.post(other_user, %{
77 "status" => "test reply",
78 "in_reply_to_status_id" => activity.id
81 user_notifications = Notification.for_user(user)
82 assert length(user_notifications) == 1
84 subscriber_notifications = Notification.for_user(subscriber)
85 assert Enum.empty?(subscriber_notifications)
89 describe "CommonApi.post/2 notification-related functionality" do
90 test_with_mock "creates but does NOT send notification to blocker user",
95 blocker = insert(:user)
96 {:ok, _user_relationship} = User.block(blocker, user)
98 {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
100 blocker_id = blocker.id
101 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
102 refute called(Push.send(:_))
105 test_with_mock "creates but does NOT send notification to notification-muter user",
110 muter = insert(:user)
111 {:ok, _user_relationships} = User.mute(muter, user)
113 {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
116 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
117 refute called(Push.send(:_))
120 test_with_mock "creates but does NOT send notification to thread-muter user",
125 thread_muter = insert(:user)
127 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
129 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
131 {:ok, _same_context_activity} =
132 CommonAPI.post(user, %{
133 "status" => "hey-hey-hey @#{thread_muter.nickname}!",
134 "in_reply_to_status_id" => activity.id
137 [pre_mute_notification, post_mute_notification] =
138 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
140 pre_mute_notification_id = pre_mute_notification.id
141 post_mute_notification_id = post_mute_notification.id
146 %Notification{id: ^pre_mute_notification_id} -> true
155 %Notification{id: ^post_mute_notification_id} -> true
163 describe "create_notification" do
164 @tag needs_streamer: true
165 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
170 Streamer.add_socket("user", user)
171 assert_receive {:render_with_user, _, _, _}, 4_000
174 task_user_notification =
176 Streamer.add_socket("user:notification", user)
177 assert_receive {:render_with_user, _, _, _}, 4_000
180 activity = insert(:note_activity)
182 notify = Notification.create_notification(activity, user)
183 assert notify.user_id == user.id
185 Task.await(task_user_notification)
188 test "it creates a notification for user if the user blocks the activity author" do
189 activity = insert(:note_activity)
190 author = User.get_cached_by_ap_id(activity.data["actor"])
192 {:ok, _user_relationship} = User.block(user, author)
194 assert Notification.create_notification(activity, user)
197 test "it creates a notification for the user if the user mutes the activity author" do
198 muter = insert(:user)
199 muted = insert(:user)
200 {:ok, _} = User.mute(muter, muted)
201 muter = Repo.get(User, muter.id)
202 {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
204 assert Notification.create_notification(activity, muter)
207 test "notification created if user is muted without notifications" do
208 muter = insert(:user)
209 muted = insert(:user)
211 {:ok, _user_relationships} = User.mute(muter, muted, false)
213 {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
215 assert Notification.create_notification(activity, muter)
218 test "it creates a notification for an activity from a muted thread" do
219 muter = insert(:user)
220 other_user = insert(:user)
221 {:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
222 CommonAPI.add_mute(muter, activity)
225 CommonAPI.post(other_user, %{
226 "status" => "Hi @#{muter.nickname}",
227 "in_reply_to_status_id" => activity.id
230 assert Notification.create_notification(activity, muter)
233 test "it disables notifications from followers" do
234 follower = insert(:user)
237 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
239 User.follow(follower, followed)
240 {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
241 refute Notification.create_notification(activity, followed)
244 test "it disables notifications from non-followers" do
245 follower = insert(:user)
249 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
252 {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
253 refute Notification.create_notification(activity, followed)
256 test "it disables notifications from people the user follows" do
258 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
260 followed = insert(:user)
261 User.follow(follower, followed)
262 follower = Repo.get(User, follower.id)
263 {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
264 refute Notification.create_notification(activity, follower)
267 test "it disables notifications from people the user does not follow" do
269 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
271 followed = insert(:user)
272 {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
273 refute Notification.create_notification(activity, follower)
276 test "it doesn't create a notification for user if he is the activity author" do
277 activity = insert(:note_activity)
278 author = User.get_cached_by_ap_id(activity.data["actor"])
280 refute Notification.create_notification(activity, author)
283 test "it doesn't create duplicate notifications for follow+subscribed users" do
285 subscriber = insert(:user)
287 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
288 User.subscribe(subscriber, user)
289 {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
290 {:ok, [_notif]} = Notification.create_notifications(status)
293 test "it doesn't create subscription notifications if the recipient cannot see the status" do
295 subscriber = insert(:user)
297 User.subscribe(subscriber, user)
299 {:ok, status} = CommonAPI.post(user, %{"status" => "inwisible", "visibility" => "direct"})
301 assert {:ok, []} == Notification.create_notifications(status)
305 describe "follow / follow_request notifications" do
306 test "it creates `follow` notification for approved Follow activity" do
308 followed_user = insert(:user, locked: false)
310 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
311 assert FollowingRelationship.following?(user, followed_user)
312 assert [notification] = Notification.for_user(followed_user)
314 assert %{type: "follow"} =
315 NotificationView.render("show.json", %{
316 notification: notification,
321 test "it creates `follow_request` notification for pending Follow activity" do
323 followed_user = insert(:user, locked: true)
325 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
326 refute FollowingRelationship.following?(user, followed_user)
327 assert [notification] = Notification.for_user(followed_user)
329 render_opts = %{notification: notification, for: followed_user}
330 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
332 # After request is accepted, the same notification is rendered with type "follow":
333 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
335 notification_id = notification.id
336 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
337 assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
340 test "it doesn't create a notification for follow-unfollow-follow chains" 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 CommonAPI.unfollow(user, followed_user)
349 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
351 notification_id = notification.id
352 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
355 test "dismisses the notification on follow request rejection" do
356 user = insert(:user, locked: true)
357 follower = insert(:user)
358 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
359 assert [notification] = Notification.for_user(user)
360 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
361 assert [] = Notification.for_user(user)
365 describe "get notification" do
366 test "it gets a notification that belongs to the user" do
368 other_user = insert(:user)
370 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
372 {:ok, [notification]} = Notification.create_notifications(activity)
373 {:ok, notification} = Notification.get(other_user, notification.id)
375 assert notification.user_id == other_user.id
378 test "it returns error if the notification doesn't belong to the user" do
380 other_user = insert(:user)
382 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
384 {:ok, [notification]} = Notification.create_notifications(activity)
385 {:error, _notification} = Notification.get(user, notification.id)
389 describe "dismiss notification" do
390 test "it dismisses a notification that belongs to the user" do
392 other_user = insert(:user)
394 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
396 {:ok, [notification]} = Notification.create_notifications(activity)
397 {:ok, notification} = Notification.dismiss(other_user, notification.id)
399 assert notification.user_id == other_user.id
402 test "it returns error if the notification doesn't belong to the user" do
404 other_user = insert(:user)
406 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
408 {:ok, [notification]} = Notification.create_notifications(activity)
409 {:error, _notification} = Notification.dismiss(user, notification.id)
413 describe "clear notification" do
414 test "it clears all notifications belonging to the user" do
416 other_user = insert(:user)
417 third_user = insert(:user)
420 CommonAPI.post(user, %{
421 "status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
424 {:ok, _notifs} = Notification.create_notifications(activity)
427 CommonAPI.post(user, %{
428 "status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
431 {:ok, _notifs} = Notification.create_notifications(activity)
432 Notification.clear(other_user)
434 assert Notification.for_user(other_user) == []
435 assert Notification.for_user(third_user) != []
439 describe "set_read_up_to()" do
440 test "it sets all notifications as read up to a specified notification ID" do
442 other_user = insert(:user)
445 CommonAPI.post(user, %{
446 "status" => "hey @#{other_user.nickname}!"
450 CommonAPI.post(user, %{
451 "status" => "hey again @#{other_user.nickname}!"
454 [n2, n1] = notifs = Notification.for_user(other_user)
455 assert length(notifs) == 2
460 CommonAPI.post(user, %{
461 "status" => "hey yet again @#{other_user.nickname}!"
464 Notification.set_read_up_to(other_user, n2.id)
466 [n3, n2, n1] = Notification.for_user(other_user)
468 assert n1.seen == true
469 assert n2.seen == true
470 assert n3.seen == false
474 describe "for_user_since/2" do
475 defp days_ago(days) do
477 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
478 -days * 60 * 60 * 24,
483 test "Returns recent notifications" do
484 user1 = insert(:user)
485 user2 = insert(:user)
487 Enum.each(0..10, fn i ->
489 CommonAPI.post(user1, %{
490 "status" => "hey ##{i} @#{user2.nickname}!"
494 {old, new} = Enum.split(Notification.for_user(user2), 5)
496 Enum.each(old, fn notification ->
498 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
499 |> Pleroma.Repo.update!()
502 recent_notifications_ids =
504 |> Notification.for_user_since(
505 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
509 Enum.each(old, fn %{id: id} ->
510 refute id in recent_notifications_ids
513 Enum.each(new, fn %{id: id} ->
514 assert id in recent_notifications_ids
519 describe "notification target determination / get_notified_from_activity/2" do
520 test "it sends notifications to addressed users in new messages" do
522 other_user = insert(:user)
525 CommonAPI.post(user, %{
526 "status" => "hey @#{other_user.nickname}!"
529 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
531 assert other_user in enabled_receivers
534 test "it sends notifications to mentioned users in new messages" do
536 other_user = insert(:user)
539 "@context" => "https://www.w3.org/ns/activitystreams",
541 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
542 "actor" => user.ap_id,
545 "content" => "message with a Mention tag, but no explicit tagging",
549 "href" => other_user.ap_id,
550 "name" => other_user.nickname
553 "attributedTo" => user.ap_id
557 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
559 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
561 assert other_user in enabled_receivers
564 test "it does not send notifications to users who are only cc in new messages" do
566 other_user = insert(:user)
569 "@context" => "https://www.w3.org/ns/activitystreams",
571 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
572 "cc" => [other_user.ap_id],
573 "actor" => user.ap_id,
576 "content" => "hi everyone",
577 "attributedTo" => user.ap_id
581 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
583 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
585 assert other_user not in enabled_receivers
588 test "it does not send notification to mentioned users in likes" do
590 other_user = insert(:user)
591 third_user = insert(:user)
593 {:ok, activity_one} =
594 CommonAPI.post(user, %{
595 "status" => "hey @#{other_user.nickname}!"
598 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
600 {enabled_receivers, _disabled_receivers} =
601 Notification.get_notified_from_activity(activity_two)
603 assert other_user not in enabled_receivers
606 test "it only notifies the post's author in likes" do
608 other_user = insert(:user)
609 third_user = insert(:user)
611 {:ok, activity_one} =
612 CommonAPI.post(user, %{
613 "status" => "hey @#{other_user.nickname}!"
616 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
620 |> Map.put("to", [other_user.ap_id | like_data["to"]])
621 |> ActivityPub.persist(local: true)
623 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
625 assert other_user not in enabled_receivers
628 test "it does not send notification to mentioned users in announces" do
630 other_user = insert(:user)
631 third_user = insert(:user)
633 {:ok, activity_one} =
634 CommonAPI.post(user, %{
635 "status" => "hey @#{other_user.nickname}!"
638 {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
640 {enabled_receivers, _disabled_receivers} =
641 Notification.get_notified_from_activity(activity_two)
643 assert other_user not in enabled_receivers
646 test "it returns blocking recipient in disabled recipients list" do
648 other_user = insert(:user)
649 {:ok, _user_relationship} = User.block(other_user, user)
651 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
653 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
655 assert [] == enabled_receivers
656 assert [other_user] == disabled_receivers
659 test "it returns notification-muting recipient in disabled recipients list" do
661 other_user = insert(:user)
662 {:ok, _user_relationships} = User.mute(other_user, user)
664 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
666 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
668 assert [] == enabled_receivers
669 assert [other_user] == disabled_receivers
672 test "it returns thread-muting recipient in disabled recipients list" do
674 other_user = insert(:user)
676 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
678 {:ok, _} = CommonAPI.add_mute(other_user, activity)
680 {:ok, same_context_activity} =
681 CommonAPI.post(user, %{
682 "status" => "hey-hey-hey @#{other_user.nickname}!",
683 "in_reply_to_status_id" => activity.id
686 {enabled_receivers, disabled_receivers} =
687 Notification.get_notified_from_activity(same_context_activity)
689 assert [other_user] == disabled_receivers
690 refute other_user in enabled_receivers
693 test "it returns non-following domain-blocking recipient in disabled recipients list" do
694 blocked_domain = "blocked.domain"
695 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
696 other_user = insert(:user)
698 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
700 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
702 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
704 assert [] == enabled_receivers
705 assert [other_user] == disabled_receivers
708 test "it returns following domain-blocking recipient in enabled recipients list" do
709 blocked_domain = "blocked.domain"
710 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
711 other_user = insert(:user)
713 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
714 {:ok, other_user} = User.follow(other_user, user)
716 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
718 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
720 assert [other_user] == enabled_receivers
721 assert [] == disabled_receivers
725 describe "notification lifecycle" do
726 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
728 other_user = insert(:user)
730 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
732 assert Enum.empty?(Notification.for_user(user))
734 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
736 assert length(Notification.for_user(user)) == 1
738 {:ok, _} = CommonAPI.delete(activity.id, user)
740 assert Enum.empty?(Notification.for_user(user))
743 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
745 other_user = insert(:user)
747 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
749 assert Enum.empty?(Notification.for_user(user))
751 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
753 assert length(Notification.for_user(user)) == 1
755 {:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
757 assert Enum.empty?(Notification.for_user(user))
760 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
762 other_user = insert(:user)
764 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
766 assert Enum.empty?(Notification.for_user(user))
768 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
770 assert length(Notification.for_user(user)) == 1
772 {:ok, _} = CommonAPI.delete(activity.id, user)
774 assert Enum.empty?(Notification.for_user(user))
777 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
779 other_user = insert(:user)
781 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
783 assert Enum.empty?(Notification.for_user(user))
785 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
787 assert length(Notification.for_user(user)) == 1
789 {:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
791 assert Enum.empty?(Notification.for_user(user))
794 test "liking an activity which is already deleted does not generate a notification" do
796 other_user = insert(:user)
798 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
800 assert Enum.empty?(Notification.for_user(user))
802 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
804 assert Enum.empty?(Notification.for_user(user))
806 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
808 assert Enum.empty?(Notification.for_user(user))
811 test "repeating an activity which is already deleted does not generate a notification" do
813 other_user = insert(:user)
815 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
817 assert Enum.empty?(Notification.for_user(user))
819 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
821 assert Enum.empty?(Notification.for_user(user))
823 {:error, _} = CommonAPI.repeat(activity.id, other_user)
825 assert Enum.empty?(Notification.for_user(user))
828 test "replying to a deleted post without tagging does not generate a notification" do
830 other_user = insert(:user)
832 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
833 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
835 {:ok, _reply_activity} =
836 CommonAPI.post(other_user, %{
837 "status" => "test reply",
838 "in_reply_to_status_id" => activity.id
841 assert Enum.empty?(Notification.for_user(user))
844 test "notifications are deleted if a local user is deleted" do
846 other_user = insert(:user)
849 CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
851 refute Enum.empty?(Notification.for_user(other_user))
853 {:ok, job} = User.delete(user)
854 ObanHelpers.perform(job)
856 assert Enum.empty?(Notification.for_user(other_user))
859 test "notifications are deleted if a remote user is deleted" do
860 remote_user = insert(:user)
861 local_user = insert(:user)
864 "@context" => "https://www.w3.org/ns/activitystreams",
866 "actor" => remote_user.ap_id,
867 "id" => remote_user.ap_id <> "/activities/test",
868 "to" => [local_user.ap_id],
872 "content" => "Hello!",
876 "href" => local_user.ap_id,
877 "name" => "@#{local_user.nickname}"
880 "to" => [local_user.ap_id],
882 "attributedTo" => remote_user.ap_id
886 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
888 refute Enum.empty?(Notification.for_user(local_user))
890 delete_user_message = %{
891 "@context" => "https://www.w3.org/ns/activitystreams",
892 "id" => remote_user.ap_id <> "/activities/delete",
893 "actor" => remote_user.ap_id,
895 "object" => remote_user.ap_id
898 remote_user_url = remote_user.ap_id
901 %{method: :get, url: ^remote_user_url} ->
902 %Tesla.Env{status: 404, body: ""}
905 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
906 ObanHelpers.perform_all()
908 assert Enum.empty?(Notification.for_user(local_user))
911 @tag capture_log: true
912 test "move activity generates a notification" do
913 %{ap_id: old_ap_id} = old_user = insert(:user)
914 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
915 follower = insert(:user)
916 other_follower = insert(:user, %{allow_following_move: false})
918 User.follow(follower, old_user)
919 User.follow(other_follower, old_user)
921 old_user_url = old_user.ap_id
924 File.read!("test/fixtures/users_mock/localhost.json")
925 |> String.replace("{{nickname}}", old_user.nickname)
929 %{method: :get, url: ^old_user_url} ->
930 %Tesla.Env{status: 200, body: body}
933 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
934 ObanHelpers.perform_all()
939 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
942 ] = Notification.for_user(follower)
947 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
950 ] = Notification.for_user(other_follower)
954 describe "for_user" do
955 test "it returns notifications for muted user without notifications" do
957 muted = insert(:user)
958 {:ok, _user_relationships} = User.mute(user, muted, false)
960 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
962 assert length(Notification.for_user(user)) == 1
965 test "it doesn't return notifications for muted user with notifications" do
967 muted = insert(:user)
968 {:ok, _user_relationships} = User.mute(user, muted)
970 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
972 assert Notification.for_user(user) == []
975 test "it doesn't return notifications for blocked user" do
977 blocked = insert(:user)
978 {:ok, _user_relationship} = User.block(user, blocked)
980 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
982 assert Notification.for_user(user) == []
985 test "it doesn't return notifications for domain-blocked non-followed user" do
987 blocked = insert(:user, ap_id: "http://some-domain.com")
988 {:ok, user} = User.block_domain(user, "some-domain.com")
990 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
992 assert Notification.for_user(user) == []
995 test "it returns notifications for domain-blocked but followed user" do
997 blocked = insert(:user, ap_id: "http://some-domain.com")
999 {:ok, user} = User.block_domain(user, "some-domain.com")
1000 {:ok, _} = User.follow(user, blocked)
1002 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
1004 assert length(Notification.for_user(user)) == 1
1007 test "it doesn't return notifications for muted thread" do
1008 user = insert(:user)
1009 another_user = insert(:user)
1011 {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
1013 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1014 assert Notification.for_user(user) == []
1017 test "it returns notifications from a muted user when with_muted is set" do
1018 user = insert(:user)
1019 muted = insert(:user)
1020 {:ok, _user_relationships} = User.mute(user, muted)
1022 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
1024 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1027 test "it doesn't return notifications from a blocked user when with_muted is set" do
1028 user = insert(:user)
1029 blocked = insert(:user)
1030 {:ok, _user_relationship} = User.block(user, blocked)
1032 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
1034 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1037 test "when with_muted is set, " <>
1038 "it doesn't return notifications from a domain-blocked non-followed user" do
1039 user = insert(:user)
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 Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1048 test "it returns notifications from muted threads when with_muted is set" do
1049 user = insert(:user)
1050 another_user = insert(:user)
1052 {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
1054 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1055 assert length(Notification.for_user(user, %{with_muted: true})) == 1