Merge branch 'release/2.0.2' into 'stable'
[akkoma] / test / web / mastodon_api / views / account_view_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
6 use Pleroma.DataCase
7
8 alias Pleroma.User
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Web.MastodonAPI.AccountView
11
12 import Pleroma.Factory
13 import Tesla.Mock
14
15 setup do
16 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
17 :ok
18 end
19
20 test "Represent a user account" do
21 source_data = %{
22 "tag" => [
23 %{
24 "type" => "Emoji",
25 "icon" => %{"url" => "/file.png"},
26 "name" => ":karjalanpiirakka:"
27 }
28 ]
29 }
30
31 background_image = %{
32 "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
33 }
34
35 user =
36 insert(:user, %{
37 follower_count: 3,
38 note_count: 5,
39 source_data: source_data,
40 background: background_image,
41 nickname: "shp@shitposter.club",
42 name: ":karjalanpiirakka: shp",
43 bio:
44 "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f",
45 inserted_at: ~N[2017-08-15 15:47:06.597036]
46 })
47
48 expected = %{
49 id: to_string(user.id),
50 username: "shp",
51 acct: user.nickname,
52 display_name: user.name,
53 locked: false,
54 created_at: "2017-08-15T15:47:06.000Z",
55 followers_count: 3,
56 following_count: 0,
57 statuses_count: 5,
58 note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f",
59 url: user.ap_id,
60 avatar: "http://localhost:4001/images/avi.png",
61 avatar_static: "http://localhost:4001/images/avi.png",
62 header: "http://localhost:4001/images/banner.png",
63 header_static: "http://localhost:4001/images/banner.png",
64 emojis: [
65 %{
66 "static_url" => "/file.png",
67 "url" => "/file.png",
68 "shortcode" => "karjalanpiirakka",
69 "visible_in_picker" => false
70 }
71 ],
72 fields: [],
73 bot: false,
74 source: %{
75 note: "valid html. a\nb\nc\nd\nf",
76 sensitive: false,
77 pleroma: %{
78 actor_type: "Person",
79 discoverable: false
80 },
81 fields: []
82 },
83 pleroma: %{
84 background_image: "https://example.com/images/asuka_hospital.png",
85 confirmation_pending: false,
86 tags: [],
87 is_admin: false,
88 is_moderator: false,
89 hide_favorites: true,
90 hide_followers: false,
91 hide_follows: false,
92 hide_followers_count: false,
93 hide_follows_count: false,
94 relationship: %{},
95 skip_thread_containment: false
96 }
97 }
98
99 assert expected == AccountView.render("show.json", %{user: user})
100 end
101
102 test "Represent the user account for the account owner" do
103 user = insert(:user)
104
105 notification_settings = %Pleroma.User.NotificationSetting{}
106 privacy = user.default_scope
107
108 assert %{
109 pleroma: %{notification_settings: ^notification_settings, allow_following_move: true},
110 source: %{privacy: ^privacy}
111 } = AccountView.render("show.json", %{user: user, for: user})
112 end
113
114 test "Represent a Service(bot) account" do
115 user =
116 insert(:user, %{
117 follower_count: 3,
118 note_count: 5,
119 source_data: %{},
120 actor_type: "Service",
121 nickname: "shp@shitposter.club",
122 inserted_at: ~N[2017-08-15 15:47:06.597036]
123 })
124
125 expected = %{
126 id: to_string(user.id),
127 username: "shp",
128 acct: user.nickname,
129 display_name: user.name,
130 locked: false,
131 created_at: "2017-08-15T15:47:06.000Z",
132 followers_count: 3,
133 following_count: 0,
134 statuses_count: 5,
135 note: user.bio,
136 url: user.ap_id,
137 avatar: "http://localhost:4001/images/avi.png",
138 avatar_static: "http://localhost:4001/images/avi.png",
139 header: "http://localhost:4001/images/banner.png",
140 header_static: "http://localhost:4001/images/banner.png",
141 emojis: [],
142 fields: [],
143 bot: true,
144 source: %{
145 note: user.bio,
146 sensitive: false,
147 pleroma: %{
148 actor_type: "Service",
149 discoverable: false
150 },
151 fields: []
152 },
153 pleroma: %{
154 background_image: nil,
155 confirmation_pending: false,
156 tags: [],
157 is_admin: false,
158 is_moderator: false,
159 hide_favorites: true,
160 hide_followers: false,
161 hide_follows: false,
162 hide_followers_count: false,
163 hide_follows_count: false,
164 relationship: %{},
165 skip_thread_containment: false
166 }
167 }
168
169 assert expected == AccountView.render("show.json", %{user: user})
170 end
171
172 test "Represent a Funkwhale channel" do
173 {:ok, user} =
174 User.get_or_fetch_by_ap_id(
175 "https://channels.tests.funkwhale.audio/federation/actors/compositions"
176 )
177
178 assert represented = AccountView.render("show.json", %{user: user})
179 assert represented.acct == "compositions@channels.tests.funkwhale.audio"
180 assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions"
181 end
182
183 test "Represent a deactivated user for an admin" do
184 admin = insert(:user, is_admin: true)
185 deactivated_user = insert(:user, deactivated: true)
186 represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
187 assert represented[:pleroma][:deactivated] == true
188 end
189
190 test "Represent a smaller mention" do
191 user = insert(:user)
192
193 expected = %{
194 id: to_string(user.id),
195 acct: user.nickname,
196 username: user.nickname,
197 url: user.ap_id
198 }
199
200 assert expected == AccountView.render("mention.json", %{user: user})
201 end
202
203 describe "relationship" do
204 test "represent a relationship for the following and followed user" do
205 user = insert(:user)
206 other_user = insert(:user)
207
208 {:ok, user} = User.follow(user, other_user)
209 {:ok, other_user} = User.follow(other_user, user)
210 {:ok, _subscription} = User.subscribe(user, other_user)
211 {:ok, _user_relationships} = User.mute(user, other_user, true)
212 {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, other_user)
213
214 expected = %{
215 id: to_string(other_user.id),
216 following: true,
217 followed_by: true,
218 blocking: false,
219 blocked_by: false,
220 muting: true,
221 muting_notifications: true,
222 subscribing: true,
223 requested: false,
224 domain_blocking: false,
225 showing_reblogs: false,
226 endorsed: false
227 }
228
229 assert expected ==
230 AccountView.render("relationship.json", %{user: user, target: other_user})
231 end
232
233 test "represent a relationship for the blocking and blocked user" do
234 user = insert(:user)
235 other_user = insert(:user)
236
237 {:ok, user} = User.follow(user, other_user)
238 {:ok, _subscription} = User.subscribe(user, other_user)
239 {:ok, _user_relationship} = User.block(user, other_user)
240 {:ok, _user_relationship} = User.block(other_user, user)
241
242 expected = %{
243 id: to_string(other_user.id),
244 following: false,
245 followed_by: false,
246 blocking: true,
247 blocked_by: true,
248 muting: false,
249 muting_notifications: false,
250 subscribing: false,
251 requested: false,
252 domain_blocking: false,
253 showing_reblogs: true,
254 endorsed: false
255 }
256
257 assert expected ==
258 AccountView.render("relationship.json", %{user: user, target: other_user})
259 end
260
261 test "represent a relationship for the user blocking a domain" do
262 user = insert(:user)
263 other_user = insert(:user, ap_id: "https://bad.site/users/other_user")
264
265 {:ok, user} = User.block_domain(user, "bad.site")
266
267 assert %{domain_blocking: true, blocking: false} =
268 AccountView.render("relationship.json", %{user: user, target: other_user})
269 end
270
271 test "represent a relationship for the user with a pending follow request" do
272 user = insert(:user)
273 other_user = insert(:user, locked: true)
274
275 {:ok, user, other_user, _} = CommonAPI.follow(user, other_user)
276 user = User.get_cached_by_id(user.id)
277 other_user = User.get_cached_by_id(other_user.id)
278
279 expected = %{
280 id: to_string(other_user.id),
281 following: false,
282 followed_by: false,
283 blocking: false,
284 blocked_by: false,
285 muting: false,
286 muting_notifications: false,
287 subscribing: false,
288 requested: true,
289 domain_blocking: false,
290 showing_reblogs: true,
291 endorsed: false
292 }
293
294 assert expected ==
295 AccountView.render("relationship.json", %{user: user, target: other_user})
296 end
297 end
298
299 test "represent an embedded relationship" do
300 user =
301 insert(:user, %{
302 follower_count: 0,
303 note_count: 5,
304 source_data: %{},
305 actor_type: "Service",
306 nickname: "shp@shitposter.club",
307 inserted_at: ~N[2017-08-15 15:47:06.597036]
308 })
309
310 other_user = insert(:user)
311 {:ok, other_user} = User.follow(other_user, user)
312 {:ok, _user_relationship} = User.block(other_user, user)
313 {:ok, _} = User.follow(insert(:user), user)
314
315 expected = %{
316 id: to_string(user.id),
317 username: "shp",
318 acct: user.nickname,
319 display_name: user.name,
320 locked: false,
321 created_at: "2017-08-15T15:47:06.000Z",
322 followers_count: 1,
323 following_count: 0,
324 statuses_count: 5,
325 note: user.bio,
326 url: user.ap_id,
327 avatar: "http://localhost:4001/images/avi.png",
328 avatar_static: "http://localhost:4001/images/avi.png",
329 header: "http://localhost:4001/images/banner.png",
330 header_static: "http://localhost:4001/images/banner.png",
331 emojis: [],
332 fields: [],
333 bot: true,
334 source: %{
335 note: user.bio,
336 sensitive: false,
337 pleroma: %{
338 actor_type: "Service",
339 discoverable: false
340 },
341 fields: []
342 },
343 pleroma: %{
344 background_image: nil,
345 confirmation_pending: false,
346 tags: [],
347 is_admin: false,
348 is_moderator: false,
349 hide_favorites: true,
350 hide_followers: false,
351 hide_follows: false,
352 hide_followers_count: false,
353 hide_follows_count: false,
354 relationship: %{
355 id: to_string(user.id),
356 following: false,
357 followed_by: false,
358 blocking: true,
359 blocked_by: false,
360 subscribing: false,
361 muting: false,
362 muting_notifications: false,
363 requested: false,
364 domain_blocking: false,
365 showing_reblogs: true,
366 endorsed: false
367 },
368 skip_thread_containment: false
369 }
370 }
371
372 assert expected ==
373 AccountView.render("show.json", %{user: refresh_record(user), for: other_user})
374 end
375
376 test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
377 user = insert(:user, pleroma_settings_store: %{fe: "test"})
378
379 result =
380 AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
381
382 assert result.pleroma.settings_store == %{:fe => "test"}
383
384 result = AccountView.render("show.json", %{user: user, with_pleroma_settings: true})
385 assert result.pleroma[:settings_store] == nil
386
387 result = AccountView.render("show.json", %{user: user, for: user})
388 assert result.pleroma[:settings_store] == nil
389 end
390
391 test "doesn't sanitize display names" do
392 user = insert(:user, name: "<marquee> username </marquee>")
393 result = AccountView.render("show.json", %{user: user})
394 assert result.display_name == "<marquee> username </marquee>"
395 end
396
397 test "never display nil user follow counts" do
398 user = insert(:user, following_count: 0, follower_count: 0)
399 result = AccountView.render("show.json", %{user: user})
400
401 assert result.following_count == 0
402 assert result.followers_count == 0
403 end
404
405 describe "hiding follows/following" do
406 test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do
407 user =
408 insert(:user, %{
409 hide_followers: true,
410 hide_followers_count: true,
411 hide_follows: true,
412 hide_follows_count: true
413 })
414
415 other_user = insert(:user)
416 {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
417 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
418
419 assert %{
420 followers_count: 0,
421 following_count: 0,
422 pleroma: %{hide_follows_count: true, hide_followers_count: true}
423 } = AccountView.render("show.json", %{user: user})
424 end
425
426 test "shows when follows/followers are hidden" do
427 user = insert(:user, hide_followers: true, hide_follows: true)
428 other_user = insert(:user)
429 {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
430 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
431
432 assert %{
433 followers_count: 1,
434 following_count: 1,
435 pleroma: %{hide_follows: true, hide_followers: true}
436 } = AccountView.render("show.json", %{user: user})
437 end
438
439 test "shows actual follower/following count to the account owner" do
440 user = insert(:user, hide_followers: true, hide_follows: true)
441 other_user = insert(:user)
442 {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
443 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
444
445 assert %{
446 followers_count: 1,
447 following_count: 1
448 } = AccountView.render("show.json", %{user: user, for: user})
449 end
450
451 test "shows unread_conversation_count only to the account owner" do
452 user = insert(:user)
453 other_user = insert(:user)
454
455 {:ok, _activity} =
456 CommonAPI.post(other_user, %{
457 "status" => "Hey @#{user.nickname}.",
458 "visibility" => "direct"
459 })
460
461 user = User.get_cached_by_ap_id(user.ap_id)
462
463 assert AccountView.render("show.json", %{user: user, for: other_user})[:pleroma][
464 :unread_conversation_count
465 ] == nil
466
467 assert AccountView.render("show.json", %{user: user, for: user})[:pleroma][
468 :unread_conversation_count
469 ] == 1
470 end
471 end
472
473 describe "follow requests counter" do
474 test "shows zero when no follow requests are pending" do
475 user = insert(:user)
476
477 assert %{follow_requests_count: 0} =
478 AccountView.render("show.json", %{user: user, for: user})
479
480 other_user = insert(:user)
481 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
482
483 assert %{follow_requests_count: 0} =
484 AccountView.render("show.json", %{user: user, for: user})
485 end
486
487 test "shows non-zero when follow requests are pending" do
488 user = insert(:user, locked: true)
489
490 assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
491
492 other_user = insert(:user)
493 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
494
495 assert %{locked: true, follow_requests_count: 1} =
496 AccountView.render("show.json", %{user: user, for: user})
497 end
498
499 test "decreases when accepting a follow request" do
500 user = insert(:user, locked: true)
501
502 assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
503
504 other_user = insert(:user)
505 {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
506
507 assert %{locked: true, follow_requests_count: 1} =
508 AccountView.render("show.json", %{user: user, for: user})
509
510 {:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
511
512 assert %{locked: true, follow_requests_count: 0} =
513 AccountView.render("show.json", %{user: user, for: user})
514 end
515
516 test "decreases when rejecting a follow request" do
517 user = insert(:user, locked: true)
518
519 assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
520
521 other_user = insert(:user)
522 {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
523
524 assert %{locked: true, follow_requests_count: 1} =
525 AccountView.render("show.json", %{user: user, for: user})
526
527 {:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
528
529 assert %{locked: true, follow_requests_count: 0} =
530 AccountView.render("show.json", %{user: user, for: user})
531 end
532
533 test "shows non-zero when historical unapproved requests are present" do
534 user = insert(:user, locked: true)
535
536 assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
537
538 other_user = insert(:user)
539 {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
540
541 {:ok, user} = User.update_and_set_cache(user, %{locked: false})
542
543 assert %{locked: false, follow_requests_count: 1} =
544 AccountView.render("show.json", %{user: user, for: user})
545 end
546 end
547 end