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] = notifs = Notification.for_user(other_user)
458 assert length(notifs) == 2
463 CommonAPI.post(user, %{
464 status: "hey yet again @#{other_user.nickname}!"
467 Notification.set_read_up_to(other_user, n2.id)
469 [n3, n2, n1] = Notification.for_user(other_user)
471 assert n1.seen == true
472 assert n2.seen == true
473 assert n3.seen == false
475 assert %Pleroma.Marker{} =
479 user_id: other_user.id,
480 timeline: "notifications"
483 assert m.last_read_id == to_string(n2.id)
487 describe "for_user_since/2" do
488 defp days_ago(days) do
490 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
491 -days * 60 * 60 * 24,
496 test "Returns recent notifications" do
497 user1 = insert(:user)
498 user2 = insert(:user)
500 Enum.each(0..10, fn i ->
502 CommonAPI.post(user1, %{
503 status: "hey ##{i} @#{user2.nickname}!"
507 {old, new} = Enum.split(Notification.for_user(user2), 5)
509 Enum.each(old, fn notification ->
511 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
512 |> Pleroma.Repo.update!()
515 recent_notifications_ids =
517 |> Notification.for_user_since(
518 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
522 Enum.each(old, fn %{id: id} ->
523 refute id in recent_notifications_ids
526 Enum.each(new, fn %{id: id} ->
527 assert id in recent_notifications_ids
532 describe "notification target determination / get_notified_from_activity/2" do
533 test "it sends notifications to addressed users in new messages" do
535 other_user = insert(:user)
538 CommonAPI.post(user, %{
539 status: "hey @#{other_user.nickname}!"
542 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
544 assert other_user in enabled_receivers
547 test "it sends notifications to mentioned users in new messages" do
549 other_user = insert(:user)
552 "@context" => "https://www.w3.org/ns/activitystreams",
554 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
555 "actor" => user.ap_id,
558 "content" => "message with a Mention tag, but no explicit tagging",
562 "href" => other_user.ap_id,
563 "name" => other_user.nickname
566 "attributedTo" => user.ap_id
570 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
572 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
574 assert other_user in enabled_receivers
577 test "it does not send notifications to users who are only cc in new messages" do
579 other_user = insert(:user)
582 "@context" => "https://www.w3.org/ns/activitystreams",
584 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
585 "cc" => [other_user.ap_id],
586 "actor" => user.ap_id,
589 "content" => "hi everyone",
590 "attributedTo" => user.ap_id
594 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
596 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
598 assert other_user not in enabled_receivers
601 test "it does not send notification to mentioned users in likes" do
603 other_user = insert(:user)
604 third_user = insert(:user)
606 {:ok, activity_one} =
607 CommonAPI.post(user, %{
608 status: "hey @#{other_user.nickname}!"
611 {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
613 {enabled_receivers, _disabled_receivers} =
614 Notification.get_notified_from_activity(activity_two)
616 assert other_user not in enabled_receivers
619 test "it only notifies the post's author in likes" do
621 other_user = insert(:user)
622 third_user = insert(:user)
624 {:ok, activity_one} =
625 CommonAPI.post(user, %{
626 status: "hey @#{other_user.nickname}!"
629 {:ok, like_data, _} = Builder.like(third_user, activity_one.object)
633 |> Map.put("to", [other_user.ap_id | like_data["to"]])
634 |> ActivityPub.persist(local: true)
636 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like)
638 assert other_user not in enabled_receivers
641 test "it does not send notification to mentioned users in announces" do
643 other_user = insert(:user)
644 third_user = insert(:user)
646 {:ok, activity_one} =
647 CommonAPI.post(user, %{
648 status: "hey @#{other_user.nickname}!"
651 {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
653 {enabled_receivers, _disabled_receivers} =
654 Notification.get_notified_from_activity(activity_two)
656 assert other_user not in enabled_receivers
659 test "it returns blocking recipient in disabled recipients list" do
661 other_user = insert(:user)
662 {:ok, _user_relationship} = User.block(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 notification-muting recipient in disabled recipients list" do
674 other_user = insert(:user)
675 {:ok, _user_relationships} = User.mute(other_user, user)
677 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
679 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
681 assert [] == enabled_receivers
682 assert [other_user] == disabled_receivers
685 test "it returns thread-muting recipient in disabled recipients list" do
687 other_user = insert(:user)
689 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
691 {:ok, _} = CommonAPI.add_mute(other_user, activity)
693 {:ok, same_context_activity} =
694 CommonAPI.post(user, %{
695 status: "hey-hey-hey @#{other_user.nickname}!",
696 in_reply_to_status_id: activity.id
699 {enabled_receivers, disabled_receivers} =
700 Notification.get_notified_from_activity(same_context_activity)
702 assert [other_user] == disabled_receivers
703 refute other_user in enabled_receivers
706 test "it returns non-following domain-blocking recipient in disabled recipients list" do
707 blocked_domain = "blocked.domain"
708 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
709 other_user = insert(:user)
711 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
713 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
715 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
717 assert [] == enabled_receivers
718 assert [other_user] == disabled_receivers
721 test "it returns following domain-blocking recipient in enabled recipients list" do
722 blocked_domain = "blocked.domain"
723 user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
724 other_user = insert(:user)
726 {:ok, other_user} = User.block_domain(other_user, blocked_domain)
727 {:ok, other_user} = User.follow(other_user, user)
729 {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
731 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
733 assert [other_user] == enabled_receivers
734 assert [] == disabled_receivers
738 describe "notification lifecycle" do
739 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
741 other_user = insert(:user)
743 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
745 assert Enum.empty?(Notification.for_user(user))
747 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
749 assert length(Notification.for_user(user)) == 1
751 {:ok, _} = CommonAPI.delete(activity.id, user)
753 assert Enum.empty?(Notification.for_user(user))
756 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
758 other_user = insert(:user)
760 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
762 assert Enum.empty?(Notification.for_user(user))
764 {:ok, _} = CommonAPI.favorite(other_user, activity.id)
766 assert length(Notification.for_user(user)) == 1
768 {:ok, _} = CommonAPI.unfavorite(activity.id, other_user)
770 assert Enum.empty?(Notification.for_user(user))
773 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
775 other_user = insert(:user)
777 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
779 assert Enum.empty?(Notification.for_user(user))
781 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
783 assert length(Notification.for_user(user)) == 1
785 {:ok, _} = CommonAPI.delete(activity.id, user)
787 assert Enum.empty?(Notification.for_user(user))
790 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
792 other_user = insert(:user)
794 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
796 assert Enum.empty?(Notification.for_user(user))
798 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
800 assert length(Notification.for_user(user)) == 1
802 {:ok, _} = CommonAPI.unrepeat(activity.id, other_user)
804 assert Enum.empty?(Notification.for_user(user))
807 test "liking an activity which is already deleted does not generate a notification" do
809 other_user = insert(:user)
811 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
813 assert Enum.empty?(Notification.for_user(user))
815 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
817 assert Enum.empty?(Notification.for_user(user))
819 {:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
821 assert Enum.empty?(Notification.for_user(user))
824 test "repeating an activity which is already deleted does not generate a notification" do
826 other_user = insert(:user)
828 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
830 assert Enum.empty?(Notification.for_user(user))
832 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
834 assert Enum.empty?(Notification.for_user(user))
836 {:error, _} = CommonAPI.repeat(activity.id, other_user)
838 assert Enum.empty?(Notification.for_user(user))
841 test "replying to a deleted post without tagging does not generate a notification" do
843 other_user = insert(:user)
845 {:ok, activity} = CommonAPI.post(user, %{status: "test post"})
846 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
848 {:ok, _reply_activity} =
849 CommonAPI.post(other_user, %{
850 status: "test reply",
851 in_reply_to_status_id: activity.id
854 assert Enum.empty?(Notification.for_user(user))
857 test "notifications are deleted if a local user is deleted" do
859 other_user = insert(:user)
862 CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
864 refute Enum.empty?(Notification.for_user(other_user))
866 {:ok, job} = User.delete(user)
867 ObanHelpers.perform(job)
869 assert Enum.empty?(Notification.for_user(other_user))
872 test "notifications are deleted if a remote user is deleted" do
873 remote_user = insert(:user)
874 local_user = insert(:user)
877 "@context" => "https://www.w3.org/ns/activitystreams",
879 "actor" => remote_user.ap_id,
880 "id" => remote_user.ap_id <> "/activities/test",
881 "to" => [local_user.ap_id],
885 "content" => "Hello!",
889 "href" => local_user.ap_id,
890 "name" => "@#{local_user.nickname}"
893 "to" => [local_user.ap_id],
895 "attributedTo" => remote_user.ap_id
899 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
901 refute Enum.empty?(Notification.for_user(local_user))
903 delete_user_message = %{
904 "@context" => "https://www.w3.org/ns/activitystreams",
905 "id" => remote_user.ap_id <> "/activities/delete",
906 "actor" => remote_user.ap_id,
908 "object" => remote_user.ap_id
911 remote_user_url = remote_user.ap_id
914 %{method: :get, url: ^remote_user_url} ->
915 %Tesla.Env{status: 404, body: ""}
918 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
919 ObanHelpers.perform_all()
921 assert Enum.empty?(Notification.for_user(local_user))
924 @tag capture_log: true
925 test "move activity generates a notification" do
926 %{ap_id: old_ap_id} = old_user = insert(:user)
927 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
928 follower = insert(:user)
929 other_follower = insert(:user, %{allow_following_move: false})
931 User.follow(follower, old_user)
932 User.follow(other_follower, old_user)
934 old_user_url = old_user.ap_id
937 File.read!("test/fixtures/users_mock/localhost.json")
938 |> String.replace("{{nickname}}", old_user.nickname)
942 %{method: :get, url: ^old_user_url} ->
943 %Tesla.Env{status: 200, body: body}
946 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
947 ObanHelpers.perform_all()
952 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
955 ] = Notification.for_user(follower)
960 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
963 ] = Notification.for_user(other_follower)
967 describe "for_user" do
968 test "it returns notifications for muted user without notifications" do
970 muted = insert(:user)
971 {:ok, _user_relationships} = User.mute(user, muted, false)
973 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
975 assert length(Notification.for_user(user)) == 1
978 test "it doesn't return notifications for muted user with notifications" do
980 muted = insert(:user)
981 {:ok, _user_relationships} = User.mute(user, muted)
983 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
985 assert Notification.for_user(user) == []
988 test "it doesn't return notifications for blocked user" do
990 blocked = insert(:user)
991 {:ok, _user_relationship} = User.block(user, blocked)
993 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
995 assert Notification.for_user(user) == []
998 test "it doesn't return notifications for domain-blocked non-followed user" do
1000 blocked = insert(:user, ap_id: "http://some-domain.com")
1001 {:ok, user} = User.block_domain(user, "some-domain.com")
1003 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1005 assert Notification.for_user(user) == []
1008 test "it returns notifications for domain-blocked but followed user" do
1009 user = insert(:user)
1010 blocked = insert(:user, ap_id: "http://some-domain.com")
1012 {:ok, user} = User.block_domain(user, "some-domain.com")
1013 {:ok, _} = User.follow(user, blocked)
1015 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1017 assert length(Notification.for_user(user)) == 1
1020 test "it doesn't return notifications for muted thread" do
1021 user = insert(:user)
1022 another_user = insert(:user)
1024 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1026 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1027 assert Notification.for_user(user) == []
1030 test "it returns notifications from a muted user when with_muted is set" do
1031 user = insert(:user)
1032 muted = insert(:user)
1033 {:ok, _user_relationships} = User.mute(user, muted)
1035 {:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
1037 assert length(Notification.for_user(user, %{with_muted: true})) == 1
1040 test "it doesn't return notifications from a blocked user when with_muted is set" do
1041 user = insert(:user)
1042 blocked = insert(:user)
1043 {:ok, _user_relationship} = User.block(user, blocked)
1045 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1047 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1050 test "when with_muted is set, " <>
1051 "it doesn't return notifications from a domain-blocked non-followed user" do
1052 user = insert(:user)
1053 blocked = insert(:user, ap_id: "http://some-domain.com")
1054 {:ok, user} = User.block_domain(user, "some-domain.com")
1056 {:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
1058 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
1061 test "it returns notifications from muted threads when with_muted is set" do
1062 user = insert(:user)
1063 another_user = insert(:user)
1065 {:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
1067 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
1068 assert length(Notification.for_user(user, %{with_muted: true})) == 1