logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

participation_test.exs (13032B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Conversation.ParticipationTest do
  5. use Pleroma.DataCase, async: true
  6. import Pleroma.Factory
  7. alias Pleroma.Conversation
  8. alias Pleroma.Conversation.Participation
  9. alias Pleroma.Repo
  10. alias Pleroma.User
  11. alias Pleroma.Web.CommonAPI
  12. test "getting a participation will also preload things" do
  13. user = insert(:user)
  14. other_user = insert(:user)
  15. {:ok, _activity} =
  16. CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
  17. [participation] = Participation.for_user(user)
  18. participation = Participation.get(participation.id, preload: [:conversation])
  19. assert %Pleroma.Conversation{} = participation.conversation
  20. end
  21. test "for a new conversation or a reply, it doesn't mark the author's participation as unread" do
  22. user = insert(:user)
  23. other_user = insert(:user)
  24. {:ok, _} =
  25. CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
  26. user = User.get_cached_by_id(user.id)
  27. other_user = User.get_cached_by_id(other_user.id)
  28. [%{read: true}] = Participation.for_user(user)
  29. [%{read: false} = participation] = Participation.for_user(other_user)
  30. assert Participation.unread_count(user) == 0
  31. assert Participation.unread_count(other_user) == 1
  32. {:ok, _} =
  33. CommonAPI.post(other_user, %{
  34. status: "Hey @#{user.nickname}.",
  35. visibility: "direct",
  36. in_reply_to_conversation_id: participation.id
  37. })
  38. user = User.get_cached_by_id(user.id)
  39. other_user = User.get_cached_by_id(other_user.id)
  40. [%{read: false}] = Participation.for_user(user)
  41. [%{read: true}] = Participation.for_user(other_user)
  42. assert Participation.unread_count(user) == 1
  43. assert Participation.unread_count(other_user) == 0
  44. end
  45. test "for a new conversation, it sets the recipients of the participation" do
  46. user = insert(:user)
  47. other_user = insert(:user)
  48. third_user = insert(:user)
  49. {:ok, activity} =
  50. CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
  51. user = User.get_cached_by_id(user.id)
  52. other_user = User.get_cached_by_id(other_user.id)
  53. [participation] = Participation.for_user(user)
  54. participation = Pleroma.Repo.preload(participation, :recipients)
  55. assert length(participation.recipients) == 2
  56. assert user in participation.recipients
  57. assert other_user in participation.recipients
  58. # Mentioning another user in the same conversation will not add a new recipients.
  59. {:ok, _activity} =
  60. CommonAPI.post(user, %{
  61. in_reply_to_status_id: activity.id,
  62. status: "Hey @#{third_user.nickname}.",
  63. visibility: "direct"
  64. })
  65. [participation] = Participation.for_user(user)
  66. participation = Pleroma.Repo.preload(participation, :recipients)
  67. assert length(participation.recipients) == 2
  68. end
  69. test "it creates a participation for a conversation and a user" do
  70. user = insert(:user)
  71. conversation = insert(:conversation)
  72. {:ok, %Participation{} = participation} =
  73. Participation.create_for_user_and_conversation(user, conversation)
  74. {:ok, participation} = time_travel(participation, -2)
  75. assert participation.user_id == user.id
  76. assert participation.conversation_id == conversation.id
  77. # Creating again returns the same participation
  78. {:ok, %Participation{} = participation_two} =
  79. Participation.create_for_user_and_conversation(user, conversation)
  80. assert participation.id == participation_two.id
  81. refute participation.updated_at == participation_two.updated_at
  82. end
  83. test "recreating an existing participations sets it to unread" do
  84. participation = insert(:participation, %{read: true})
  85. {:ok, participation} =
  86. Participation.create_for_user_and_conversation(
  87. participation.user,
  88. participation.conversation
  89. )
  90. refute participation.read
  91. end
  92. test "it marks a participation as read" do
  93. participation = insert(:participation, %{updated_at: ~N[2017-07-17 17:09:58], read: false})
  94. {:ok, updated_participation} = Participation.mark_as_read(participation)
  95. assert updated_participation.read
  96. assert :gt = NaiveDateTime.compare(updated_participation.updated_at, participation.updated_at)
  97. end
  98. test "it marks a participation as unread" do
  99. participation = insert(:participation, %{read: true})
  100. {:ok, participation} = Participation.mark_as_unread(participation)
  101. refute participation.read
  102. end
  103. test "it marks all the user's participations as read" do
  104. user = insert(:user)
  105. other_user = insert(:user)
  106. participation1 = insert(:participation, %{read: false, user: user})
  107. participation2 = insert(:participation, %{read: false, user: user})
  108. participation3 = insert(:participation, %{read: false, user: other_user})
  109. {:ok, _, [%{read: true}, %{read: true}]} = Participation.mark_all_as_read(user)
  110. assert Participation.get(participation1.id).read == true
  111. assert Participation.get(participation2.id).read == true
  112. assert Participation.get(participation3.id).read == false
  113. end
  114. test "gets all the participations for a user, ordered by updated at descending" do
  115. user = insert(:user)
  116. {:ok, activity_one} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
  117. {:ok, activity_two} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
  118. {:ok, activity_three} =
  119. CommonAPI.post(user, %{
  120. status: "x",
  121. visibility: "direct",
  122. in_reply_to_status_id: activity_one.id
  123. })
  124. # Offset participations because the accuracy of updated_at is down to a second
  125. for {activity, offset} <- [{activity_two, 1}, {activity_three, 2}] do
  126. conversation = Conversation.get_for_ap_id(activity.data["context"])
  127. participation = Participation.for_user_and_conversation(user, conversation)
  128. updated_at = NaiveDateTime.add(Map.get(participation, :updated_at), offset)
  129. Ecto.Changeset.change(participation, %{updated_at: updated_at})
  130. |> Repo.update!()
  131. end
  132. assert [participation_one, participation_two] = Participation.for_user(user)
  133. object2 = Pleroma.Object.normalize(activity_two, fetch: false)
  134. object3 = Pleroma.Object.normalize(activity_three, fetch: false)
  135. user = Repo.get(Pleroma.User, user.id)
  136. assert participation_one.conversation.ap_id == object3.data["context"]
  137. assert participation_two.conversation.ap_id == object2.data["context"]
  138. assert participation_one.conversation.users == [user]
  139. # Pagination
  140. assert [participation_one] = Participation.for_user(user, %{"limit" => 1})
  141. assert participation_one.conversation.ap_id == object3.data["context"]
  142. # With last_activity_id
  143. assert [participation_one] =
  144. Participation.for_user_with_last_activity_id(user, %{"limit" => 1})
  145. assert participation_one.last_activity_id == activity_three.id
  146. end
  147. test "Doesn't die when the conversation gets empty" do
  148. user = insert(:user)
  149. {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
  150. [participation] = Participation.for_user_with_last_activity_id(user)
  151. assert participation.last_activity_id == activity.id
  152. {:ok, _} = CommonAPI.delete(activity.id, user)
  153. [] = Participation.for_user_with_last_activity_id(user)
  154. end
  155. test "it sets recipients, always keeping the owner of the participation even when not explicitly set" do
  156. user = insert(:user)
  157. other_user = insert(:user)
  158. {:ok, _activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
  159. [participation] = Participation.for_user_with_last_activity_id(user)
  160. participation = Repo.preload(participation, :recipients)
  161. user = User.get_cached_by_id(user.id)
  162. assert participation.recipients |> length() == 1
  163. assert user in participation.recipients
  164. {:ok, participation} = Participation.set_recipients(participation, [other_user.id])
  165. assert participation.recipients |> length() == 2
  166. assert user in participation.recipients
  167. assert other_user in participation.recipients
  168. end
  169. describe "blocking" do
  170. test "when the user blocks a recipient, the existing conversations with them are marked as read" do
  171. blocker = insert(:user)
  172. blocked = insert(:user)
  173. third_user = insert(:user)
  174. {:ok, _direct1} =
  175. CommonAPI.post(third_user, %{
  176. status: "Hi @#{blocker.nickname}",
  177. visibility: "direct"
  178. })
  179. {:ok, _direct2} =
  180. CommonAPI.post(third_user, %{
  181. status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
  182. visibility: "direct"
  183. })
  184. {:ok, _direct3} =
  185. CommonAPI.post(blocked, %{
  186. status: "Hi @#{blocker.nickname}",
  187. visibility: "direct"
  188. })
  189. {:ok, _direct4} =
  190. CommonAPI.post(blocked, %{
  191. status: "Hi @#{blocker.nickname}, @#{third_user.nickname}",
  192. visibility: "direct"
  193. })
  194. assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
  195. Participation.for_user(blocker)
  196. assert Participation.unread_count(blocker) == 4
  197. {:ok, _user_relationship} = User.block(blocker, blocked)
  198. # The conversations with the blocked user are marked as read
  199. assert [%{read: true}, %{read: true}, %{read: true}, %{read: false}] =
  200. Participation.for_user(blocker)
  201. assert Participation.unread_count(blocker) == 1
  202. # The conversation is not marked as read for the blocked user
  203. assert [_, _, %{read: false}] = Participation.for_user(blocked)
  204. assert Participation.unread_count(blocker) == 1
  205. # The conversation is not marked as read for the third user
  206. assert [%{read: false}, _, _] = Participation.for_user(third_user)
  207. assert Participation.unread_count(third_user) == 1
  208. end
  209. test "the new conversation with the blocked user is not marked as unread " do
  210. blocker = insert(:user)
  211. blocked = insert(:user)
  212. third_user = insert(:user)
  213. {:ok, _user_relationship} = User.block(blocker, blocked)
  214. # When the blocked user is the author
  215. {:ok, _direct1} =
  216. CommonAPI.post(blocked, %{
  217. status: "Hi @#{blocker.nickname}",
  218. visibility: "direct"
  219. })
  220. assert [%{read: true}] = Participation.for_user(blocker)
  221. assert Participation.unread_count(blocker) == 0
  222. # When the blocked user is a recipient
  223. {:ok, _direct2} =
  224. CommonAPI.post(third_user, %{
  225. status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
  226. visibility: "direct"
  227. })
  228. assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
  229. assert Participation.unread_count(blocker) == 0
  230. assert [%{read: false}, _] = Participation.for_user(blocked)
  231. assert Participation.unread_count(blocked) == 1
  232. end
  233. test "the conversation with the blocked user is not marked as unread on a reply" do
  234. blocker = insert(:user)
  235. blocked = insert(:user)
  236. third_user = insert(:user)
  237. {:ok, _direct1} =
  238. CommonAPI.post(blocker, %{
  239. status: "Hi @#{third_user.nickname}, @#{blocked.nickname}",
  240. visibility: "direct"
  241. })
  242. {:ok, _user_relationship} = User.block(blocker, blocked)
  243. assert [%{read: true}] = Participation.for_user(blocker)
  244. assert Participation.unread_count(blocker) == 0
  245. assert [blocked_participation] = Participation.for_user(blocked)
  246. # When it's a reply from the blocked user
  247. {:ok, _direct2} =
  248. CommonAPI.post(blocked, %{
  249. status: "reply",
  250. visibility: "direct",
  251. in_reply_to_conversation_id: blocked_participation.id
  252. })
  253. assert [%{read: true}] = Participation.for_user(blocker)
  254. assert Participation.unread_count(blocker) == 0
  255. assert [third_user_participation] = Participation.for_user(third_user)
  256. # When it's a reply from the third user
  257. {:ok, _direct3} =
  258. CommonAPI.post(third_user, %{
  259. status: "reply",
  260. visibility: "direct",
  261. in_reply_to_conversation_id: third_user_participation.id
  262. })
  263. assert [%{read: true}] = Participation.for_user(blocker)
  264. assert Participation.unread_count(blocker) == 0
  265. # Marked as unread for the blocked user
  266. assert [%{read: false}] = Participation.for_user(blocked)
  267. assert Participation.unread_count(blocked) == 1
  268. end
  269. end
  270. test "deletes a conversation" do
  271. user = insert(:user)
  272. other_user = insert(:user)
  273. {:ok, _activity} =
  274. CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
  275. assert [participation] = Participation.for_user(other_user)
  276. assert {:ok, _} = Participation.delete(participation)
  277. assert [] == Participation.for_user(other_user)
  278. end
  279. end