OpenAPI: MastodonAPI Conversation Controller
[akkoma] / test / pleroma / web / mastodon_api / controllers / conversation_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
6 use Pleroma.Web.ConnCase, async: true
7
8 alias Pleroma.Conversation.Participation
9 alias Pleroma.User
10 alias Pleroma.Web.CommonAPI
11
12 import Pleroma.Factory
13
14 setup do: oauth_access(["read:statuses"])
15
16 describe "returns a list of conversations" do
17 setup(%{user: user_one, conn: conn}) do
18 user_two = insert(:user)
19 user_three = insert(:user)
20
21 {:ok, user_two, user_one} = User.follow(user_two, user_one)
22
23 {:ok, %{user: user_one, user_two: user_two, user_three: user_three, conn: conn}}
24 end
25
26 test "returns correct conversations", %{
27 user: user_one,
28 user_two: user_two,
29 user_three: user_three,
30 conn: conn
31 } do
32 assert Participation.unread_count(user_two) == 0
33 {:ok, direct} = create_direct_message(user_one, [user_two, user_three])
34
35 assert Participation.unread_count(user_two) == 1
36
37 {:ok, _follower_only} =
38 CommonAPI.post(user_one, %{
39 status: "Hi @#{user_two.nickname}!",
40 visibility: "private"
41 })
42
43 res_conn = get(conn, "/api/v1/conversations")
44
45 assert response = json_response_and_validate_schema(res_conn, 200)
46
47 assert [
48 %{
49 "id" => res_id,
50 "accounts" => res_accounts,
51 "last_status" => res_last_status,
52 "unread" => unread
53 }
54 ] = response
55
56 account_ids = Enum.map(res_accounts, & &1["id"])
57 assert length(res_accounts) == 2
58 assert user_one.id not in account_ids
59 assert user_two.id in account_ids
60 assert user_three.id in account_ids
61 assert is_binary(res_id)
62 assert unread == false
63 assert res_last_status["id"] == direct.id
64 assert res_last_status["account"]["id"] == user_one.id
65 assert Participation.unread_count(user_one) == 0
66 end
67
68 test "includes the user if the user is the only participant", %{
69 user: user_one,
70 conn: conn
71 } do
72 {:ok, _direct} = create_direct_message(user_one, [])
73
74 res_conn = get(conn, "/api/v1/conversations")
75
76 assert response = json_response_and_validate_schema(res_conn, 200)
77
78 assert [
79 %{
80 "accounts" => [account]
81 }
82 ] = response
83
84 assert user_one.id == account["id"]
85 end
86
87 test "observes limit params", %{
88 user: user_one,
89 user_two: user_two,
90 user_three: user_three,
91 conn: conn
92 } do
93 {:ok, _} = create_direct_message(user_one, [user_two, user_three])
94 {:ok, _} = create_direct_message(user_two, [user_one, user_three])
95 {:ok, _} = create_direct_message(user_three, [user_two, user_one])
96
97 res_conn = get(conn, "/api/v1/conversations?limit=1")
98
99 assert response = json_response_and_validate_schema(res_conn, 200)
100
101 assert Enum.count(response) == 1
102
103 res_conn = get(conn, "/api/v1/conversations?limit=2")
104
105 assert response = json_response_and_validate_schema(res_conn, 200)
106
107 assert Enum.count(response) == 2
108 end
109 end
110
111 test "filters conversations by recipients", %{user: user_one, conn: conn} do
112 user_two = insert(:user)
113 user_three = insert(:user)
114 {:ok, direct1} = create_direct_message(user_one, [user_two])
115 {:ok, _direct2} = create_direct_message(user_one, [user_three])
116 {:ok, direct3} = create_direct_message(user_one, [user_two, user_three])
117 {:ok, _direct4} = create_direct_message(user_two, [user_three])
118 {:ok, direct5} = create_direct_message(user_two, [user_one])
119
120 assert [conversation1, conversation2] =
121 conn
122 |> get("/api/v1/conversations?recipients[]=#{user_two.id}")
123 |> json_response_and_validate_schema(200)
124
125 assert conversation1["last_status"]["id"] == direct5.id
126 assert conversation2["last_status"]["id"] == direct1.id
127
128 [conversation1] =
129 conn
130 |> get("/api/v1/conversations?recipients[]=#{user_two.id}&recipients[]=#{user_three.id}")
131 |> json_response_and_validate_schema(200)
132
133 assert conversation1["last_status"]["id"] == direct3.id
134 end
135
136 test "updates the last_status on reply", %{user: user_one, conn: conn} do
137 user_two = insert(:user)
138 {:ok, direct} = create_direct_message(user_one, [user_two])
139
140 {:ok, direct_reply} =
141 CommonAPI.post(user_two, %{
142 status: "reply",
143 visibility: "direct",
144 in_reply_to_status_id: direct.id
145 })
146
147 [%{"last_status" => res_last_status}] =
148 conn
149 |> get("/api/v1/conversations")
150 |> json_response_and_validate_schema(200)
151
152 assert res_last_status["id"] == direct_reply.id
153 end
154
155 test "the user marks a conversation as read", %{user: user_one, conn: conn} do
156 user_two = insert(:user)
157 {:ok, direct} = create_direct_message(user_one, [user_two])
158
159 assert Participation.unread_count(user_one) == 0
160 assert Participation.unread_count(user_two) == 1
161
162 user_two_conn =
163 build_conn()
164 |> assign(:user, user_two)
165 |> assign(
166 :token,
167 insert(:oauth_token, user: user_two, scopes: ["read:statuses", "write:conversations"])
168 )
169
170 [%{"id" => direct_conversation_id, "unread" => true}] =
171 user_two_conn
172 |> get("/api/v1/conversations")
173 |> json_response_and_validate_schema(200)
174
175 %{"unread" => false} =
176 user_two_conn
177 |> post("/api/v1/conversations/#{direct_conversation_id}/read")
178 |> json_response_and_validate_schema(200)
179
180 assert Participation.unread_count(user_one) == 0
181 assert Participation.unread_count(user_two) == 0
182
183 # The conversation is marked as unread on reply
184 {:ok, _} =
185 CommonAPI.post(user_two, %{
186 status: "reply",
187 visibility: "direct",
188 in_reply_to_status_id: direct.id
189 })
190
191 [%{"unread" => true}] =
192 conn
193 |> get("/api/v1/conversations")
194 |> json_response_and_validate_schema(200)
195
196 assert Participation.unread_count(user_one) == 1
197 assert Participation.unread_count(user_two) == 0
198
199 # A reply doesn't increment the user's unread_conversation_count if the conversation is unread
200 {:ok, _} =
201 CommonAPI.post(user_two, %{
202 status: "reply",
203 visibility: "direct",
204 in_reply_to_status_id: direct.id
205 })
206
207 assert Participation.unread_count(user_one) == 1
208 assert Participation.unread_count(user_two) == 0
209 end
210
211 test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do
212 user_two = insert(:user)
213 {:ok, direct} = create_direct_message(user_one, [user_two])
214
215 res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context")
216
217 assert %{"ancestors" => [], "descendants" => []} ==
218 json_response_and_validate_schema(res_conn, 200)
219 end
220
221 test "Removes a conversation", %{user: user_one, conn: conn} do
222 user_two = insert(:user)
223 token = insert(:oauth_token, user: user_one, scopes: ["read:statuses", "write:conversations"])
224
225 {:ok, _direct} = create_direct_message(user_one, [user_two])
226 {:ok, _direct} = create_direct_message(user_one, [user_two])
227
228 assert [%{"id" => conv1_id}, %{"id" => conv2_id}] =
229 conn
230 |> assign(:token, token)
231 |> get("/api/v1/conversations")
232 |> json_response_and_validate_schema(200)
233
234 assert %{} =
235 conn
236 |> assign(:token, token)
237 |> delete("/api/v1/conversations/#{conv1_id}")
238 |> json_response_and_validate_schema(200)
239
240 assert [%{"id" => ^conv2_id}] =
241 conn
242 |> assign(:token, token)
243 |> get("/api/v1/conversations")
244 |> json_response_and_validate_schema(200)
245 end
246
247 defp create_direct_message(sender, recips) do
248 hellos =
249 recips
250 |> Enum.map(fn s -> "@#{s.nickname}" end)
251 |> Enum.join(", ")
252
253 CommonAPI.post(sender, %{
254 status: "Hi #{hellos}!",
255 visibility: "direct"
256 })
257 end
258 end