Merge branch 'support/issue_442' into 'develop'
[akkoma] / test / notification_test.exs
1 defmodule Pleroma.NotificationTest do
2 use Pleroma.DataCase
3 alias Pleroma.Web.TwitterAPI.TwitterAPI
4 alias Pleroma.Web.CommonAPI
5 alias Pleroma.{User, Notification}
6 alias Pleroma.Web.ActivityPub.Transmogrifier
7 import Pleroma.Factory
8
9 describe "create_notifications" do
10 test "notifies someone when they are directly addressed" do
11 user = insert(:user)
12 other_user = insert(:user)
13 third_user = insert(:user)
14
15 {:ok, activity} =
16 TwitterAPI.create_status(user, %{
17 "status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"
18 })
19
20 {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
21
22 notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
23 assert notified_ids == [other_user.id, third_user.id]
24 assert notification.activity_id == activity.id
25 assert other_notification.activity_id == activity.id
26 end
27 end
28
29 describe "create_notification" do
30 test "it doesn't create a notification for user if the user blocks the activity author" do
31 activity = insert(:note_activity)
32 author = User.get_by_ap_id(activity.data["actor"])
33 user = insert(:user)
34 {:ok, user} = User.block(user, author)
35
36 assert nil == Notification.create_notification(activity, user)
37 end
38
39 test "it doesn't create a notification for user if he is the activity author" do
40 activity = insert(:note_activity)
41 author = User.get_by_ap_id(activity.data["actor"])
42
43 assert nil == Notification.create_notification(activity, author)
44 end
45 end
46
47 describe "get notification" do
48 test "it gets a notification that belongs to the user" do
49 user = insert(:user)
50 other_user = insert(:user)
51
52 {:ok, activity} =
53 TwitterAPI.create_status(user, %{"status" => "hey @#{other_user.nickname}"})
54
55 {:ok, [notification]} = Notification.create_notifications(activity)
56 {:ok, notification} = Notification.get(other_user, notification.id)
57
58 assert notification.user_id == other_user.id
59 end
60
61 test "it returns error if the notification doesn't belong to the user" do
62 user = insert(:user)
63 other_user = insert(:user)
64
65 {:ok, activity} =
66 TwitterAPI.create_status(user, %{"status" => "hey @#{other_user.nickname}"})
67
68 {:ok, [notification]} = Notification.create_notifications(activity)
69 {:error, _notification} = Notification.get(user, notification.id)
70 end
71 end
72
73 describe "dismiss notification" do
74 test "it dismisses a notification that belongs to the user" do
75 user = insert(:user)
76 other_user = insert(:user)
77
78 {:ok, activity} =
79 TwitterAPI.create_status(user, %{"status" => "hey @#{other_user.nickname}"})
80
81 {:ok, [notification]} = Notification.create_notifications(activity)
82 {:ok, notification} = Notification.dismiss(other_user, notification.id)
83
84 assert notification.user_id == other_user.id
85 end
86
87 test "it returns error if the notification doesn't belong to the user" do
88 user = insert(:user)
89 other_user = insert(:user)
90
91 {:ok, activity} =
92 TwitterAPI.create_status(user, %{"status" => "hey @#{other_user.nickname}"})
93
94 {:ok, [notification]} = Notification.create_notifications(activity)
95 {:error, _notification} = Notification.dismiss(user, notification.id)
96 end
97 end
98
99 describe "clear notification" do
100 test "it clears all notifications belonging to the user" do
101 user = insert(:user)
102 other_user = insert(:user)
103 third_user = insert(:user)
104
105 {:ok, activity} =
106 TwitterAPI.create_status(user, %{
107 "status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
108 })
109
110 {:ok, _notifs} = Notification.create_notifications(activity)
111
112 {:ok, activity} =
113 TwitterAPI.create_status(user, %{
114 "status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
115 })
116
117 {:ok, _notifs} = Notification.create_notifications(activity)
118 Notification.clear(other_user)
119
120 assert Notification.for_user(other_user) == []
121 assert Notification.for_user(third_user) != []
122 end
123 end
124
125 describe "set_read_up_to()" do
126 test "it sets all notifications as read up to a specified notification ID" do
127 user = insert(:user)
128 other_user = insert(:user)
129
130 {:ok, _activity} =
131 TwitterAPI.create_status(user, %{
132 "status" => "hey @#{other_user.nickname}!"
133 })
134
135 {:ok, _activity} =
136 TwitterAPI.create_status(user, %{
137 "status" => "hey again @#{other_user.nickname}!"
138 })
139
140 [n2, n1] = notifs = Notification.for_user(other_user)
141 assert length(notifs) == 2
142
143 assert n2.id > n1.id
144
145 {:ok, _activity} =
146 TwitterAPI.create_status(user, %{
147 "status" => "hey yet again @#{other_user.nickname}!"
148 })
149
150 Notification.set_read_up_to(other_user, n2.id)
151
152 [n3, n2, n1] = Notification.for_user(other_user)
153
154 assert n1.seen == true
155 assert n2.seen == true
156 assert n3.seen == false
157 end
158 end
159
160 describe "notification target determination" do
161 test "it sends notifications to addressed users in new messages" do
162 user = insert(:user)
163 other_user = insert(:user)
164
165 {:ok, activity} =
166 CommonAPI.post(user, %{
167 "status" => "hey @#{other_user.nickname}!"
168 })
169
170 assert other_user in Notification.get_notified_from_activity(activity)
171 end
172
173 test "it sends notifications to mentioned users in new messages" do
174 user = insert(:user)
175 other_user = insert(:user)
176
177 create_activity = %{
178 "@context" => "https://www.w3.org/ns/activitystreams",
179 "type" => "Create",
180 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
181 "actor" => user.ap_id,
182 "object" => %{
183 "type" => "Note",
184 "content" => "message with a Mention tag, but no explicit tagging",
185 "tag" => [
186 %{
187 "type" => "Mention",
188 "href" => other_user.ap_id,
189 "name" => other_user.nickname
190 }
191 ],
192 "attributedTo" => user.ap_id
193 }
194 }
195
196 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
197
198 assert other_user in Notification.get_notified_from_activity(activity)
199 end
200
201 test "it does not send notifications to users who are only cc in new messages" do
202 user = insert(:user)
203 other_user = insert(:user)
204
205 create_activity = %{
206 "@context" => "https://www.w3.org/ns/activitystreams",
207 "type" => "Create",
208 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
209 "cc" => [other_user.ap_id],
210 "actor" => user.ap_id,
211 "object" => %{
212 "type" => "Note",
213 "content" => "hi everyone",
214 "attributedTo" => user.ap_id
215 }
216 }
217
218 {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
219
220 assert other_user not in Notification.get_notified_from_activity(activity)
221 end
222
223 test "it does not send notification to mentioned users in likes" do
224 user = insert(:user)
225 other_user = insert(:user)
226 third_user = insert(:user)
227
228 {:ok, activity_one} =
229 CommonAPI.post(user, %{
230 "status" => "hey @#{other_user.nickname}!"
231 })
232
233 {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
234
235 assert other_user not in Notification.get_notified_from_activity(activity_two)
236 end
237
238 test "it does not send notification to mentioned users in announces" do
239 user = insert(:user)
240 other_user = insert(:user)
241 third_user = insert(:user)
242
243 {:ok, activity_one} =
244 CommonAPI.post(user, %{
245 "status" => "hey @#{other_user.nickname}!"
246 })
247
248 {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
249
250 assert other_user not in Notification.get_notified_from_activity(activity_two)
251 end
252 end
253
254 describe "notification lifecycle" do
255 test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
256 user = insert(:user)
257 other_user = insert(:user)
258
259 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
260
261 assert length(Notification.for_user(user)) == 0
262
263 {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
264
265 assert length(Notification.for_user(user)) == 1
266
267 {:ok, _} = CommonAPI.delete(activity.id, user)
268
269 assert length(Notification.for_user(user)) == 0
270 end
271
272 test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
273 user = insert(:user)
274 other_user = insert(:user)
275
276 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
277
278 assert length(Notification.for_user(user)) == 0
279
280 {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
281
282 assert length(Notification.for_user(user)) == 1
283
284 {:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
285
286 assert length(Notification.for_user(user)) == 0
287 end
288
289 test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
290 user = insert(:user)
291 other_user = insert(:user)
292
293 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
294
295 assert length(Notification.for_user(user)) == 0
296
297 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
298
299 assert length(Notification.for_user(user)) == 1
300
301 {:ok, _} = CommonAPI.delete(activity.id, user)
302
303 assert length(Notification.for_user(user)) == 0
304 end
305
306 test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
307 user = insert(:user)
308 other_user = insert(:user)
309
310 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
311
312 assert length(Notification.for_user(user)) == 0
313
314 {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
315
316 assert length(Notification.for_user(user)) == 1
317
318 {:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
319
320 assert length(Notification.for_user(user)) == 0
321 end
322
323 test "liking an activity which is already deleted does not generate a notification" do
324 user = insert(:user)
325 other_user = insert(:user)
326
327 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
328
329 assert length(Notification.for_user(user)) == 0
330
331 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
332
333 assert length(Notification.for_user(user)) == 0
334
335 {:error, _} = CommonAPI.favorite(activity.id, other_user)
336
337 assert length(Notification.for_user(user)) == 0
338 end
339
340 test "repeating an activity which is already deleted does not generate a notification" do
341 user = insert(:user)
342 other_user = insert(:user)
343
344 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
345
346 assert length(Notification.for_user(user)) == 0
347
348 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
349
350 assert length(Notification.for_user(user)) == 0
351
352 {:error, _} = CommonAPI.repeat(activity.id, other_user)
353
354 assert length(Notification.for_user(user)) == 0
355 end
356
357 test "replying to a deleted post without tagging does not generate a notification" do
358 user = insert(:user)
359 other_user = insert(:user)
360
361 {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
362 {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
363
364 {:ok, _reply_activity} =
365 CommonAPI.post(other_user, %{
366 "status" => "test reply",
367 "in_reply_to_status_id" => activity.id
368 })
369
370 assert length(Notification.for_user(user)) == 0
371 end
372 end
373 end