Merge remote-tracking branch 'origin/develop' into benchmark-finishing
[akkoma] / test / web / mastodon_api / controllers / timeline_controller_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.Web.MastodonAPI.TimelineControllerTest do
6 use Pleroma.Web.ConnCase
7
8 import Pleroma.Factory
9 import Tesla.Mock
10
11 alias Pleroma.Config
12 alias Pleroma.User
13 alias Pleroma.Web.CommonAPI
14 alias Pleroma.Web.OStatus
15
16 clear_config([:instance, :public])
17
18 setup do
19 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
20 :ok
21 end
22
23 test "the home timeline", %{conn: conn} do
24 user = insert(:user)
25 following = insert(:user)
26
27 {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
28
29 conn =
30 conn
31 |> assign(:user, user)
32 |> get("/api/v1/timelines/home")
33
34 assert Enum.empty?(json_response(conn, :ok))
35
36 {:ok, user} = User.follow(user, following)
37
38 conn =
39 build_conn()
40 |> assign(:user, user)
41 |> get("/api/v1/timelines/home")
42
43 assert [%{"content" => "test"}] = json_response(conn, :ok)
44 end
45
46 describe "public" do
47 @tag capture_log: true
48 test "the public timeline", %{conn: conn} do
49 following = insert(:user)
50
51 {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
52
53 {:ok, [_activity]} =
54 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
55
56 conn = get(conn, "/api/v1/timelines/public", %{"local" => "False"})
57
58 assert length(json_response(conn, :ok)) == 2
59
60 conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "True"})
61
62 assert [%{"content" => "test"}] = json_response(conn, :ok)
63
64 conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "1"})
65
66 assert [%{"content" => "test"}] = json_response(conn, :ok)
67 end
68
69 test "the public timeline when public is set to false", %{conn: conn} do
70 Config.put([:instance, :public], false)
71
72 assert %{"error" => "This resource requires authentication."} ==
73 conn
74 |> get("/api/v1/timelines/public", %{"local" => "False"})
75 |> json_response(:forbidden)
76 end
77
78 test "the public timeline includes only public statuses for an authenticated user" do
79 user = insert(:user)
80
81 conn =
82 build_conn()
83 |> assign(:user, user)
84
85 {:ok, _activity} = CommonAPI.post(user, %{"status" => "test"})
86 {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "private"})
87 {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "unlisted"})
88 {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"})
89
90 res_conn = get(conn, "/api/v1/timelines/public")
91 assert length(json_response(res_conn, 200)) == 1
92 end
93 end
94
95 describe "direct" do
96 test "direct timeline", %{conn: conn} do
97 user_one = insert(:user)
98 user_two = insert(:user)
99
100 {:ok, user_two} = User.follow(user_two, user_one)
101
102 {:ok, direct} =
103 CommonAPI.post(user_one, %{
104 "status" => "Hi @#{user_two.nickname}!",
105 "visibility" => "direct"
106 })
107
108 {:ok, _follower_only} =
109 CommonAPI.post(user_one, %{
110 "status" => "Hi @#{user_two.nickname}!",
111 "visibility" => "private"
112 })
113
114 # Only direct should be visible here
115 res_conn =
116 conn
117 |> assign(:user, user_two)
118 |> get("api/v1/timelines/direct")
119
120 [status] = json_response(res_conn, :ok)
121
122 assert %{"visibility" => "direct"} = status
123 assert status["url"] != direct.data["id"]
124
125 # User should be able to see their own direct message
126 res_conn =
127 build_conn()
128 |> assign(:user, user_one)
129 |> get("api/v1/timelines/direct")
130
131 [status] = json_response(res_conn, :ok)
132
133 assert %{"visibility" => "direct"} = status
134
135 # Both should be visible here
136 res_conn =
137 conn
138 |> assign(:user, user_two)
139 |> get("api/v1/timelines/home")
140
141 [_s1, _s2] = json_response(res_conn, :ok)
142
143 # Test pagination
144 Enum.each(1..20, fn _ ->
145 {:ok, _} =
146 CommonAPI.post(user_one, %{
147 "status" => "Hi @#{user_two.nickname}!",
148 "visibility" => "direct"
149 })
150 end)
151
152 res_conn =
153 conn
154 |> assign(:user, user_two)
155 |> get("api/v1/timelines/direct")
156
157 statuses = json_response(res_conn, :ok)
158 assert length(statuses) == 20
159
160 res_conn =
161 conn
162 |> assign(:user, user_two)
163 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
164
165 [status] = json_response(res_conn, :ok)
166
167 assert status["url"] != direct.data["id"]
168 end
169
170 test "doesn't include DMs from blocked users", %{conn: conn} do
171 blocker = insert(:user)
172 blocked = insert(:user)
173 user = insert(:user)
174 {:ok, blocker} = User.block(blocker, blocked)
175
176 {:ok, _blocked_direct} =
177 CommonAPI.post(blocked, %{
178 "status" => "Hi @#{blocker.nickname}!",
179 "visibility" => "direct"
180 })
181
182 {:ok, direct} =
183 CommonAPI.post(user, %{
184 "status" => "Hi @#{blocker.nickname}!",
185 "visibility" => "direct"
186 })
187
188 res_conn =
189 conn
190 |> assign(:user, user)
191 |> get("api/v1/timelines/direct")
192
193 [status] = json_response(res_conn, :ok)
194 assert status["id"] == direct.id
195 end
196 end
197
198 describe "list" do
199 test "list timeline", %{conn: conn} do
200 user = insert(:user)
201 other_user = insert(:user)
202 {:ok, _activity_one} = CommonAPI.post(user, %{"status" => "Marisa is cute."})
203 {:ok, activity_two} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."})
204 {:ok, list} = Pleroma.List.create("name", user)
205 {:ok, list} = Pleroma.List.follow(list, other_user)
206
207 conn =
208 conn
209 |> assign(:user, user)
210 |> get("/api/v1/timelines/list/#{list.id}")
211
212 assert [%{"id" => id}] = json_response(conn, :ok)
213
214 assert id == to_string(activity_two.id)
215 end
216
217 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
218 user = insert(:user)
219 other_user = insert(:user)
220 {:ok, activity_one} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."})
221
222 {:ok, _activity_two} =
223 CommonAPI.post(other_user, %{
224 "status" => "Marisa is cute.",
225 "visibility" => "private"
226 })
227
228 {:ok, list} = Pleroma.List.create("name", user)
229 {:ok, list} = Pleroma.List.follow(list, other_user)
230
231 conn =
232 conn
233 |> assign(:user, user)
234 |> get("/api/v1/timelines/list/#{list.id}")
235
236 assert [%{"id" => id}] = json_response(conn, :ok)
237
238 assert id == to_string(activity_one.id)
239 end
240 end
241
242 describe "hashtag" do
243 @tag capture_log: true
244 test "hashtag timeline", %{conn: conn} do
245 following = insert(:user)
246
247 {:ok, activity} = CommonAPI.post(following, %{"status" => "test #2hu"})
248
249 {:ok, [_activity]} =
250 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
251
252 nconn = get(conn, "/api/v1/timelines/tag/2hu")
253
254 assert [%{"id" => id}] = json_response(nconn, :ok)
255
256 assert id == to_string(activity.id)
257
258 # works for different capitalization too
259 nconn = get(conn, "/api/v1/timelines/tag/2HU")
260
261 assert [%{"id" => id}] = json_response(nconn, :ok)
262
263 assert id == to_string(activity.id)
264 end
265
266 test "multi-hashtag timeline", %{conn: conn} do
267 user = insert(:user)
268
269 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
270 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
271 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
272
273 any_test = get(conn, "/api/v1/timelines/tag/test", %{"any" => ["test1"]})
274
275 [status_none, status_test1, status_test] = json_response(any_test, :ok)
276
277 assert to_string(activity_test.id) == status_test["id"]
278 assert to_string(activity_test1.id) == status_test1["id"]
279 assert to_string(activity_none.id) == status_none["id"]
280
281 restricted_test =
282 get(conn, "/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
283
284 assert [status_test1] == json_response(restricted_test, :ok)
285
286 all_test = get(conn, "/api/v1/timelines/tag/test", %{"all" => ["none"]})
287
288 assert [status_none] == json_response(all_test, :ok)
289 end
290 end
291 end