static-fe overhaul (#236)
[akkoma] / test / pleroma / web / static_fe / static_fe_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.StaticFE.StaticFEControllerTest do
6 use Pleroma.Web.ConnCase
7
8 alias Pleroma.Activity
9 alias Pleroma.User
10 alias Pleroma.Web.ActivityPub.ActivityPub
11 alias Pleroma.Web.ActivityPub.Transmogrifier
12 alias Pleroma.Web.ActivityPub.Utils
13 alias Pleroma.Web.CommonAPI
14
15 import Pleroma.Factory
16
17 setup_all do: clear_config([:static_fe, :enabled], true)
18
19 setup %{conn: conn} do
20 conn = put_req_header(conn, "accept", "text/html")
21 user = insert(:user)
22
23 %{conn: conn, user: user}
24 end
25
26 describe "user profile html" do
27 test "just the profile as HTML", %{conn: conn, user: user} do
28 conn = get(conn, "/users/#{user.nickname}")
29
30 assert html_response(conn, 200) =~ user.nickname
31 end
32
33 test "404 when user not found", %{conn: conn} do
34 conn = get(conn, "/users/limpopo")
35
36 assert html_response(conn, 404) =~ "not found"
37 end
38
39 test "profile does not include private messages", %{conn: conn, user: user} do
40 CommonAPI.post(user, %{status: "public"})
41 CommonAPI.post(user, %{status: "private", visibility: "private"})
42
43 conn = get(conn, "/users/#{user.nickname}")
44
45 html = html_response(conn, 200)
46
47 assert html =~ "\npublic\n"
48 refute html =~ "\nprivate\n"
49 end
50
51 test "main page does not include replies", %{conn: conn, user: user} do
52 {:ok, op} = CommonAPI.post(user, %{status: "beep"})
53 CommonAPI.post(user, %{status: "boop", in_reply_to_id: op})
54
55 conn = get(conn, "/users/#{user.nickname}")
56
57 html = html_response(conn, 200)
58
59 assert html =~ "\nbeep\n"
60 refute html =~ "\nboop\n"
61 end
62
63 test "media page only includes posts with attachments", %{conn: conn, user: user} do
64 file = %Plug.Upload{
65 content_type: "image/jpeg",
66 path: Path.absname("test/fixtures/image.jpg"),
67 filename: "an_image.jpg"
68 }
69
70 {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
71
72 CommonAPI.post(user, %{status: "virgin text post"})
73 CommonAPI.post(user, %{status: "chad post with attachment", media_ids: [media_id]})
74
75 conn = get(conn, "/users/#{user.nickname}/media")
76
77 html = html_response(conn, 200)
78
79 assert html =~ "\nchad post with attachment\n"
80 refute html =~ "\nvirgin text post\n"
81 end
82
83 test "show follower list", %{conn: conn, user: user} do
84 follower = insert(:user)
85 CommonAPI.follow(follower, user)
86
87 conn = get(conn, "/users/#{user.nickname}/followers")
88
89 html = html_response(conn, 200)
90
91 assert html =~ "user-card"
92 end
93
94 test "don't show followers if hidden", %{conn: conn, user: user} do
95 follower = insert(:user)
96 CommonAPI.follow(follower, user)
97
98 {:ok, user} =
99 user
100 |> User.update_changeset(%{hide_followers: true})
101 |> User.update_and_set_cache()
102
103 conn = get(conn, "/users/#{user.nickname}/followers")
104
105 html = html_response(conn, 200)
106
107 refute html =~ "user-card"
108 end
109
110 test "pagination", %{conn: conn, user: user} do
111 Enum.map(1..30, fn i -> CommonAPI.post(user, %{status: "test#{i}"}) end)
112
113 conn = get(conn, "/users/#{user.nickname}")
114
115 html = html_response(conn, 200)
116
117 assert html =~ "\ntest30\n"
118 assert html =~ "\ntest11\n"
119 refute html =~ "\ntest10\n"
120 refute html =~ "\ntest1\n"
121 end
122
123 test "pagination, page 2", %{conn: conn, user: user} do
124 activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{status: "test#{i}"}) end)
125 {:ok, a11} = Enum.at(activities, 11)
126
127 conn = get(conn, "/users/#{user.nickname}?max_id=#{a11.id}")
128
129 html = html_response(conn, 200)
130
131 assert html =~ "\ntest1\n"
132 assert html =~ "\ntest10\n"
133 refute html =~ "\ntest20\n"
134 refute html =~ "\ntest29\n"
135 end
136
137 test "does not require authentication on non-federating instances", %{
138 conn: conn,
139 user: user
140 } do
141 clear_config([:instance, :federating], false)
142
143 conn = get(conn, "/users/#{user.nickname}")
144
145 assert html_response(conn, 200) =~ user.nickname
146 end
147
148 test "returns 404 for local user with `restrict_unauthenticated/profiles/local` setting", %{
149 conn: conn
150 } do
151 clear_config([:restrict_unauthenticated, :profiles, :local], true)
152
153 local_user = insert(:user, local: true)
154
155 conn
156 |> get("/users/#{local_user.nickname}")
157 |> html_response(404)
158 end
159 end
160
161 describe "notice html" do
162 test "single notice page", %{conn: conn, user: user} do
163 {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
164
165 conn = get(conn, "/notice/#{activity.id}")
166
167 html = html_response(conn, 200)
168 assert html =~ "<div class=\"panel conversation\">"
169 assert html =~ user.nickname
170 assert html =~ "testing a thing!"
171 end
172
173 test "redirects to json if requested", %{conn: conn, user: user} do
174 {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
175
176 conn =
177 conn
178 |> put_req_header(
179 "accept",
180 "Accept: application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", text/html"
181 )
182 |> get("/notice/#{activity.id}")
183
184 assert redirected_to(conn, 302) =~ activity.data["object"]
185 end
186
187 test "filters HTML tags", %{conn: conn} do
188 user = insert(:user)
189 {:ok, activity} = CommonAPI.post(user, %{status: "<script>alert('xss')</script>"})
190
191 conn =
192 conn
193 |> put_req_header("accept", "text/html")
194 |> get("/notice/#{activity.id}")
195
196 html = html_response(conn, 200)
197 assert html =~ ~s[&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;]
198 end
199
200 test "shows the whole thread", %{conn: conn, user: user} do
201 {:ok, activity} = CommonAPI.post(user, %{status: "space: the final frontier"})
202
203 CommonAPI.post(user, %{
204 status: "these are the voyages or something",
205 in_reply_to_status_id: activity.id
206 })
207
208 conn = get(conn, "/notice/#{activity.id}")
209
210 html = html_response(conn, 200)
211 assert html =~ "the final frontier"
212 assert html =~ "voyages"
213 end
214
215 test "redirect by AP object ID", %{conn: conn, user: user} do
216 {:ok, %Activity{data: %{"object" => object_url}}} =
217 CommonAPI.post(user, %{status: "beam me up"})
218
219 conn = get(conn, URI.parse(object_url).path)
220
221 assert html_response(conn, 302) =~ "redirected"
222 end
223
224 test "redirect by activity ID", %{conn: conn, user: user} do
225 {:ok, %Activity{data: %{"id" => id}}} =
226 CommonAPI.post(user, %{status: "I'm a doctor, not a devops!"})
227
228 conn = get(conn, URI.parse(id).path)
229
230 assert html_response(conn, 302) =~ "redirected"
231 end
232
233 test "404 when notice not found", %{conn: conn} do
234 conn = get(conn, "/notice/88c9c317")
235
236 assert html_response(conn, 404) =~ "not found"
237 end
238
239 test "404 for private status", %{conn: conn, user: user} do
240 {:ok, activity} = CommonAPI.post(user, %{status: "don't show me!", visibility: "private"})
241
242 conn = get(conn, "/notice/#{activity.id}")
243
244 assert html_response(conn, 404) =~ "not found"
245 end
246
247 test "302 for remote cached status", %{conn: conn, user: user} do
248 message = %{
249 "@context" => "https://www.w3.org/ns/activitystreams",
250 "type" => "Create",
251 "actor" => user.ap_id,
252 "object" => %{
253 "to" => user.follower_address,
254 "cc" => "https://www.w3.org/ns/activitystreams#Public",
255 "id" => Utils.generate_object_id(),
256 "content" => "blah blah blah",
257 "type" => "Note",
258 "attributedTo" => user.ap_id
259 }
260 }
261
262 assert {:ok, activity} = Transmogrifier.handle_incoming(message)
263
264 conn = get(conn, "/notice/#{activity.id}")
265
266 assert html_response(conn, 302) =~ "redirected"
267 end
268
269 test "does not require authentication on non-federating instances", %{
270 conn: conn,
271 user: user
272 } do
273 clear_config([:instance, :federating], false)
274
275 {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
276
277 conn = get(conn, "/notice/#{activity.id}")
278
279 assert html_response(conn, 200) =~ "testing a thing!"
280 end
281
282 test "returns 404 for local public activity with `restrict_unauthenticated/activities/local` setting",
283 %{conn: conn, user: user} do
284 clear_config([:restrict_unauthenticated, :activities, :local], true)
285
286 {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"})
287
288 conn
289 |> get("/notice/#{activity.id}")
290 |> html_response(404)
291 end
292 end
293 end