Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

915 lines
29KB

  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. defmodule Pleroma.NotificationTest do
  5. use Pleroma.DataCase
  6. import Pleroma.Factory
  7. import Mock
  8. alias Pleroma.Notification
  9. alias Pleroma.Tests.ObanHelpers
  10. alias Pleroma.User
  11. alias Pleroma.Web.ActivityPub.Transmogrifier
  12. alias Pleroma.Web.CommonAPI
  13. alias Pleroma.Web.Push
  14. alias Pleroma.Web.Streamer
  15. describe "create_notifications" do
  16. test "creates a notification for an emoji reaction" do
  17. user = insert(:user)
  18. other_user = insert(:user)
  19. {:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
  20. {:ok, activity, _object} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
  21. {:ok, [notification]} = Notification.create_notifications(activity)
  22. assert notification.user_id == user.id
  23. end
  24. test "notifies someone when they are directly addressed" do
  25. user = insert(:user)
  26. other_user = insert(:user)
  27. third_user = insert(:user)
  28. {:ok, activity} =
  29. CommonAPI.post(user, %{
  30. "status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"
  31. })
  32. {:ok, [notification, other_notification]} = Notification.create_notifications(activity)
  33. notified_ids = Enum.sort([notification.user_id, other_notification.user_id])
  34. assert notified_ids == [other_user.id, third_user.id]
  35. assert notification.activity_id == activity.id
  36. assert other_notification.activity_id == activity.id
  37. end
  38. test "it creates a notification for subscribed users" do
  39. user = insert(:user)
  40. subscriber = insert(:user)
  41. User.subscribe(subscriber, user)
  42. {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
  43. {:ok, [notification]} = Notification.create_notifications(status)
  44. assert notification.user_id == subscriber.id
  45. end
  46. test "does not create a notification for subscribed users if status is a reply" do
  47. user = insert(:user)
  48. other_user = insert(:user)
  49. subscriber = insert(:user)
  50. User.subscribe(subscriber, other_user)
  51. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  52. {:ok, _reply_activity} =
  53. CommonAPI.post(other_user, %{
  54. "status" => "test reply",
  55. "in_reply_to_status_id" => activity.id
  56. })
  57. user_notifications = Notification.for_user(user)
  58. assert length(user_notifications) == 1
  59. subscriber_notifications = Notification.for_user(subscriber)
  60. assert Enum.empty?(subscriber_notifications)
  61. end
  62. end
  63. describe "CommonApi.post/2 notification-related functionality" do
  64. test_with_mock "creates but does NOT send notification to blocker user",
  65. Push,
  66. [:passthrough],
  67. [] do
  68. user = insert(:user)
  69. blocker = insert(:user)
  70. {:ok, _user_relationship} = User.block(blocker, user)
  71. {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
  72. blocker_id = blocker.id
  73. assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
  74. refute called(Push.send(:_))
  75. end
  76. test_with_mock "creates but does NOT send notification to notification-muter user",
  77. Push,
  78. [:passthrough],
  79. [] do
  80. user = insert(:user)
  81. muter = insert(:user)
  82. {:ok, _user_relationships} = User.mute(muter, user)
  83. {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
  84. muter_id = muter.id
  85. assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
  86. refute called(Push.send(:_))
  87. end
  88. test_with_mock "creates but does NOT send notification to thread-muter user",
  89. Push,
  90. [:passthrough],
  91. [] do
  92. user = insert(:user)
  93. thread_muter = insert(:user)
  94. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
  95. {:ok, _} = CommonAPI.add_mute(thread_muter, activity)
  96. {:ok, _same_context_activity} =
  97. CommonAPI.post(user, %{
  98. "status" => "hey-hey-hey @#{thread_muter.nickname}!",
  99. "in_reply_to_status_id" => activity.id
  100. })
  101. [pre_mute_notification, post_mute_notification] =
  102. Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id))
  103. pre_mute_notification_id = pre_mute_notification.id
  104. post_mute_notification_id = post_mute_notification.id
  105. assert called(
  106. Push.send(
  107. :meck.is(fn
  108. %Notification{id: ^pre_mute_notification_id} -> true
  109. _ -> false
  110. end)
  111. )
  112. )
  113. refute called(
  114. Push.send(
  115. :meck.is(fn
  116. %Notification{id: ^post_mute_notification_id} -> true
  117. _ -> false
  118. end)
  119. )
  120. )
  121. end
  122. end
  123. describe "create_notification" do
  124. @tag needs_streamer: true
  125. test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
  126. user = insert(:user)
  127. task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
  128. task_user_notification = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
  129. Streamer.add_socket("user", %{transport_pid: task.pid, assigns: %{user: user}})
  130. Streamer.add_socket(
  131. "user:notification",
  132. %{transport_pid: task_user_notification.pid, assigns: %{user: user}}
  133. )
  134. activity = insert(:note_activity)
  135. notify = Notification.create_notification(activity, user)
  136. assert notify.user_id == user.id
  137. Task.await(task)
  138. Task.await(task_user_notification)
  139. end
  140. test "it creates a notification for user if the user blocks the activity author" do
  141. activity = insert(:note_activity)
  142. author = User.get_cached_by_ap_id(activity.data["actor"])
  143. user = insert(:user)
  144. {:ok, _user_relationship} = User.block(user, author)
  145. assert Notification.create_notification(activity, user)
  146. end
  147. test "it creates a notification for the user if the user mutes the activity author" do
  148. muter = insert(:user)
  149. muted = insert(:user)
  150. {:ok, _} = User.mute(muter, muted)
  151. muter = Repo.get(User, muter.id)
  152. {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
  153. assert Notification.create_notification(activity, muter)
  154. end
  155. test "notification created if user is muted without notifications" do
  156. muter = insert(:user)
  157. muted = insert(:user)
  158. {:ok, _user_relationships} = User.mute(muter, muted, false)
  159. {:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
  160. assert Notification.create_notification(activity, muter)
  161. end
  162. test "it creates a notification for an activity from a muted thread" do
  163. muter = insert(:user)
  164. other_user = insert(:user)
  165. {:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
  166. CommonAPI.add_mute(muter, activity)
  167. {:ok, activity} =
  168. CommonAPI.post(other_user, %{
  169. "status" => "Hi @#{muter.nickname}",
  170. "in_reply_to_status_id" => activity.id
  171. })
  172. assert Notification.create_notification(activity, muter)
  173. end
  174. test "it disables notifications from followers" do
  175. follower = insert(:user)
  176. followed =
  177. insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
  178. User.follow(follower, followed)
  179. {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
  180. refute Notification.create_notification(activity, followed)
  181. end
  182. test "it disables notifications from non-followers" do
  183. follower = insert(:user)
  184. followed =
  185. insert(:user,
  186. notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
  187. )
  188. {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
  189. refute Notification.create_notification(activity, followed)
  190. end
  191. test "it disables notifications from people the user follows" do
  192. follower =
  193. insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
  194. followed = insert(:user)
  195. User.follow(follower, followed)
  196. follower = Repo.get(User, follower.id)
  197. {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
  198. refute Notification.create_notification(activity, follower)
  199. end
  200. test "it disables notifications from people the user does not follow" do
  201. follower =
  202. insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
  203. followed = insert(:user)
  204. {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
  205. refute Notification.create_notification(activity, follower)
  206. end
  207. test "it doesn't create a notification for user if he is the activity author" do
  208. activity = insert(:note_activity)
  209. author = User.get_cached_by_ap_id(activity.data["actor"])
  210. refute Notification.create_notification(activity, author)
  211. end
  212. test "it doesn't create a notification for follow-unfollow-follow chains" do
  213. user = insert(:user)
  214. followed_user = insert(:user)
  215. {:ok, _, _, activity} = CommonAPI.follow(user, followed_user)
  216. Notification.create_notification(activity, followed_user)
  217. CommonAPI.unfollow(user, followed_user)
  218. {:ok, _, _, activity_dupe} = CommonAPI.follow(user, followed_user)
  219. refute Notification.create_notification(activity_dupe, followed_user)
  220. end
  221. test "it doesn't create duplicate notifications for follow+subscribed users" do
  222. user = insert(:user)
  223. subscriber = insert(:user)
  224. {:ok, _, _, _} = CommonAPI.follow(subscriber, user)
  225. User.subscribe(subscriber, user)
  226. {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
  227. {:ok, [_notif]} = Notification.create_notifications(status)
  228. end
  229. test "it doesn't create subscription notifications if the recipient cannot see the status" do
  230. user = insert(:user)
  231. subscriber = insert(:user)
  232. User.subscribe(subscriber, user)
  233. {:ok, status} = CommonAPI.post(user, %{"status" => "inwisible", "visibility" => "direct"})
  234. assert {:ok, []} == Notification.create_notifications(status)
  235. end
  236. end
  237. describe "get notification" do
  238. test "it gets a notification that belongs to the user" do
  239. user = insert(:user)
  240. other_user = insert(:user)
  241. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
  242. {:ok, [notification]} = Notification.create_notifications(activity)
  243. {:ok, notification} = Notification.get(other_user, notification.id)
  244. assert notification.user_id == other_user.id
  245. end
  246. test "it returns error if the notification doesn't belong to the user" do
  247. user = insert(:user)
  248. other_user = insert(:user)
  249. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
  250. {:ok, [notification]} = Notification.create_notifications(activity)
  251. {:error, _notification} = Notification.get(user, notification.id)
  252. end
  253. end
  254. describe "dismiss notification" do
  255. test "it dismisses a notification that belongs to the user" do
  256. user = insert(:user)
  257. other_user = insert(:user)
  258. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
  259. {:ok, [notification]} = Notification.create_notifications(activity)
  260. {:ok, notification} = Notification.dismiss(other_user, notification.id)
  261. assert notification.user_id == other_user.id
  262. end
  263. test "it returns error if the notification doesn't belong to the user" do
  264. user = insert(:user)
  265. other_user = insert(:user)
  266. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
  267. {:ok, [notification]} = Notification.create_notifications(activity)
  268. {:error, _notification} = Notification.dismiss(user, notification.id)
  269. end
  270. end
  271. describe "clear notification" do
  272. test "it clears all notifications belonging to the user" do
  273. user = insert(:user)
  274. other_user = insert(:user)
  275. third_user = insert(:user)
  276. {:ok, activity} =
  277. CommonAPI.post(user, %{
  278. "status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
  279. })
  280. {:ok, _notifs} = Notification.create_notifications(activity)
  281. {:ok, activity} =
  282. CommonAPI.post(user, %{
  283. "status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
  284. })
  285. {:ok, _notifs} = Notification.create_notifications(activity)
  286. Notification.clear(other_user)
  287. assert Notification.for_user(other_user) == []
  288. assert Notification.for_user(third_user) != []
  289. end
  290. end
  291. describe "set_read_up_to()" do
  292. test "it sets all notifications as read up to a specified notification ID" do
  293. user = insert(:user)
  294. other_user = insert(:user)
  295. {:ok, _activity} =
  296. CommonAPI.post(user, %{
  297. "status" => "hey @#{other_user.nickname}!"
  298. })
  299. {:ok, _activity} =
  300. CommonAPI.post(user, %{
  301. "status" => "hey again @#{other_user.nickname}!"
  302. })
  303. [n2, n1] = notifs = Notification.for_user(other_user)
  304. assert length(notifs) == 2
  305. assert n2.id > n1.id
  306. {:ok, _activity} =
  307. CommonAPI.post(user, %{
  308. "status" => "hey yet again @#{other_user.nickname}!"
  309. })
  310. Notification.set_read_up_to(other_user, n2.id)
  311. [n3, n2, n1] = Notification.for_user(other_user)
  312. assert n1.seen == true
  313. assert n2.seen == true
  314. assert n3.seen == false
  315. end
  316. end
  317. describe "for_user_since/2" do
  318. defp days_ago(days) do
  319. NaiveDateTime.add(
  320. NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
  321. -days * 60 * 60 * 24,
  322. :second
  323. )
  324. end
  325. test "Returns recent notifications" do
  326. user1 = insert(:user)
  327. user2 = insert(:user)
  328. Enum.each(0..10, fn i ->
  329. {:ok, _activity} =
  330. CommonAPI.post(user1, %{
  331. "status" => "hey ##{i} @#{user2.nickname}!"
  332. })
  333. end)
  334. {old, new} = Enum.split(Notification.for_user(user2), 5)
  335. Enum.each(old, fn notification ->
  336. notification
  337. |> cast(%{updated_at: days_ago(10)}, [:updated_at])
  338. |> Pleroma.Repo.update!()
  339. end)
  340. recent_notifications_ids =
  341. user2
  342. |> Notification.for_user_since(
  343. NaiveDateTime.add(NaiveDateTime.utc_now(), -5 * 86_400, :second)
  344. )
  345. |> Enum.map(& &1.id)
  346. Enum.each(old, fn %{id: id} ->
  347. refute id in recent_notifications_ids
  348. end)
  349. Enum.each(new, fn %{id: id} ->
  350. assert id in recent_notifications_ids
  351. end)
  352. end
  353. end
  354. describe "notification target determination / get_notified_from_activity/2" do
  355. test "it sends notifications to addressed users in new messages" do
  356. user = insert(:user)
  357. other_user = insert(:user)
  358. {:ok, activity} =
  359. CommonAPI.post(user, %{
  360. "status" => "hey @#{other_user.nickname}!"
  361. })
  362. {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
  363. assert other_user in enabled_receivers
  364. end
  365. test "it sends notifications to mentioned users in new messages" do
  366. user = insert(:user)
  367. other_user = insert(:user)
  368. create_activity = %{
  369. "@context" => "https://www.w3.org/ns/activitystreams",
  370. "type" => "Create",
  371. "to" => ["https://www.w3.org/ns/activitystreams#Public"],
  372. "actor" => user.ap_id,
  373. "object" => %{
  374. "type" => "Note",
  375. "content" => "message with a Mention tag, but no explicit tagging",
  376. "tag" => [
  377. %{
  378. "type" => "Mention",
  379. "href" => other_user.ap_id,
  380. "name" => other_user.nickname
  381. }
  382. ],
  383. "attributedTo" => user.ap_id
  384. }
  385. }
  386. {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
  387. {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
  388. assert other_user in enabled_receivers
  389. end
  390. test "it does not send notifications to users who are only cc in new messages" do
  391. user = insert(:user)
  392. other_user = insert(:user)
  393. create_activity = %{
  394. "@context" => "https://www.w3.org/ns/activitystreams",
  395. "type" => "Create",
  396. "to" => ["https://www.w3.org/ns/activitystreams#Public"],
  397. "cc" => [other_user.ap_id],
  398. "actor" => user.ap_id,
  399. "object" => %{
  400. "type" => "Note",
  401. "content" => "hi everyone",
  402. "attributedTo" => user.ap_id
  403. }
  404. }
  405. {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
  406. {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
  407. assert other_user not in enabled_receivers
  408. end
  409. test "it does not send notification to mentioned users in likes" do
  410. user = insert(:user)
  411. other_user = insert(:user)
  412. third_user = insert(:user)
  413. {:ok, activity_one} =
  414. CommonAPI.post(user, %{
  415. "status" => "hey @#{other_user.nickname}!"
  416. })
  417. {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
  418. {enabled_receivers, _disabled_receivers} =
  419. Notification.get_notified_from_activity(activity_two)
  420. assert other_user not in enabled_receivers
  421. end
  422. test "it does not send notification to mentioned users in announces" do
  423. user = insert(:user)
  424. other_user = insert(:user)
  425. third_user = insert(:user)
  426. {:ok, activity_one} =
  427. CommonAPI.post(user, %{
  428. "status" => "hey @#{other_user.nickname}!"
  429. })
  430. {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
  431. {enabled_receivers, _disabled_receivers} =
  432. Notification.get_notified_from_activity(activity_two)
  433. assert other_user not in enabled_receivers
  434. end
  435. test "it returns blocking recipient in disabled recipients list" do
  436. user = insert(:user)
  437. other_user = insert(:user)
  438. {:ok, _user_relationship} = User.block(other_user, user)
  439. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
  440. {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
  441. assert [] == enabled_receivers
  442. assert [other_user] == disabled_receivers
  443. end
  444. test "it returns notification-muting recipient in disabled recipients list" do
  445. user = insert(:user)
  446. other_user = insert(:user)
  447. {:ok, _user_relationships} = User.mute(other_user, user)
  448. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
  449. {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
  450. assert [] == enabled_receivers
  451. assert [other_user] == disabled_receivers
  452. end
  453. test "it returns thread-muting recipient in disabled recipients list" do
  454. user = insert(:user)
  455. other_user = insert(:user)
  456. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
  457. {:ok, _} = CommonAPI.add_mute(other_user, activity)
  458. {:ok, same_context_activity} =
  459. CommonAPI.post(user, %{
  460. "status" => "hey-hey-hey @#{other_user.nickname}!",
  461. "in_reply_to_status_id" => activity.id
  462. })
  463. {enabled_receivers, disabled_receivers} =
  464. Notification.get_notified_from_activity(same_context_activity)
  465. assert [other_user] == disabled_receivers
  466. refute other_user in enabled_receivers
  467. end
  468. end
  469. describe "notification lifecycle" do
  470. test "liking an activity results in 1 notification, then 0 if the activity is deleted" do
  471. user = insert(:user)
  472. other_user = insert(:user)
  473. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  474. assert Enum.empty?(Notification.for_user(user))
  475. {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
  476. assert length(Notification.for_user(user)) == 1
  477. {:ok, _} = CommonAPI.delete(activity.id, user)
  478. assert Enum.empty?(Notification.for_user(user))
  479. end
  480. test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
  481. user = insert(:user)
  482. other_user = insert(:user)
  483. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  484. assert Enum.empty?(Notification.for_user(user))
  485. {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
  486. assert length(Notification.for_user(user)) == 1
  487. {:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
  488. assert Enum.empty?(Notification.for_user(user))
  489. end
  490. test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
  491. user = insert(:user)
  492. other_user = insert(:user)
  493. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  494. assert Enum.empty?(Notification.for_user(user))
  495. {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
  496. assert length(Notification.for_user(user)) == 1
  497. {:ok, _} = CommonAPI.delete(activity.id, user)
  498. assert Enum.empty?(Notification.for_user(user))
  499. end
  500. test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
  501. user = insert(:user)
  502. other_user = insert(:user)
  503. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  504. assert Enum.empty?(Notification.for_user(user))
  505. {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
  506. assert length(Notification.for_user(user)) == 1
  507. {:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
  508. assert Enum.empty?(Notification.for_user(user))
  509. end
  510. test "liking an activity which is already deleted does not generate a notification" do
  511. user = insert(:user)
  512. other_user = insert(:user)
  513. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  514. assert Enum.empty?(Notification.for_user(user))
  515. {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
  516. assert Enum.empty?(Notification.for_user(user))
  517. {:error, _} = CommonAPI.favorite(activity.id, other_user)
  518. assert Enum.empty?(Notification.for_user(user))
  519. end
  520. test "repeating an activity which is already deleted does not generate a notification" do
  521. user = insert(:user)
  522. other_user = insert(:user)
  523. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  524. assert Enum.empty?(Notification.for_user(user))
  525. {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
  526. assert Enum.empty?(Notification.for_user(user))
  527. {:error, _} = CommonAPI.repeat(activity.id, other_user)
  528. assert Enum.empty?(Notification.for_user(user))
  529. end
  530. test "replying to a deleted post without tagging does not generate a notification" do
  531. user = insert(:user)
  532. other_user = insert(:user)
  533. {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
  534. {:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
  535. {:ok, _reply_activity} =
  536. CommonAPI.post(other_user, %{
  537. "status" => "test reply",
  538. "in_reply_to_status_id" => activity.id
  539. })
  540. assert Enum.empty?(Notification.for_user(user))
  541. end
  542. test "notifications are deleted if a local user is deleted" do
  543. user = insert(:user)
  544. other_user = insert(:user)
  545. {:ok, _activity} =
  546. CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
  547. refute Enum.empty?(Notification.for_user(other_user))
  548. {:ok, job} = User.delete(user)
  549. ObanHelpers.perform(job)
  550. assert Enum.empty?(Notification.for_user(other_user))
  551. end
  552. test "notifications are deleted if a remote user is deleted" do
  553. remote_user = insert(:user)
  554. local_user = insert(:user)
  555. dm_message = %{
  556. "@context" => "https://www.w3.org/ns/activitystreams",
  557. "type" => "Create",
  558. "actor" => remote_user.ap_id,
  559. "id" => remote_user.ap_id <> "/activities/test",
  560. "to" => [local_user.ap_id],
  561. "cc" => [],
  562. "object" => %{
  563. "type" => "Note",
  564. "content" => "Hello!",
  565. "tag" => [
  566. %{
  567. "type" => "Mention",
  568. "href" => local_user.ap_id,
  569. "name" => "@#{local_user.nickname}"
  570. }
  571. ],
  572. "to" => [local_user.ap_id],
  573. "cc" => [],
  574. "attributedTo" => remote_user.ap_id
  575. }
  576. }
  577. {:ok, _dm_activity} = Transmogrifier.handle_incoming(dm_message)
  578. refute Enum.empty?(Notification.for_user(local_user))
  579. delete_user_message = %{
  580. "@context" => "https://www.w3.org/ns/activitystreams",
  581. "id" => remote_user.ap_id <> "/activities/delete",
  582. "actor" => remote_user.ap_id,
  583. "type" => "Delete",
  584. "object" => remote_user.ap_id
  585. }
  586. {:ok, _delete_activity} = Transmogrifier.handle_incoming(delete_user_message)
  587. ObanHelpers.perform_all()
  588. assert Enum.empty?(Notification.for_user(local_user))
  589. end
  590. test "move activity generates a notification" do
  591. %{ap_id: old_ap_id} = old_user = insert(:user)
  592. %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
  593. follower = insert(:user)
  594. other_follower = insert(:user, %{allow_following_move: false})
  595. User.follow(follower, old_user)
  596. User.follow(other_follower, old_user)
  597. Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
  598. ObanHelpers.perform_all()
  599. assert [
  600. %{
  601. activity: %{
  602. data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
  603. }
  604. }
  605. ] = Notification.for_user(follower)
  606. assert [
  607. %{
  608. activity: %{
  609. data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id}
  610. }
  611. }
  612. ] = Notification.for_user(other_follower)
  613. end
  614. end
  615. describe "for_user" do
  616. test "it returns notifications for muted user without notifications" do
  617. user = insert(:user)
  618. muted = insert(:user)
  619. {:ok, _user_relationships} = User.mute(user, muted, false)
  620. {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
  621. assert length(Notification.for_user(user)) == 1
  622. end
  623. test "it doesn't return notifications for muted user with notifications" do
  624. user = insert(:user)
  625. muted = insert(:user)
  626. {:ok, _user_relationships} = User.mute(user, muted)
  627. {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
  628. assert Notification.for_user(user) == []
  629. end
  630. test "it doesn't return notifications for blocked user" do
  631. user = insert(:user)
  632. blocked = insert(:user)
  633. {:ok, _user_relationship} = User.block(user, blocked)
  634. {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
  635. assert Notification.for_user(user) == []
  636. end
  637. test "it doesn't return notifications for blocked domain" do
  638. user = insert(:user)
  639. blocked = insert(:user, ap_id: "http://some-domain.com")
  640. {:ok, user} = User.block_domain(user, "some-domain.com")
  641. {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
  642. assert Notification.for_user(user) == []
  643. end
  644. test "it doesn't return notifications for muted thread" do
  645. user = insert(:user)
  646. another_user = insert(:user)
  647. {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
  648. {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
  649. assert Notification.for_user(user) == []
  650. end
  651. test "it returns notifications from a muted user when with_muted is set" do
  652. user = insert(:user)
  653. muted = insert(:user)
  654. {:ok, _user_relationships} = User.mute(user, muted)
  655. {:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
  656. assert length(Notification.for_user(user, %{with_muted: true})) == 1
  657. end
  658. test "it doesn't return notifications from a blocked user when with_muted is set" do
  659. user = insert(:user)
  660. blocked = insert(:user)
  661. {:ok, _user_relationship} = User.block(user, blocked)
  662. {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
  663. assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
  664. end
  665. test "it doesn't return notifications from a domain-blocked user when with_muted is set" do
  666. user = insert(:user)
  667. blocked = insert(:user, ap_id: "http://some-domain.com")
  668. {:ok, user} = User.block_domain(user, "some-domain.com")
  669. {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
  670. assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
  671. end
  672. test "it returns notifications from muted threads when with_muted is set" do
  673. user = insert(:user)
  674. another_user = insert(:user)
  675. {:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
  676. {:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
  677. assert length(Notification.for_user(user, %{with_muted: true})) == 1
  678. end
  679. end
  680. end