Merge branch 'fix/prefer-url-over-search' into 'develop'
[akkoma] / test / web / mastodon_api / controllers / notification_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
6 use Pleroma.Web.ConnCase
7
8 alias Pleroma.Notification
9 alias Pleroma.Repo
10 alias Pleroma.User
11 alias Pleroma.Web.CommonAPI
12
13 import Pleroma.Factory
14
15 test "list of notifications", %{conn: conn} do
16 user = insert(:user)
17 other_user = insert(:user)
18
19 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
20
21 {:ok, [_notification]} = Notification.create_notifications(activity)
22
23 conn =
24 conn
25 |> assign(:user, user)
26 |> get("/api/v1/notifications")
27
28 expected_response =
29 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
30 user.ap_id
31 }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
32
33 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
34 assert response == expected_response
35 end
36
37 test "getting a single notification", %{conn: conn} do
38 user = insert(:user)
39 other_user = insert(:user)
40
41 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
42
43 {:ok, [notification]} = Notification.create_notifications(activity)
44
45 conn =
46 conn
47 |> assign(:user, user)
48 |> get("/api/v1/notifications/#{notification.id}")
49
50 expected_response =
51 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
52 user.ap_id
53 }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
54
55 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
56 assert response == expected_response
57 end
58
59 test "dismissing a single notification", %{conn: conn} do
60 user = insert(:user)
61 other_user = insert(:user)
62
63 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
64
65 {:ok, [notification]} = Notification.create_notifications(activity)
66
67 conn =
68 conn
69 |> assign(:user, user)
70 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
71
72 assert %{} = json_response(conn, 200)
73 end
74
75 test "clearing all notifications", %{conn: conn} do
76 user = insert(:user)
77 other_user = insert(:user)
78
79 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
80
81 {:ok, [_notification]} = Notification.create_notifications(activity)
82
83 conn =
84 conn
85 |> assign(:user, user)
86 |> post("/api/v1/notifications/clear")
87
88 assert %{} = json_response(conn, 200)
89
90 conn =
91 build_conn()
92 |> assign(:user, user)
93 |> get("/api/v1/notifications")
94
95 assert all = json_response(conn, 200)
96 assert all == []
97 end
98
99 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
100 user = insert(:user)
101 other_user = insert(:user)
102
103 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
104 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
105 {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
106 {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
107
108 notification1_id = get_notification_id_by_activity(activity1)
109 notification2_id = get_notification_id_by_activity(activity2)
110 notification3_id = get_notification_id_by_activity(activity3)
111 notification4_id = get_notification_id_by_activity(activity4)
112
113 conn = assign(conn, :user, user)
114
115 # min_id
116 result =
117 conn
118 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
119 |> json_response(:ok)
120
121 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
122
123 # since_id
124 result =
125 conn
126 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
127 |> json_response(:ok)
128
129 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
130
131 # max_id
132 result =
133 conn
134 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
135 |> json_response(:ok)
136
137 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
138 end
139
140 describe "exclude_visibilities" do
141 test "filters notifications for mentions", %{conn: conn} do
142 user = insert(:user)
143 other_user = insert(:user)
144
145 {:ok, public_activity} =
146 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "public"})
147
148 {:ok, direct_activity} =
149 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
150
151 {:ok, unlisted_activity} =
152 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "unlisted"})
153
154 {:ok, private_activity} =
155 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
156
157 conn = assign(conn, :user, user)
158
159 conn_res =
160 get(conn, "/api/v1/notifications", %{
161 exclude_visibilities: ["public", "unlisted", "private"]
162 })
163
164 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
165 assert id == direct_activity.id
166
167 conn_res =
168 get(conn, "/api/v1/notifications", %{
169 exclude_visibilities: ["public", "unlisted", "direct"]
170 })
171
172 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
173 assert id == private_activity.id
174
175 conn_res =
176 get(conn, "/api/v1/notifications", %{
177 exclude_visibilities: ["public", "private", "direct"]
178 })
179
180 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
181 assert id == unlisted_activity.id
182
183 conn_res =
184 get(conn, "/api/v1/notifications", %{
185 exclude_visibilities: ["unlisted", "private", "direct"]
186 })
187
188 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
189 assert id == public_activity.id
190 end
191
192 test "filters notifications for Like activities", %{conn: conn} do
193 user = insert(:user)
194 other_user = insert(:user)
195
196 {:ok, public_activity} =
197 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
198
199 {:ok, direct_activity} =
200 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
201
202 {:ok, unlisted_activity} =
203 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
204
205 {:ok, private_activity} =
206 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"})
207
208 {:ok, _, _} = CommonAPI.favorite(public_activity.id, user)
209 {:ok, _, _} = CommonAPI.favorite(direct_activity.id, user)
210 {:ok, _, _} = CommonAPI.favorite(unlisted_activity.id, user)
211 {:ok, _, _} = CommonAPI.favorite(private_activity.id, user)
212
213 activity_ids =
214 conn
215 |> assign(:user, other_user)
216 |> get("/api/v1/notifications", %{exclude_visibilities: ["direct"]})
217 |> json_response(200)
218 |> Enum.map(& &1["status"]["id"])
219
220 assert public_activity.id in activity_ids
221 assert unlisted_activity.id in activity_ids
222 assert private_activity.id in activity_ids
223 refute direct_activity.id in activity_ids
224
225 activity_ids =
226 conn
227 |> assign(:user, other_user)
228 |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
229 |> json_response(200)
230 |> Enum.map(& &1["status"]["id"])
231
232 assert public_activity.id in activity_ids
233 refute unlisted_activity.id in activity_ids
234 assert private_activity.id in activity_ids
235 assert direct_activity.id in activity_ids
236
237 activity_ids =
238 conn
239 |> assign(:user, other_user)
240 |> get("/api/v1/notifications", %{exclude_visibilities: ["private"]})
241 |> json_response(200)
242 |> Enum.map(& &1["status"]["id"])
243
244 assert public_activity.id in activity_ids
245 assert unlisted_activity.id in activity_ids
246 refute private_activity.id in activity_ids
247 assert direct_activity.id in activity_ids
248
249 activity_ids =
250 conn
251 |> assign(:user, other_user)
252 |> get("/api/v1/notifications", %{exclude_visibilities: ["public"]})
253 |> json_response(200)
254 |> Enum.map(& &1["status"]["id"])
255
256 refute public_activity.id in activity_ids
257 assert unlisted_activity.id in activity_ids
258 assert private_activity.id in activity_ids
259 assert direct_activity.id in activity_ids
260 end
261
262 test "filters notifications for Announce activities", %{conn: conn} do
263 user = insert(:user)
264 other_user = insert(:user)
265
266 {:ok, public_activity} =
267 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
268
269 {:ok, unlisted_activity} =
270 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
271
272 {:ok, _, _} = CommonAPI.repeat(public_activity.id, user)
273 {:ok, _, _} = CommonAPI.repeat(unlisted_activity.id, user)
274
275 activity_ids =
276 conn
277 |> assign(:user, other_user)
278 |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
279 |> json_response(200)
280 |> Enum.map(& &1["status"]["id"])
281
282 assert public_activity.id in activity_ids
283 refute unlisted_activity.id in activity_ids
284 end
285 end
286
287 test "filters notifications using exclude_types", %{conn: conn} do
288 user = insert(:user)
289 other_user = insert(:user)
290
291 {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
292 {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
293 {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
294 {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
295 {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
296
297 mention_notification_id = get_notification_id_by_activity(mention_activity)
298 favorite_notification_id = get_notification_id_by_activity(favorite_activity)
299 reblog_notification_id = get_notification_id_by_activity(reblog_activity)
300 follow_notification_id = get_notification_id_by_activity(follow_activity)
301
302 conn = assign(conn, :user, user)
303
304 conn_res =
305 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
306
307 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
308
309 conn_res =
310 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
311
312 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
313
314 conn_res =
315 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
316
317 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
318
319 conn_res =
320 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
321
322 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
323 end
324
325 test "destroy multiple", %{conn: conn} do
326 user = insert(:user)
327 other_user = insert(:user)
328
329 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
330 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
331 {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
332 {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
333
334 notification1_id = get_notification_id_by_activity(activity1)
335 notification2_id = get_notification_id_by_activity(activity2)
336 notification3_id = get_notification_id_by_activity(activity3)
337 notification4_id = get_notification_id_by_activity(activity4)
338
339 conn = assign(conn, :user, user)
340
341 result =
342 conn
343 |> get("/api/v1/notifications")
344 |> json_response(:ok)
345
346 assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
347
348 conn2 =
349 conn
350 |> assign(:user, other_user)
351
352 result =
353 conn2
354 |> get("/api/v1/notifications")
355 |> json_response(:ok)
356
357 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
358
359 conn_destroy =
360 conn
361 |> delete("/api/v1/notifications/destroy_multiple", %{
362 "ids" => [notification1_id, notification2_id]
363 })
364
365 assert json_response(conn_destroy, 200) == %{}
366
367 result =
368 conn2
369 |> get("/api/v1/notifications")
370 |> json_response(:ok)
371
372 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
373 end
374
375 test "doesn't see notifications after muting user with notifications", %{conn: conn} do
376 user = insert(:user)
377 user2 = insert(:user)
378
379 {:ok, _, _, _} = CommonAPI.follow(user, user2)
380 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
381
382 conn = assign(conn, :user, user)
383
384 conn = get(conn, "/api/v1/notifications")
385
386 assert length(json_response(conn, 200)) == 1
387
388 {:ok, _user_relationships} = User.mute(user, user2)
389
390 conn = assign(build_conn(), :user, user)
391 conn = get(conn, "/api/v1/notifications")
392
393 assert json_response(conn, 200) == []
394 end
395
396 test "see notifications after muting user without notifications", %{conn: conn} do
397 user = insert(:user)
398 user2 = insert(:user)
399
400 {:ok, _, _, _} = CommonAPI.follow(user, user2)
401 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
402
403 conn = assign(conn, :user, user)
404
405 conn = get(conn, "/api/v1/notifications")
406
407 assert length(json_response(conn, 200)) == 1
408
409 {:ok, _user_relationships} = User.mute(user, user2, false)
410
411 conn = assign(build_conn(), :user, user)
412 conn = get(conn, "/api/v1/notifications")
413
414 assert length(json_response(conn, 200)) == 1
415 end
416
417 test "see notifications after muting user with notifications and with_muted parameter", %{
418 conn: conn
419 } do
420 user = insert(:user)
421 user2 = insert(:user)
422
423 {:ok, _, _, _} = CommonAPI.follow(user, user2)
424 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
425
426 conn = assign(conn, :user, user)
427
428 conn = get(conn, "/api/v1/notifications")
429
430 assert length(json_response(conn, 200)) == 1
431
432 {:ok, _user_relationships} = User.mute(user, user2)
433
434 conn = assign(build_conn(), :user, user)
435 conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
436
437 assert length(json_response(conn, 200)) == 1
438 end
439
440 test "see move notifications with `with_move` parameter", %{
441 conn: conn
442 } do
443 old_user = insert(:user)
444 new_user = insert(:user, also_known_as: [old_user.ap_id])
445 follower = insert(:user)
446
447 User.follow(follower, old_user)
448 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
449 Pleroma.Tests.ObanHelpers.perform_all()
450
451 conn =
452 conn
453 |> assign(:user, follower)
454 |> get("/api/v1/notifications")
455
456 assert json_response(conn, 200) == []
457
458 conn =
459 build_conn()
460 |> assign(:user, follower)
461 |> get("/api/v1/notifications", %{"with_move" => "true"})
462
463 assert length(json_response(conn, 200)) == 1
464 end
465
466 defp get_notification_id_by_activity(%{id: id}) do
467 Notification
468 |> Repo.get_by(activity_id: id)
469 |> Map.get(:id)
470 |> to_string()
471 end
472 end