Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
[akkoma] / test / conversation / participation_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.Conversation.ParticipationTest do
6 use Pleroma.DataCase
7 import Pleroma.Factory
8 alias Pleroma.Conversation.Participation
9 alias Pleroma.User
10 alias Pleroma.Web.CommonAPI
11
12 test "getting a participation will also preload things" do
13 user = insert(:user)
14 other_user = insert(:user)
15
16 {:ok, _activity} =
17 CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
18
19 [participation] = Participation.for_user(user)
20
21 participation = Participation.get(participation.id, preload: [:conversation])
22
23 assert %Pleroma.Conversation{} = participation.conversation
24 end
25
26 test "for a new conversation or a reply, it doesn't mark the author's participation as unread" do
27 user = insert(:user)
28 other_user = insert(:user)
29
30 {:ok, _} =
31 CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
32
33 user = User.get_cached_by_id(user.id)
34 other_user = User.get_cached_by_id(other_user.id)
35
36 [%{read: true}] = Participation.for_user(user)
37 [%{read: false} = participation] = Participation.for_user(other_user)
38
39 assert User.get_cached_by_id(user.id).unread_conversation_count == 0
40 assert User.get_cached_by_id(other_user.id).unread_conversation_count == 1
41
42 {:ok, _} =
43 CommonAPI.post(other_user, %{
44 "status" => "Hey @#{user.nickname}.",
45 "visibility" => "direct",
46 "in_reply_to_conversation_id" => participation.id
47 })
48
49 user = User.get_cached_by_id(user.id)
50 other_user = User.get_cached_by_id(other_user.id)
51
52 [%{read: false}] = Participation.for_user(user)
53 [%{read: true}] = Participation.for_user(other_user)
54
55 assert User.get_cached_by_id(user.id).unread_conversation_count == 1
56 assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0
57 end
58
59 test "for a new conversation, it sets the recipents of the participation" do
60 user = insert(:user)
61 other_user = insert(:user)
62 third_user = insert(:user)
63
64 {:ok, activity} =
65 CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
66
67 user = User.get_cached_by_id(user.id)
68 other_user = User.get_cached_by_id(other_user.id)
69 [participation] = Participation.for_user(user)
70 participation = Pleroma.Repo.preload(participation, :recipients)
71
72 assert length(participation.recipients) == 2
73 assert user in participation.recipients
74 assert other_user in participation.recipients
75
76 # Mentioning another user in the same conversation will not add a new recipients.
77
78 {:ok, _activity} =
79 CommonAPI.post(user, %{
80 "in_reply_to_status_id" => activity.id,
81 "status" => "Hey @#{third_user.nickname}.",
82 "visibility" => "direct"
83 })
84
85 [participation] = Participation.for_user(user)
86 participation = Pleroma.Repo.preload(participation, :recipients)
87
88 assert length(participation.recipients) == 2
89 end
90
91 test "it creates a participation for a conversation and a user" do
92 user = insert(:user)
93 conversation = insert(:conversation)
94
95 {:ok, %Participation{} = participation} =
96 Participation.create_for_user_and_conversation(user, conversation)
97
98 assert participation.user_id == user.id
99 assert participation.conversation_id == conversation.id
100
101 :timer.sleep(1000)
102 # Creating again returns the same participation
103 {:ok, %Participation{} = participation_two} =
104 Participation.create_for_user_and_conversation(user, conversation)
105
106 assert participation.id == participation_two.id
107 refute participation.updated_at == participation_two.updated_at
108 end
109
110 test "recreating an existing participations sets it to unread" do
111 participation = insert(:participation, %{read: true})
112
113 {:ok, participation} =
114 Participation.create_for_user_and_conversation(
115 participation.user,
116 participation.conversation
117 )
118
119 refute participation.read
120 end
121
122 test "it marks a participation as read" do
123 participation = insert(:participation, %{read: false})
124 {:ok, participation} = Participation.mark_as_read(participation)
125
126 assert participation.read
127 end
128
129 test "it marks a participation as unread" do
130 participation = insert(:participation, %{read: true})
131 {:ok, participation} = Participation.mark_as_unread(participation)
132
133 refute participation.read
134 end
135
136 test "it marks all the user's participations as read" do
137 user = insert(:user)
138 other_user = insert(:user)
139 participation1 = insert(:participation, %{read: false, user: user})
140 participation2 = insert(:participation, %{read: false, user: user})
141 participation3 = insert(:participation, %{read: false, user: other_user})
142
143 {:ok, _, [%{read: true}, %{read: true}]} = Participation.mark_all_as_read(user)
144
145 assert Participation.get(participation1.id).read == true
146 assert Participation.get(participation2.id).read == true
147 assert Participation.get(participation3.id).read == false
148 end
149
150 test "gets all the participations for a user, ordered by updated at descending" do
151 user = insert(:user)
152 {:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
153 :timer.sleep(1000)
154 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
155 :timer.sleep(1000)
156
157 {:ok, activity_three} =
158 CommonAPI.post(user, %{
159 "status" => "x",
160 "visibility" => "direct",
161 "in_reply_to_status_id" => activity_one.id
162 })
163
164 assert [participation_one, participation_two] = Participation.for_user(user)
165
166 object2 = Pleroma.Object.normalize(activity_two)
167 object3 = Pleroma.Object.normalize(activity_three)
168
169 user = Repo.get(Pleroma.User, user.id)
170
171 assert participation_one.conversation.ap_id == object3.data["context"]
172 assert participation_two.conversation.ap_id == object2.data["context"]
173 assert participation_one.conversation.users == [user]
174
175 # Pagination
176 assert [participation_one] = Participation.for_user(user, %{"limit" => 1})
177
178 assert participation_one.conversation.ap_id == object3.data["context"]
179
180 # With last_activity_id
181 assert [participation_one] =
182 Participation.for_user_with_last_activity_id(user, %{"limit" => 1})
183
184 assert participation_one.last_activity_id == activity_three.id
185 end
186
187 test "Doesn't die when the conversation gets empty" do
188 user = insert(:user)
189
190 {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
191 [participation] = Participation.for_user_with_last_activity_id(user)
192
193 assert participation.last_activity_id == activity.id
194
195 {:ok, _} = CommonAPI.delete(activity.id, user)
196
197 [] = Participation.for_user_with_last_activity_id(user)
198 end
199
200 test "it sets recipients, always keeping the owner of the participation even when not explicitly set" do
201 user = insert(:user)
202 other_user = insert(:user)
203
204 {:ok, _activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
205 [participation] = Participation.for_user_with_last_activity_id(user)
206
207 participation = Repo.preload(participation, :recipients)
208 user = User.get_cached_by_id(user.id)
209
210 assert participation.recipients |> length() == 1
211 assert user in participation.recipients
212
213 {:ok, participation} = Participation.set_recipients(participation, [other_user.id])
214
215 assert participation.recipients |> length() == 2
216 assert user in participation.recipients
217 assert other_user in participation.recipients
218 end
219
220 describe "blocking" do
221 test "when the user blocks a recipient, the existing conversations with them are marked as read" do
222 blocker = insert(:user)
223 blocked = insert(:user)
224 third_user = insert(:user)
225
226 {:ok, _direct1} =
227 CommonAPI.post(third_user, %{
228 "status" => "Hi @#{blocker.nickname}",
229 "visibility" => "direct"
230 })
231
232 {:ok, _direct2} =
233 CommonAPI.post(third_user, %{
234 "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
235 "visibility" => "direct"
236 })
237
238 {:ok, _direct3} =
239 CommonAPI.post(blocked, %{
240 "status" => "Hi @#{blocker.nickname}",
241 "visibility" => "direct"
242 })
243
244 {:ok, _direct4} =
245 CommonAPI.post(blocked, %{
246 "status" => "Hi @#{blocker.nickname}, @#{third_user.nickname}",
247 "visibility" => "direct"
248 })
249
250 assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
251 Participation.for_user(blocker)
252
253 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 4
254
255 {:ok, _user_relationship} = User.block(blocker, blocked)
256
257 # The conversations with the blocked user are marked as read
258 assert [%{read: true}, %{read: true}, %{read: true}, %{read: false}] =
259 Participation.for_user(blocker)
260
261 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 1
262
263 # The conversation is not marked as read for the blocked user
264 assert [_, _, %{read: false}] = Participation.for_user(blocked)
265 assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
266
267 # The conversation is not marked as read for the third user
268 assert [%{read: false}, _, _] = Participation.for_user(third_user)
269 assert User.get_cached_by_id(third_user.id).unread_conversation_count == 1
270 end
271
272 test "the new conversation with the blocked user is not marked as unread " do
273 blocker = insert(:user)
274 blocked = insert(:user)
275 third_user = insert(:user)
276
277 {:ok, _user_relationship} = User.block(blocker, blocked)
278
279 # When the blocked user is the author
280 {:ok, _direct1} =
281 CommonAPI.post(blocked, %{
282 "status" => "Hi @#{blocker.nickname}",
283 "visibility" => "direct"
284 })
285
286 assert [%{read: true}] = Participation.for_user(blocker)
287 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
288
289 # When the blocked user is a recipient
290 {:ok, _direct2} =
291 CommonAPI.post(third_user, %{
292 "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
293 "visibility" => "direct"
294 })
295
296 assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
297 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
298
299 assert [%{read: false}, _] = Participation.for_user(blocked)
300 assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
301 end
302
303 test "the conversation with the blocked user is not marked as unread on a reply" do
304 blocker = insert(:user)
305 blocked = insert(:user)
306 third_user = insert(:user)
307
308 {:ok, _direct1} =
309 CommonAPI.post(blocker, %{
310 "status" => "Hi @#{third_user.nickname}, @#{blocked.nickname}",
311 "visibility" => "direct"
312 })
313
314 {:ok, _user_relationship} = User.block(blocker, blocked)
315 assert [%{read: true}] = Participation.for_user(blocker)
316 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
317
318 assert [blocked_participation] = Participation.for_user(blocked)
319
320 # When it's a reply from the blocked user
321 {:ok, _direct2} =
322 CommonAPI.post(blocked, %{
323 "status" => "reply",
324 "visibility" => "direct",
325 "in_reply_to_conversation_id" => blocked_participation.id
326 })
327
328 assert [%{read: true}] = Participation.for_user(blocker)
329 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
330
331 assert [third_user_participation] = Participation.for_user(third_user)
332
333 # When it's a reply from the third user
334 {:ok, _direct3} =
335 CommonAPI.post(third_user, %{
336 "status" => "reply",
337 "visibility" => "direct",
338 "in_reply_to_conversation_id" => third_user_participation.id
339 })
340
341 assert [%{read: true}] = Participation.for_user(blocker)
342 assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
343
344 # Marked as unread for the blocked user
345 assert [%{read: false}] = Participation.for_user(blocked)
346 assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
347 end
348 end
349 end