1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
6 use Pleroma.Web.ConnCase
8 alias Pleroma.Notification
11 alias Pleroma.Web.CommonAPI
13 import Pleroma.Factory
15 test "list of notifications", %{conn: conn} do
17 other_user = insert(:user)
19 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
21 {:ok, [_notification]} = Notification.create_notifications(activity)
25 |> assign(:user, user)
26 |> get("/api/v1/notifications")
29 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
31 }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
33 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
34 assert response == expected_response
37 test "getting a single notification", %{conn: conn} do
39 other_user = insert(:user)
41 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
43 {:ok, [notification]} = Notification.create_notifications(activity)
47 |> assign(:user, user)
48 |> get("/api/v1/notifications/#{notification.id}")
51 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
53 }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
55 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
56 assert response == expected_response
59 test "dismissing a single notification", %{conn: conn} do
61 other_user = insert(:user)
63 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
65 {:ok, [notification]} = Notification.create_notifications(activity)
69 |> assign(:user, user)
70 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
72 assert %{} = json_response(conn, 200)
75 test "clearing all notifications", %{conn: conn} do
77 other_user = insert(:user)
79 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
81 {:ok, [_notification]} = Notification.create_notifications(activity)
85 |> assign(:user, user)
86 |> post("/api/v1/notifications/clear")
88 assert %{} = json_response(conn, 200)
92 |> assign(:user, user)
93 |> get("/api/v1/notifications")
95 assert all = json_response(conn, 200)
99 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
101 other_user = insert(:user)
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}"})
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)
113 conn = assign(conn, :user, user)
118 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
119 |> json_response(:ok)
121 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
126 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
127 |> json_response(:ok)
129 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
134 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
135 |> json_response(:ok)
137 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
140 describe "exclude_visibilities" do
141 test "filters notifications for mentions", %{conn: conn} do
143 other_user = insert(:user)
145 {:ok, public_activity} =
146 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "public"})
148 {:ok, direct_activity} =
149 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
151 {:ok, unlisted_activity} =
152 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "unlisted"})
154 {:ok, private_activity} =
155 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
157 conn = assign(conn, :user, user)
160 get(conn, "/api/v1/notifications", %{
161 exclude_visibilities: ["public", "unlisted", "private"]
164 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
165 assert id == direct_activity.id
168 get(conn, "/api/v1/notifications", %{
169 exclude_visibilities: ["public", "unlisted", "direct"]
172 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
173 assert id == private_activity.id
176 get(conn, "/api/v1/notifications", %{
177 exclude_visibilities: ["public", "private", "direct"]
180 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
181 assert id == unlisted_activity.id
184 get(conn, "/api/v1/notifications", %{
185 exclude_visibilities: ["unlisted", "private", "direct"]
188 assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
189 assert id == public_activity.id
192 test "filters notifications for Like activities", %{conn: conn} do
194 other_user = insert(:user)
196 {:ok, public_activity} =
197 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
199 {:ok, direct_activity} =
200 CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
202 {:ok, unlisted_activity} =
203 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
205 {:ok, private_activity} =
206 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"})
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)
215 |> assign(:user, other_user)
216 |> get("/api/v1/notifications", %{exclude_visibilities: ["direct"]})
217 |> json_response(200)
218 |> Enum.map(& &1["status"]["id"])
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
227 |> assign(:user, other_user)
228 |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
229 |> json_response(200)
230 |> Enum.map(& &1["status"]["id"])
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
239 |> assign(:user, other_user)
240 |> get("/api/v1/notifications", %{exclude_visibilities: ["private"]})
241 |> json_response(200)
242 |> Enum.map(& &1["status"]["id"])
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
251 |> assign(:user, other_user)
252 |> get("/api/v1/notifications", %{exclude_visibilities: ["public"]})
253 |> json_response(200)
254 |> Enum.map(& &1["status"]["id"])
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
262 test "filters notifications for Announce activities", %{conn: conn} do
264 other_user = insert(:user)
266 {:ok, public_activity} =
267 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"})
269 {:ok, unlisted_activity} =
270 CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"})
272 {:ok, _, _} = CommonAPI.repeat(public_activity.id, user)
273 {:ok, _, _} = CommonAPI.repeat(unlisted_activity.id, user)
277 |> assign(:user, other_user)
278 |> get("/api/v1/notifications", %{exclude_visibilities: ["unlisted"]})
279 |> json_response(200)
280 |> Enum.map(& &1["status"]["id"])
282 assert public_activity.id in activity_ids
283 refute unlisted_activity.id in activity_ids
287 test "filters notifications using exclude_types", %{conn: conn} do
289 other_user = insert(:user)
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)
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)
302 conn = assign(conn, :user, user)
305 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
307 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
310 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
312 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
315 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
317 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
320 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
322 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
325 test "destroy multiple", %{conn: conn} do
327 other_user = insert(:user)
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}"})
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)
339 conn = assign(conn, :user, user)
343 |> get("/api/v1/notifications")
344 |> json_response(:ok)
346 assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
350 |> assign(:user, other_user)
354 |> get("/api/v1/notifications")
355 |> json_response(:ok)
357 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
361 |> delete("/api/v1/notifications/destroy_multiple", %{
362 "ids" => [notification1_id, notification2_id]
365 assert json_response(conn_destroy, 200) == %{}
369 |> get("/api/v1/notifications")
370 |> json_response(:ok)
372 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
375 test "doesn't see notifications after muting user with notifications", %{conn: conn} do
377 user2 = insert(:user)
379 {:ok, _, _, _} = CommonAPI.follow(user, user2)
380 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
382 conn = assign(conn, :user, user)
384 conn = get(conn, "/api/v1/notifications")
386 assert length(json_response(conn, 200)) == 1
388 {:ok, _user_relationships} = User.mute(user, user2)
390 conn = assign(build_conn(), :user, user)
391 conn = get(conn, "/api/v1/notifications")
393 assert json_response(conn, 200) == []
396 test "see notifications after muting user without notifications", %{conn: conn} do
398 user2 = insert(:user)
400 {:ok, _, _, _} = CommonAPI.follow(user, user2)
401 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
403 conn = assign(conn, :user, user)
405 conn = get(conn, "/api/v1/notifications")
407 assert length(json_response(conn, 200)) == 1
409 {:ok, _user_relationships} = User.mute(user, user2, false)
411 conn = assign(build_conn(), :user, user)
412 conn = get(conn, "/api/v1/notifications")
414 assert length(json_response(conn, 200)) == 1
417 test "see notifications after muting user with notifications and with_muted parameter", %{
421 user2 = insert(:user)
423 {:ok, _, _, _} = CommonAPI.follow(user, user2)
424 {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"})
426 conn = assign(conn, :user, user)
428 conn = get(conn, "/api/v1/notifications")
430 assert length(json_response(conn, 200)) == 1
432 {:ok, _user_relationships} = User.mute(user, user2)
434 conn = assign(build_conn(), :user, user)
435 conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"})
437 assert length(json_response(conn, 200)) == 1
440 test "see move notifications with `with_move` parameter", %{
443 old_user = insert(:user)
444 new_user = insert(:user, also_known_as: [old_user.ap_id])
445 follower = insert(:user)
447 User.follow(follower, old_user)
448 Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
449 Pleroma.Tests.ObanHelpers.perform_all()
453 |> assign(:user, follower)
454 |> get("/api/v1/notifications")
456 assert json_response(conn, 200) == []
460 |> assign(:user, follower)
461 |> get("/api/v1/notifications", %{"with_move" => "true"})
463 assert length(json_response(conn, 200)) == 1
466 defp get_notification_id_by_activity(%{id: id}) do
468 |> Repo.get_by(activity_id: id)