CHANGELOG.md: add 2.0.7 entry
[akkoma] / test / notification_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.NotificationTest do
6 use Pleroma.DataCase
7
8 import Pleroma.Factory
9 import Mock
10
11 alias Pleroma.FollowingRelationship
12 alias Pleroma.Notification
13 alias Pleroma.Tests.ObanHelpers
14 alias Pleroma.User
15 alias Pleroma.Web.ActivityPub.Transmogrifier
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.MastodonAPI.NotificationView
18 alias Pleroma.Web.Push
19 alias Pleroma.Web.Streamer
20
21 describe "create_notifications" do
22 test "creates a notification for an emoji reaction" do
23 user = insert(:user)
24 other_user = insert(:user)
25
26 {:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
27 {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
28
29 {:ok, [notification]} = Notification.create_notifications(activity)
30
31 assert notification.user_id == user.id
32 end
33
34 test "notifies someone when they are directly addressed" do
35 user = insert(:user)
36 other_user = insert(:user)
37 third_user = insert(:user)
38
39 {:ok, activity} =
40 CommonAPI.post(user, %{
41 "status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"
42 })
43
44 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
45
46 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
47 assert notified_ids == [other_user.id, third_user.id]
48 assert notification.activity_id == activity.id
49 assert other_notification.activity_id == activity.id
50 end
51
52 test "it creates a notification for subscribed users" do
53 user = insert(:user)
54 subscriber = insert(:user)
55
56 User.subscribe(subscriber, user)
57
58 {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
59 {:ok, [notification]} = Notification.create_notifications(status)
60
61 assert notification.user_id == subscriber.id
62 end
63
64 test "does not create a notification for subscribed users if status is a reply" do
65 user = insert(:user)
66 other_user = insert(:user)
67 subscriber = insert(:user)
68
69 User.subscribe(subscriber, other_user)
70
71 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
72
73 {:ok, _reply_activity} =
74 CommonAPI.post(other_user, %{
75 "status" => "test reply",
76 "in_reply_to_status_id" => activity.id
77 })
78
79 user_notifications = Notification.for_user(user)
80 assert length(user_notifications) == 1
81
82 subscriber_notifications = Notification.for_user(subscriber)
83 assert Enum.empty?(subscriber_notifications)
84 end
85 end
86
87 describe "CommonApi.post/2 notification-related functionality" do
88 test_with_mock "creates but does NOT send notification to blocker user",
89 Push,
90 [:passthrough],
91 [] do
92 user = insert(:user)
93 blocker = insert(:user)
94 {:ok, _user_relationship} = User.block(blocker, user)
95
96 {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
97
98 blocker_id = blocker.id
99 assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
100 refute called(Push.send(:_))
101 end
102
103 test_with_mock "creates but does NOT send notification to notification-muter user",
104 Push,
105 [:passthrough],
106 [] do
107 user = insert(:user)
108 muter = insert(:user)
109 {:ok, _user_relationships} = User.mute(muter, user)
110
111 {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
112
113 muter_id = muter.id
114 assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
115 refute called(Push.send(:_))
116 end
117
118 test_with_mock "creates but does NOT send notification to thread-muter user",
119 Push,
120 [:passthrough],
121 [] do
122 user = insert(:user)
123 thread_muter = insert(:user)
124
125 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
126
127 {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
128
129 {:ok, _same_context_activity} =
130 CommonAPI.post(user, %{
131 "status" => "hey-hey-hey @#{thread_muter.nickname}!",
132 "in_reply_to_status_id" => activity.id
133 })
134
135 [pre_mute_notification, post_mute_notification] =
136 Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
137
138 pre_mute_notification_id = pre_mute_notification.id
139 post_mute_notification_id = post_mute_notification.id
140
141 assert called(
142 Push.send(
143 :meck.is(fn
144 %Notification{id: ^pre_mute_notification_id} -> true
145 _ -> false
146 end)
147 )
148 )
149
150 refute called(
151 Push.send(
152 :meck.is(fn
153 %Notification{id: ^post_mute_notification_id} -> true
154 _ -> false
155 end)
156 )
157 )
158 end
159 end
160
161 describe "create_notification" do
162 @tag needs_streamer: true
163 test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
164 user = insert(:user)
165 task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
166 task_user_notification = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
167
168 Streamer.get_topic_and_add_socket("user", %{transport_pid: task.pid, assigns: %{user: user}})
169
170 Streamer.get_topic_and_add_socket("user:notification", %{
171 transport_pid: task_user_notification.pid,
172 assigns: %{user: user}
173 })
174
175 activity = insert(:note_activity)
176
177 notify = Notification.create_notification(activity, user)
178 assert notify.user_id == user.id
179 Task.await(task)
180 Task.await(task_user_notification)
181 end
182
183 test "it creates a notification for user if the user blocks the activity author" do
184 activity = insert(:note_activity)
185 author = User.get_cached_by_ap_id(activity.data["actor"])
186 user = insert(:user)
187 {:ok, _user_relationship} = User.block(user, author)
188
189 assert Notification.create_notification(activity, user)
190 end
191
192 test "it creates a notification for the user if the user mutes the activity author" do
193 muter = insert(:user)
194 muted = insert(:user)
195 {:ok, _} = User.mute(muter, muted)
196 muter = Repo.get(User, muter.id)
197 {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
198
199 assert Notification.create_notification(activity, muter)
200 end
201
202 test "notification created if user is muted without notifications" do
203 muter = insert(:user)
204 muted = insert(:user)
205
206 {:ok, _user_relationships} = User.mute(muter, muted, false)
207
208 {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
209
210 assert Notification.create_notification(activity, muter)
211 end
212
213 test "it creates a notification for an activity from a muted thread" do
214 muter = insert(:user)
215 other_user = insert(:user)
216 {:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
217 CommonAPI.add_mute(muter, activity)
218
219 {:ok, activity} =
220 CommonAPI.post(other_user, %{
221 "status" => "Hi @#{muter.nickname}",
222 "in_reply_to_status_id" => activity.id
223 })
224
225 assert Notification.create_notification(activity, muter)
226 end
227
228 test "it disables notifications from followers" do
229 follower = insert(:user)
230
231 followed =
232 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
233
234 User.follow(follower, followed)
235 {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
236 refute Notification.create_notification(activity, followed)
237 end
238
239 test "it disables notifications from non-followers" do
240 follower = insert(:user)
241
242 followed =
243 insert(:user,
244 notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
245 )
246
247 {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
248 refute Notification.create_notification(activity, followed)
249 end
250
251 test "it disables notifications from people the user follows" do
252 follower =
253 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
254
255 followed = insert(:user)
256 User.follow(follower, followed)
257 follower = Repo.get(User, follower.id)
258 {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
259 refute Notification.create_notification(activity, follower)
260 end
261
262 test "it disables notifications from people the user does not follow" do
263 follower =
264 insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
265
266 followed = insert(:user)
267 {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
268 refute Notification.create_notification(activity, follower)
269 end
270
271 test "it doesn't create a notification for user if he is the activity author" do
272 activity = insert(:note_activity)
273 author = User.get_cached_by_ap_id(activity.data["actor"])
274
275 refute Notification.create_notification(activity, author)
276 end
277
278 test "it doesn't create duplicate notifications for follow+subscribed users" do
279 user = insert(:user)
280 subscriber = insert(:user)
281
282 {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
283 User.subscribe(subscriber, user)
284 {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
285 {:ok, [_notif]} = Notification.create_notifications(status)
286 end
287
288 test "it doesn't create subscription notifications if the recipient cannot see the status" do
289 user = insert(:user)
290 subscriber = insert(:user)
291
292 User.subscribe(subscriber, user)
293
294 {:ok, status} = CommonAPI.post(user, %{"status" => "inwisible", "visibility" => "direct"})
295
296 assert {:ok, []} == Notification.create_notifications(status)
297 end
298 end
299
300 describe "follow / follow_request notifications" do
301 test "it creates `follow` notification for approved Follow activity" do
302 user = insert(:user)
303 followed_user = insert(:user, locked: false)
304
305 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
306 assert FollowingRelationship.following?(user, followed_user)
307 assert [notification] = Notification.for_user(followed_user)
308
309 assert %{type: "follow"} =
310 NotificationView.render("show.json", %{
311 notification: notification,
312 for: followed_user
313 })
314 end
315
316 test "it creates `follow_request` notification for pending Follow activity" do
317 user = insert(:user)
318 followed_user = insert(:user, locked: true)
319
320 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
321 refute FollowingRelationship.following?(user, followed_user)
322 assert [notification] = Notification.for_user(followed_user)
323
324 render_opts = %{notification: notification, for: followed_user}
325 assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
326
327 # After request is accepted, the same notification is rendered with type "follow":
328 assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
329
330 notification_id = notification.id
331 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
332 assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
333 end
334
335 test "it doesn't create a notification for follow-unfollow-follow chains" do
336 user = insert(:user)
337 followed_user = insert(:user, locked: false)
338
339 {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
340 assert FollowingRelationship.following?(user, followed_user)
341 assert [notification] = Notification.for_user(followed_user)
342
343 CommonAPI.unfollow(user, followed_user)
344 {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
345
346 notification_id = notification.id
347 assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
348 end
349
350 test "dismisses the notification on follow request rejection" do
351 user = insert(:user, locked: true)
352 follower = insert(:user)
353 {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
354 assert [notification] = Notification.for_user(user)
355 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
356 assert [] = Notification.for_user(user)
357 end
358 end
359
360 describe "get notification" do
361 test "it gets a notification that belongs to the user" do
362 user = insert(:user)
363 other_user = insert(:user)
364
365 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
366
367 {:ok, [notification]} = Notification.create_notifications(activity)
368 {:ok, notification} = Notification.get(other_user, notification.id)
369
370 assert notification.user_id == other_user.id
371 end
372
373 test "it returns error if the notification doesn't belong to the user" do
374 user = insert(:user)
375 other_user = insert(:user)
376
377 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
378
379 {:ok, [notification]} = Notification.create_notifications(activity)
380 {:error, _notification} = Notification.get(user, notification.id)
381 end
382 end
383
384 describe "dismiss notification" do
385 test "it dismisses a notification that belongs to the user" do
386 user = insert(:user)
387 other_user = insert(:user)
388
389 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
390
391 {:ok, [notification]} = Notification.create_notifications(activity)
392 {:ok, notification} = Notification.dismiss(other_user, notification.id)
393
394 assert notification.user_id == other_user.id
395 end
396
397 test "it returns error if the notification doesn't belong to the user" do
398 user = insert(:user)
399 other_user = insert(:user)
400
401 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
402
403 {:ok, [notification]} = Notification.create_notifications(activity)
404 {:error, _notification} = Notification.dismiss(user, notification.id)
405 end
406 end
407
408 describe "clear notification" do
409 test "it clears all notifications belonging to the user" do
410 user = insert(:user)
411 other_user = insert(:user)
412 third_user = insert(:user)
413
414 {:ok, activity} =
415 CommonAPI.post(user, %{
416 "status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
417 })
418
419 {:ok, _notifs} = Notification.create_notifications(activity)
420
421 {:ok, activity} =
422 CommonAPI.post(user, %{
423 "status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
424 })
425
426 {:ok, _notifs} = Notification.create_notifications(activity)
427 Notification.clear(other_user)
428
429 assert Notification.for_user(other_user) == []
430 assert Notification.for_user(third_user) != []
431 end
432 end
433
434 describe "set_read_up_to()" do
435 test "it sets all notifications as read up to a specified notification ID" do
436 user = insert(:user)
437 other_user = insert(:user)
438
439 {:ok, _activity} =
440 CommonAPI.post(user, %{
441 "status" => "hey @#{other_user.nickname}!"
442 })
443
444 {:ok, _activity} =
445 CommonAPI.post(user, %{
446 "status" => "hey again @#{other_user.nickname}!"
447 })
448
449 [n2, n1] = Notification.for_user(other_user)
450
451 assert n2.id > n1.id
452
453 {:ok, _activity} =
454 CommonAPI.post(user, %{
455 "status" => "hey yet again @#{other_user.nickname}!"
456 })
457
458 [_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
459
460 assert read_notification.activity.object
461
462 [n3, n2, n1] = Notification.for_user(other_user)
463
464 assert n1.seen == true
465 assert n2.seen == true
466 assert n3.seen == false
467 end
468 end
469
470 describe "for_user_since/2" do
471 defp days_ago(days) do
472 NaiveDateTime.add(
473 NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
474 -days * 60 * 60 * 24,
475 :second
476 )
477 end
478
479 test "Returns recent notifications" do
480 user1 = insert(:user)
481 user2 = insert(:user)
482
483 Enum.each(0..10, fn i ->
484 {:ok, _activity} =
485 CommonAPI.post(user1, %{
486 "status" => "hey ##{i} @#{user2.nickname}!"
487 })
488 end)
489
490 {old, new} = Enum.split(Notification.for_user(user2), 5)
491
492 Enum.each(old, fn notification ->
493 notification
494 |> cast(%{updated_at: days_ago(10)}, [:updated_at])
495 |> Pleroma.Repo.update!()
496 end)
497
498 recent_notifications_ids =
499 user2
500 |> Notification.for_user_since(
501 NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
502 )
503 |> Enum.map(& &1.id)
504
505 Enum.each(old, fn %{id: id} ->
506 refute id in recent_notifications_ids
507 end)
508
509 Enum.each(new, fn %{id: id} ->
510 assert id in recent_notifications_ids
511 end)
512 end
513 end
514
515 describe "notification target determination / get_notified_from_activity/2" do
516 test "it sends notifications to addressed users in new messages" do
517 user = insert(:user)
518 other_user = insert(:user)
519
520 {:ok, activity} =
521 CommonAPI.post(user, %{
522 "status" => "hey @#{other_user.nickname}!"
523 })
524
525 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
526
527 assert other_user in enabled_receivers
528 end
529
530 test "it sends notifications to mentioned users in new messages" do
531 user = insert(:user)
532 other_user = insert(:user)
533
534 create_activity = %{
535 "@context" => "https://www.w3.org/ns/activitystreams",
536 "type" => "Create",
537 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
538 "actor" => user.ap_id,
539 "object" => %{
540 "type" => "Note",
541 "content" => "message with a Mention tag, but no explicit tagging",
542 "tag" => [
543 %{
544 "type" => "Mention",
545 "href" => other_user.ap_id,
546 "name" => other_user.nickname
547 }
548 ],
549 "attributedTo" => user.ap_id
550 }
551 }
552
553 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
554
555 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
556
557 assert other_user in enabled_receivers
558 end
559
560 test "it does not send notifications to users who are only cc in new messages" do
561 user = insert(:user)
562 other_user = insert(:user)
563
564 create_activity = %{
565 "@context" => "https://www.w3.org/ns/activitystreams",
566 "type" => "Create",
567 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
568 "cc" => [other_user.ap_id],
569 "actor" => user.ap_id,
570 "object" => %{
571 "type" => "Note",
572 "content" => "hi everyone",
573 "attributedTo" => user.ap_id
574 }
575 }
576
577 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
578
579 {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
580
581 assert other_user not in enabled_receivers
582 end
583
584 test "it does not send notification to mentioned users in likes" do
585 user = insert(:user)
586 other_user = insert(:user)
587 third_user = insert(:user)
588
589 {:ok, activity_one} =
590 CommonAPI.post(user, %{
591 "status" => "hey @#{other_user.nickname}!"
592 })
593
594 {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
595
596 {enabled_receivers, _disabled_receivers} =
597 Notification.get_notified_from_activity(activity_two)
598
599 assert other_user not in enabled_receivers
600 end
601
602 test "it does not send notification to mentioned users in announces" do
603 user = insert(:user)
604 other_user = insert(:user)
605 third_user = insert(:user)
606
607 {:ok, activity_one} =
608 CommonAPI.post(user, %{
609 "status" => "hey @#{other_user.nickname}!"
610 })
611
612 {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
613
614 {enabled_receivers, _disabled_receivers} =
615 Notification.get_notified_from_activity(activity_two)
616
617 assert other_user not in enabled_receivers
618 end
619
620 test "it returns blocking recipient in disabled recipients list" do
621 user = insert(:user)
622 other_user = insert(:user)
623 {:ok, _user_relationship} = User.block(other_user, user)
624
625 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
626
627 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
628
629 assert [] == enabled_receivers
630 assert [other_user] == disabled_receivers
631 end
632
633 test "it returns notification-muting recipient in disabled recipients list" do
634 user = insert(:user)
635 other_user = insert(:user)
636 {:ok, _user_relationships} = User.mute(other_user, user)
637
638 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
639
640 {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
641
642 assert [] == enabled_receivers
643 assert [other_user] == disabled_receivers
644 end
645
646 test "it returns thread-muting recipient in disabled recipients list" do
647 user = insert(:user)
648 other_user = insert(:user)
649
650 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
651
652 {:ok, _} = CommonAPI.add_mute(other_user, activity)
653
654 {:ok, same_context_activity} =
655 CommonAPI.post(user, %{
656 "status" => "hey-hey-hey @#{other_user.nickname}!",
657 "in_reply_to_status_id" => activity.id
658 })
659
660 {enabled_receivers, disabled_receivers} =
661 Notification.get_notified_from_activity(same_context_activity)
662
663 assert [other_user] == disabled_receivers
664 refute other_user in enabled_receivers
665 end
666 end
667
668 describe "notification lifecycle" do
669 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
670 user = insert(:user)
671 other_user = insert(:user)
672
673 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
674
675 assert Enum.empty?(Notification.for_user(user))
676
677 {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
678
679 assert length(Notification.for_user(user)) == 1
680
681 {:ok, _} = CommonAPI.delete(activity.id, user)
682
683 assert Enum.empty?(Notification.for_user(user))
684 end
685
686 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
687 user = insert(:user)
688 other_user = insert(:user)
689
690 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
691
692 assert Enum.empty?(Notification.for_user(user))
693
694 {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
695
696 assert length(Notification.for_user(user)) == 1
697
698 {:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
699
700 assert Enum.empty?(Notification.for_user(user))
701 end
702
703 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
704 user = insert(:user)
705 other_user = insert(:user)
706
707 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
708
709 assert Enum.empty?(Notification.for_user(user))
710
711 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
712
713 assert length(Notification.for_user(user)) == 1
714
715 {:ok, _} = CommonAPI.delete(activity.id, user)
716
717 assert Enum.empty?(Notification.for_user(user))
718 end
719
720 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
721 user = insert(:user)
722 other_user = insert(:user)
723
724 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
725
726 assert Enum.empty?(Notification.for_user(user))
727
728 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
729
730 assert length(Notification.for_user(user)) == 1
731
732 {:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
733
734 assert Enum.empty?(Notification.for_user(user))
735 end
736
737 test "liking an activity which is already deleted does not generate a notification" do
738 user = insert(:user)
739 other_user = insert(:user)
740
741 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
742
743 assert Enum.empty?(Notification.for_user(user))
744
745 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
746
747 assert Enum.empty?(Notification.for_user(user))
748
749 {:error, _} = CommonAPI.favorite(activity.id, other_user)
750
751 assert Enum.empty?(Notification.for_user(user))
752 end
753
754 test "repeating an activity which is already deleted does not generate a notification" do
755 user = insert(:user)
756 other_user = insert(:user)
757
758 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
759
760 assert Enum.empty?(Notification.for_user(user))
761
762 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
763
764 assert Enum.empty?(Notification.for_user(user))
765
766 {:error, _} = CommonAPI.repeat(activity.id, other_user)
767
768 assert Enum.empty?(Notification.for_user(user))
769 end
770
771 test "replying to a deleted post without tagging does not generate a notification" do
772 user = insert(:user)
773 other_user = insert(:user)
774
775 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
776 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
777
778 {:ok, _reply_activity} =
779 CommonAPI.post(other_user, %{
780 "status" => "test reply",
781 "in_reply_to_status_id" => activity.id
782 })
783
784 assert Enum.empty?(Notification.for_user(user))
785 end
786
787 test "notifications are deleted if a local user is deleted" do
788 user = insert(:user)
789 other_user = insert(:user)
790
791 {:ok, _activity} =
792 CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
793
794 refute Enum.empty?(Notification.for_user(other_user))
795
796 {:ok, job} = User.delete(user)
797 ObanHelpers.perform(job)
798
799 assert Enum.empty?(Notification.for_user(other_user))
800 end
801
802 test "notifications are deleted if a remote user is deleted" do
803 remote_user = insert(:user)
804 local_user = insert(:user)
805
806 dm_message = %{
807 "@context" => "https://www.w3.org/ns/activitystreams",
808 "type" => "Create",
809 "actor" => remote_user.ap_id,
810 "id" => remote_user.ap_id <> "/activities/test",
811 "to" => [local_user.ap_id],
812 "cc" => [],
813 "object" => %{
814 "type" => "Note",
815 "content" => "Hello!",
816 "tag" => [
817 %{
818 "type" => "Mention",
819 "href" => local_user.ap_id,
820 "name" => "@#{local_user.nickname}"
821 }
822 ],
823 "to" => [local_user.ap_id],
824 "cc" => [],
825 "attributedTo" => remote_user.ap_id
826 }
827 }
828
829 {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
830
831 refute Enum.empty?(Notification.for_user(local_user))
832
833 delete_user_message = %{
834 "@context" => "https://www.w3.org/ns/activitystreams",
835 "id" => remote_user.ap_id <> "/activities/delete",
836 "actor" => remote_user.ap_id,
837 "type" => "Delete",
838 "object" => remote_user.ap_id
839 }
840
841 {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
842 ObanHelpers.perform_all()
843
844 assert Enum.empty?(Notification.for_user(local_user))
845 end
846
847 test "move activity generates a notification" do
848 %{ap_id: old_ap_id} = old_user = insert(:user)
849 %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
850 follower = insert(:user)
851 other_follower = insert(:user, %{allow_following_move: false})
852
853 User.follow(follower, old_user)
854 User.follow(other_follower, old_user)
855
856 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
857 ObanHelpers.perform_all()
858
859 assert [] = Notification.for_user(follower)
860
861 assert [
862 %{
863 activity: %{
864 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
865 }
866 }
867 ] = Notification.for_user(follower, %{with_move: true})
868
869 assert [] = Notification.for_user(other_follower)
870
871 assert [
872 %{
873 activity: %{
874 data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
875 }
876 }
877 ] = Notification.for_user(other_follower, %{with_move: true})
878 end
879 end
880
881 describe "for_user" do
882 test "it returns notifications for muted user without notifications" do
883 user = insert(:user)
884 muted = insert(:user)
885 {:ok, _user_relationships} = User.mute(user, muted, false)
886
887 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
888
889 [notification] = Notification.for_user(user)
890
891 assert notification.activity.object
892 end
893
894 test "it doesn't return notifications for muted user with notifications" do
895 user = insert(:user)
896 muted = insert(:user)
897 {:ok, _user_relationships} = User.mute(user, muted)
898
899 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
900
901 assert Notification.for_user(user) == []
902 end
903
904 test "it doesn't return notifications for blocked user" do
905 user = insert(:user)
906 blocked = insert(:user)
907 {:ok, _user_relationship} = User.block(user, blocked)
908
909 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
910
911 assert Notification.for_user(user) == []
912 end
913
914 test "it doesn't return notifications for blocked domain" do
915 user = insert(:user)
916 blocked = insert(:user, ap_id: "http://some-domain.com")
917 {:ok, user} = User.block_domain(user, "some-domain.com")
918
919 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
920
921 assert Notification.for_user(user) == []
922 end
923
924 test "it doesn't return notifications for muted thread" do
925 user = insert(:user)
926 another_user = insert(:user)
927
928 {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
929
930 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
931 assert Notification.for_user(user) == []
932 end
933
934 test "it returns notifications from a muted user when with_muted is set" do
935 user = insert(:user)
936 muted = insert(:user)
937 {:ok, _user_relationships} = User.mute(user, muted)
938
939 {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
940
941 assert length(Notification.for_user(user, %{with_muted: true})) == 1
942 end
943
944 test "it doesn't return notifications from a blocked user when with_muted is set" do
945 user = insert(:user)
946 blocked = insert(:user)
947 {:ok, _user_relationship} = User.block(user, blocked)
948
949 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
950
951 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
952 end
953
954 test "it doesn't return notifications from a domain-blocked user when with_muted is set" do
955 user = insert(:user)
956 blocked = insert(:user, ap_id: "http://some-domain.com")
957 {:ok, user} = User.block_domain(user, "some-domain.com")
958
959 {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
960
961 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
962 end
963
964 test "it returns notifications from muted threads when with_muted is set" do
965 user = insert(:user)
966 another_user = insert(:user)
967
968 {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
969
970 {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
971 assert length(Notification.for_user(user, %{with_muted: true})) == 1
972 end
973 end
974 end