total rebase
[anni] / test / pleroma / web / mastodon_api / views / account_view_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 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, async: false
7
8   alias Pleroma.UnstubbedConfigMock, as: ConfigMock
9   alias Pleroma.User
10   alias Pleroma.UserRelationship
11   alias Pleroma.Web.CommonAPI
12   alias Pleroma.Web.MastodonAPI.AccountView
13
14   import Mox
15   import Pleroma.Factory
16   import Tesla.Mock
17
18   setup do
19     mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
20     :ok
21   end
22
23   test "Represent a user account" do
24     background_image = %{
25       "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
26     }
27
28     user =
29       insert(:user, %{
30         follower_count: 3,
31         note_count: 5,
32         background: background_image,
33         nickname: "shp@shitposter.club",
34         name: ":karjalanpiirakka: shp",
35         bio:
36           "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
37         inserted_at: ~N[2017-08-15 15:47:06.597036],
38         emoji: %{"karjalanpiirakka" => "/file.png"},
39         raw_bio: "valid html. a\nb\nc\nd\nf '&<>\"",
40         also_known_as: ["https://shitposter.zone/users/shp"],
41         last_status_at: NaiveDateTime.utc_now()
42       })
43
44     expected = %{
45       id: to_string(user.id),
46       username: "shp",
47       acct: user.nickname,
48       display_name: user.name,
49       locked: false,
50       created_at: "2017-08-15T15:47:06.000Z",
51       followers_count: 3,
52       following_count: 0,
53       statuses_count: 5,
54       note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f &#39;&amp;&lt;&gt;&quot;",
55       url: user.ap_id,
56       avatar: "http://localhost:4001/images/avi.png",
57       avatar_static: "http://localhost:4001/images/avi.png",
58       header: "http://localhost:4001/images/banner.png",
59       header_static: "http://localhost:4001/images/banner.png",
60       emojis: [
61         %{
62           static_url: "/file.png",
63           url: "/file.png",
64           shortcode: "karjalanpiirakka",
65           visible_in_picker: false
66         }
67       ],
68       fields: [],
69       bot: false,
70       source: %{
71         note: "valid html. a\nb\nc\nd\nf '&<>\"",
72         sensitive: false,
73         pleroma: %{
74           actor_type: "Person",
75           discoverable: true
76         },
77         fields: []
78       },
79       fqn: "shp@shitposter.club",
80       last_status_at: user.last_status_at |> NaiveDateTime.to_date() |> Date.to_iso8601(),
81       pleroma: %{
82         ap_id: user.ap_id,
83         also_known_as: ["https://shitposter.zone/users/shp"],
84         background_image: "https://example.com/images/asuka_hospital.png",
85         favicon: nil,
86         is_confirmed: true,
87         tags: [],
88         is_admin: false,
89         is_moderator: false,
90         privileges: [],
91         is_suggested: false,
92         hide_favorites: true,
93         hide_followers: false,
94         hide_follows: false,
95         hide_followers_count: false,
96         hide_follows_count: false,
97         relationship: %{},
98         skip_thread_containment: false,
99         accepts_chat_messages: nil
100       }
101     }
102
103     assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
104   end
105
106   describe "roles and privileges" do
107     setup do
108       clear_config([:instance, :moderator_privileges], [:cofe, :only_moderator])
109       clear_config([:instance, :admin_privileges], [:cofe, :only_admin])
110
111       %{
112         user: insert(:user),
113         moderator: insert(:user, is_moderator: true),
114         admin: insert(:user, is_admin: true),
115         moderator_admin: insert(:user, is_moderator: true, is_admin: true),
116         user_no_show_roles: insert(:user, show_role: false),
117         moderator_admin_no_show_roles:
118           insert(:user, is_moderator: true, is_admin: true, show_role: false)
119       }
120     end
121
122     test "shows roles and privileges when show_role: true", %{
123       user: user,
124       moderator: moderator,
125       admin: admin,
126       moderator_admin: moderator_admin,
127       user_no_show_roles: user_no_show_roles,
128       moderator_admin_no_show_roles: moderator_admin_no_show_roles
129     } do
130       assert %{pleroma: %{is_moderator: false, is_admin: false}} =
131                AccountView.render("show.json", %{user: user, skip_visibility_check: true})
132
133       assert [] ==
134                AccountView.render("show.json", %{user: user, skip_visibility_check: true})[
135                  :pleroma
136                ][:privileges]
137                |> Enum.sort()
138
139       assert %{pleroma: %{is_moderator: true, is_admin: false}} =
140                AccountView.render("show.json", %{user: moderator, skip_visibility_check: true})
141
142       assert [:cofe, :only_moderator] ==
143                AccountView.render("show.json", %{user: moderator, skip_visibility_check: true})[
144                  :pleroma
145                ][:privileges]
146                |> Enum.sort()
147
148       assert %{pleroma: %{is_moderator: false, is_admin: true}} =
149                AccountView.render("show.json", %{user: admin, skip_visibility_check: true})
150
151       assert [:cofe, :only_admin] ==
152                AccountView.render("show.json", %{user: admin, skip_visibility_check: true})[
153                  :pleroma
154                ][:privileges]
155                |> Enum.sort()
156
157       assert %{pleroma: %{is_moderator: true, is_admin: true}} =
158                AccountView.render("show.json", %{
159                  user: moderator_admin,
160                  skip_visibility_check: true
161                })
162
163       assert [:cofe, :only_admin, :only_moderator] ==
164                AccountView.render("show.json", %{
165                  user: moderator_admin,
166                  skip_visibility_check: true
167                })[:pleroma][:privileges]
168                |> Enum.sort()
169
170       refute match?(
171                %{pleroma: %{is_moderator: _}},
172                AccountView.render("show.json", %{
173                  user: user_no_show_roles,
174                  skip_visibility_check: true
175                })
176              )
177
178       refute match?(
179                %{pleroma: %{is_admin: _}},
180                AccountView.render("show.json", %{
181                  user: user_no_show_roles,
182                  skip_visibility_check: true
183                })
184              )
185
186       refute match?(
187                %{pleroma: %{privileges: _}},
188                AccountView.render("show.json", %{
189                  user: user_no_show_roles,
190                  skip_visibility_check: true
191                })
192              )
193
194       refute match?(
195                %{pleroma: %{is_moderator: _}},
196                AccountView.render("show.json", %{
197                  user: moderator_admin_no_show_roles,
198                  skip_visibility_check: true
199                })
200              )
201
202       refute match?(
203                %{pleroma: %{is_admin: _}},
204                AccountView.render("show.json", %{
205                  user: moderator_admin_no_show_roles,
206                  skip_visibility_check: true
207                })
208              )
209
210       refute match?(
211                %{pleroma: %{privileges: _}},
212                AccountView.render("show.json", %{
213                  user: moderator_admin_no_show_roles,
214                  skip_visibility_check: true
215                })
216              )
217     end
218
219     test "shows roles and privileges when viewing own account, even when show_role: false", %{
220       user_no_show_roles: user_no_show_roles,
221       moderator_admin_no_show_roles: moderator_admin_no_show_roles
222     } do
223       assert %{pleroma: %{is_moderator: false, is_admin: false, privileges: []}} =
224                AccountView.render("show.json", %{
225                  user: user_no_show_roles,
226                  skip_visibility_check: true,
227                  for: user_no_show_roles
228                })
229
230       assert %{
231                pleroma: %{
232                  is_moderator: true,
233                  is_admin: true,
234                  privileges: privileges
235                }
236              } =
237                AccountView.render("show.json", %{
238                  user: moderator_admin_no_show_roles,
239                  skip_visibility_check: true,
240                  for: moderator_admin_no_show_roles
241                })
242
243       assert [:cofe, :only_admin, :only_moderator] == privileges |> Enum.sort()
244     end
245   end
246
247   describe "favicon" do
248     setup do
249       [user: insert(:user)]
250     end
251
252     test "is parsed when :instance_favicons is enabled", %{user: user} do
253       clear_config([:instances_favicons, :enabled], true)
254
255       assert %{
256                pleroma: %{
257                  favicon:
258                    "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png"
259                }
260              } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
261     end
262
263     test "is nil when :instances_favicons is disabled", %{user: user} do
264       assert %{pleroma: %{favicon: nil}} =
265                AccountView.render("show.json", %{user: user, skip_visibility_check: true})
266     end
267   end
268
269   test "Represent the user account for the account owner" do
270     user = insert(:user)
271
272     notification_settings = %{
273       block_from_strangers: false,
274       hide_notification_contents: false
275     }
276
277     privacy = user.default_scope
278
279     assert %{
280              pleroma: %{notification_settings: ^notification_settings, allow_following_move: true},
281              source: %{privacy: ^privacy}
282            } = AccountView.render("show.json", %{user: user, for: user})
283   end
284
285   test "Represent a Service(bot) account" do
286     user =
287       insert(:user, %{
288         follower_count: 3,
289         note_count: 5,
290         actor_type: "Service",
291         nickname: "shp@shitposter.club",
292         inserted_at: ~N[2017-08-15 15:47:06.597036]
293       })
294
295     expected = %{
296       id: to_string(user.id),
297       username: "shp",
298       acct: user.nickname,
299       display_name: user.name,
300       locked: false,
301       created_at: "2017-08-15T15:47:06.000Z",
302       followers_count: 3,
303       following_count: 0,
304       statuses_count: 5,
305       note: user.bio,
306       url: user.ap_id,
307       avatar: "http://localhost:4001/images/avi.png",
308       avatar_static: "http://localhost:4001/images/avi.png",
309       header: "http://localhost:4001/images/banner.png",
310       header_static: "http://localhost:4001/images/banner.png",
311       emojis: [],
312       fields: [],
313       bot: true,
314       source: %{
315         note: user.bio,
316         sensitive: false,
317         pleroma: %{
318           actor_type: "Service",
319           discoverable: true
320         },
321         fields: []
322       },
323       fqn: "shp@shitposter.club",
324       last_status_at: nil,
325       pleroma: %{
326         ap_id: user.ap_id,
327         also_known_as: [],
328         background_image: nil,
329         favicon: nil,
330         is_confirmed: true,
331         tags: [],
332         is_admin: false,
333         is_moderator: false,
334         privileges: [],
335         is_suggested: false,
336         hide_favorites: true,
337         hide_followers: false,
338         hide_follows: false,
339         hide_followers_count: false,
340         hide_follows_count: false,
341         relationship: %{},
342         skip_thread_containment: false,
343         accepts_chat_messages: nil
344       }
345     }
346
347     assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
348   end
349
350   test "Represent a Funkwhale channel" do
351     {:ok, user} =
352       User.get_or_fetch_by_ap_id(
353         "https://channels.tests.funkwhale.audio/federation/actors/compositions"
354       )
355
356     assert represented =
357              AccountView.render("show.json", %{user: user, skip_visibility_check: true})
358
359     assert represented.acct == "compositions@channels.tests.funkwhale.audio"
360     assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions"
361   end
362
363   test "Represent a deactivated user for a privileged user" do
364     clear_config([:instance, :moderator_privileges], [:users_manage_activation_state])
365
366     admin = insert(:user, is_moderator: true)
367     deactivated_user = insert(:user, is_active: false)
368     represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
369     assert represented[:pleroma][:deactivated] == true
370   end
371
372   test "Represent a smaller mention" do
373     user = insert(:user)
374
375     expected = %{
376       id: to_string(user.id),
377       acct: user.nickname,
378       username: user.nickname,
379       url: user.ap_id
380     }
381
382     assert expected == AccountView.render("mention.json", %{user: user})
383   end
384
385   test "demands :for or :skip_visibility_check option for account rendering" do
386     clear_config([:restrict_unauthenticated, :profiles, :local], false)
387
388     user = insert(:user)
389     user_id = user.id
390
391     assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: nil})
392     assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: user})
393
394     assert %{id: ^user_id} =
395              AccountView.render("show.json", %{user: user, skip_visibility_check: true})
396
397     assert_raise RuntimeError, ~r/:skip_visibility_check or :for option is required/, fn ->
398       AccountView.render("show.json", %{user: user})
399     end
400   end
401
402   describe "relationship" do
403     defp test_relationship_rendering(user, other_user, expected_result) do
404       opts = %{user: user, target: other_user, relationships: nil}
405       assert expected_result == AccountView.render("relationship.json", opts)
406
407       relationships_opt = UserRelationship.view_relationships_option(user, [other_user])
408       opts = Map.put(opts, :relationships, relationships_opt)
409       assert expected_result == AccountView.render("relationship.json", opts)
410
411       assert [expected_result] ==
412                AccountView.render("relationships.json", %{user: user, targets: [other_user]})
413     end
414
415     @blank_response %{
416       following: false,
417       followed_by: false,
418       blocking: false,
419       blocked_by: false,
420       muting: false,
421       muting_notifications: false,
422       subscribing: false,
423       notifying: false,
424       requested: false,
425       domain_blocking: false,
426       showing_reblogs: true,
427       endorsed: false,
428       note: ""
429     }
430
431     test "represent a relationship for the following and followed user" do
432       user = insert(:user)
433       other_user = insert(:user)
434
435       {:ok, user, other_user} = User.follow(user, other_user)
436       {:ok, other_user, user} = User.follow(other_user, user)
437       {:ok, _subscription} = User.subscribe(user, other_user)
438       {:ok, _user_relationships} = User.mute(user, other_user, %{notifications: true})
439       {:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, other_user)
440
441       expected =
442         Map.merge(
443           @blank_response,
444           %{
445             following: true,
446             followed_by: true,
447             muting: true,
448             muting_notifications: true,
449             subscribing: true,
450             notifying: true,
451             showing_reblogs: false,
452             id: to_string(other_user.id)
453           }
454         )
455
456       test_relationship_rendering(user, other_user, expected)
457     end
458
459     test "represent a relationship for the blocking and blocked user" do
460       user = insert(:user)
461       other_user = insert(:user)
462
463       {:ok, user, other_user} = User.follow(user, other_user)
464       {:ok, _subscription} = User.subscribe(user, other_user)
465       {:ok, _user_relationship} = User.block(user, other_user)
466       {:ok, _user_relationship} = User.block(other_user, user)
467
468       expected =
469         Map.merge(
470           @blank_response,
471           %{following: false, blocking: true, blocked_by: true, id: to_string(other_user.id)}
472         )
473
474       test_relationship_rendering(user, other_user, expected)
475     end
476
477     test "represent a relationship for the user blocking a domain" do
478       user = insert(:user)
479       other_user = insert(:user, ap_id: "https://bad.site/users/other_user")
480
481       {:ok, user} = User.block_domain(user, "bad.site")
482
483       expected =
484         Map.merge(
485           @blank_response,
486           %{domain_blocking: true, blocking: false, id: to_string(other_user.id)}
487         )
488
489       test_relationship_rendering(user, other_user, expected)
490     end
491
492     test "represent a relationship for the user with a pending follow request" do
493       user = insert(:user)
494       other_user = insert(:user, is_locked: true)
495
496       {:ok, user, other_user, _} = CommonAPI.follow(user, other_user)
497       user = User.get_cached_by_id(user.id)
498       other_user = User.get_cached_by_id(other_user.id)
499
500       expected =
501         Map.merge(
502           @blank_response,
503           %{requested: true, following: false, id: to_string(other_user.id)}
504         )
505
506       test_relationship_rendering(user, other_user, expected)
507     end
508   end
509
510   test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
511     user = insert(:user, pleroma_settings_store: %{fe: "test"})
512
513     result =
514       AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
515
516     assert result.pleroma.settings_store == %{:fe => "test"}
517
518     result = AccountView.render("show.json", %{user: user, for: nil, with_pleroma_settings: true})
519     assert result.pleroma[:settings_store] == nil
520
521     result = AccountView.render("show.json", %{user: user, for: user})
522     assert result.pleroma[:settings_store] == nil
523   end
524
525   test "doesn't sanitize display names" do
526     user = insert(:user, name: "<marquee> username </marquee>")
527     result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
528     assert result.display_name == "<marquee> username </marquee>"
529   end
530
531   test "never display nil user follow counts" do
532     user = insert(:user, following_count: 0, follower_count: 0)
533     result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
534
535     assert result.following_count == 0
536     assert result.followers_count == 0
537   end
538
539   describe "hiding follows/following" do
540     test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do
541       user =
542         insert(:user, %{
543           hide_followers: true,
544           hide_followers_count: true,
545           hide_follows: true,
546           hide_follows_count: true
547         })
548
549       other_user = insert(:user)
550       {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
551       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
552
553       assert %{
554                followers_count: 0,
555                following_count: 0,
556                pleroma: %{hide_follows_count: true, hide_followers_count: true}
557              } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
558     end
559
560     test "shows when follows/followers are hidden" do
561       user = insert(:user, hide_followers: true, hide_follows: true)
562       other_user = insert(:user)
563       {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
564       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
565
566       assert %{
567                followers_count: 1,
568                following_count: 1,
569                pleroma: %{hide_follows: true, hide_followers: true}
570              } = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
571     end
572
573     test "shows actual follower/following count to the account owner" do
574       user = insert(:user, hide_followers: true, hide_follows: true)
575       other_user = insert(:user)
576       {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
577
578       assert User.following?(user, other_user)
579       assert Pleroma.FollowingRelationship.follower_count(other_user) == 1
580       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
581
582       assert %{
583                followers_count: 1,
584                following_count: 1
585              } = AccountView.render("show.json", %{user: user, for: user})
586     end
587
588     test "shows unread_conversation_count only to the account owner" do
589       user = insert(:user)
590       other_user = insert(:user)
591
592       {:ok, _activity} =
593         CommonAPI.post(other_user, %{
594           status: "Hey @#{user.nickname}.",
595           visibility: "direct"
596         })
597
598       user = User.get_cached_by_ap_id(user.ap_id)
599
600       assert AccountView.render("show.json", %{user: user, for: other_user})[:pleroma][
601                :unread_conversation_count
602              ] == nil
603
604       assert AccountView.render("show.json", %{user: user, for: user})[:pleroma][
605                :unread_conversation_count
606              ] == 1
607     end
608
609     test "shows unread_count only to the account owner" do
610       user = insert(:user)
611       insert_list(7, :notification, user: user, activity: insert(:note_activity))
612       other_user = insert(:user)
613
614       user = User.get_cached_by_ap_id(user.ap_id)
615
616       assert AccountView.render(
617                "show.json",
618                %{user: user, for: other_user}
619              )[:pleroma][:unread_notifications_count] == nil
620
621       assert AccountView.render(
622                "show.json",
623                %{user: user, for: user}
624              )[:pleroma][:unread_notifications_count] == 7
625     end
626
627     test "shows email only to the account owner" do
628       user = insert(:user)
629       other_user = insert(:user)
630
631       user = User.get_cached_by_ap_id(user.ap_id)
632
633       assert AccountView.render(
634                "show.json",
635                %{user: user, for: other_user}
636              )[:pleroma][:email] == nil
637
638       assert AccountView.render(
639                "show.json",
640                %{user: user, for: user}
641              )[:pleroma][:email] == user.email
642     end
643   end
644
645   describe "hiding birthday" do
646     test "doesn't show birthday if hidden" do
647       user =
648         insert(:user, %{
649           birthday: "2001-02-12",
650           show_birthday: false
651         })
652
653       other_user = insert(:user)
654
655       user = User.get_cached_by_ap_id(user.ap_id)
656
657       assert AccountView.render(
658                "show.json",
659                %{user: user, for: other_user}
660              )[:birthday] == nil
661     end
662
663     test "shows hidden birthday to the account owner" do
664       user =
665         insert(:user, %{
666           birthday: "2001-02-12",
667           show_birthday: false
668         })
669
670       user = User.get_cached_by_ap_id(user.ap_id)
671
672       assert AccountView.render(
673                "show.json",
674                %{user: user, for: user}
675              )[:birthday] == nil
676     end
677   end
678
679   describe "follow requests counter" do
680     test "shows zero when no follow requests are pending" do
681       user = insert(:user)
682
683       assert %{follow_requests_count: 0} =
684                AccountView.render("show.json", %{user: user, for: user})
685
686       other_user = insert(:user)
687       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
688
689       assert %{follow_requests_count: 0} =
690                AccountView.render("show.json", %{user: user, for: user})
691     end
692
693     test "shows non-zero when follow requests are pending" do
694       user = insert(:user, is_locked: true)
695
696       assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
697
698       other_user = insert(:user)
699       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
700
701       assert %{locked: true, follow_requests_count: 1} =
702                AccountView.render("show.json", %{user: user, for: user})
703     end
704
705     test "decreases when accepting a follow request" do
706       user = insert(:user, is_locked: true)
707
708       assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
709
710       other_user = insert(:user)
711       {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
712
713       assert %{locked: true, follow_requests_count: 1} =
714                AccountView.render("show.json", %{user: user, for: user})
715
716       {:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
717
718       assert %{locked: true, follow_requests_count: 0} =
719                AccountView.render("show.json", %{user: user, for: user})
720     end
721
722     test "decreases when rejecting a follow request" do
723       user = insert(:user, is_locked: true)
724
725       assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
726
727       other_user = insert(:user)
728       {:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
729
730       assert %{locked: true, follow_requests_count: 1} =
731                AccountView.render("show.json", %{user: user, for: user})
732
733       {:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
734
735       assert %{locked: true, follow_requests_count: 0} =
736                AccountView.render("show.json", %{user: user, for: user})
737     end
738
739     test "shows non-zero when historical unapproved requests are present" do
740       user = insert(:user, is_locked: true)
741
742       assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
743
744       other_user = insert(:user)
745       {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
746
747       {:ok, user} = User.update_and_set_cache(user, %{is_locked: false})
748
749       assert %{locked: false, follow_requests_count: 1} =
750                AccountView.render("show.json", %{user: user, for: user})
751     end
752   end
753
754   test "uses mediaproxy urls when it's enabled (regardless of media preview proxy state)" do
755     clear_config([:media_proxy, :enabled], true)
756     clear_config([:media_preview_proxy, :enabled])
757
758     ConfigMock
759     |> stub_with(Pleroma.Test.StaticConfig)
760
761     user =
762       insert(:user,
763         avatar: %{"url" => [%{"href" => "https://evil.website/avatar.png"}]},
764         banner: %{"url" => [%{"href" => "https://evil.website/banner.png"}]},
765         emoji: %{"joker_smile" => "https://evil.website/society.png"}
766       )
767
768     Enum.each([true, false], fn media_preview_enabled ->
769       clear_config([:media_preview_proxy, :enabled], media_preview_enabled)
770
771       AccountView.render("show.json", %{user: user, skip_visibility_check: true})
772       |> Enum.all?(fn
773         {key, url} when key in [:avatar, :avatar_static, :header, :header_static] ->
774           String.starts_with?(url, Pleroma.Web.Endpoint.url())
775
776         {:emojis, emojis} ->
777           Enum.all?(emojis, fn %{url: url, static_url: static_url} ->
778             String.starts_with?(url, Pleroma.Web.Endpoint.url()) &&
779               String.starts_with?(static_url, Pleroma.Web.Endpoint.url())
780           end)
781
782         _ ->
783           true
784       end)
785       |> assert()
786     end)
787   end
788
789   test "renders mute expiration date" do
790     user = insert(:user)
791     other_user = insert(:user)
792
793     {:ok, _user_relationships} =
794       User.mute(user, other_user, %{notifications: true, duration: 24 * 60 * 60})
795
796     %{
797       mute_expires_at: mute_expires_at
798     } = AccountView.render("show.json", %{user: other_user, for: user, mutes: true})
799
800     assert DateTime.diff(
801              mute_expires_at,
802              DateTime.utc_now() |> DateTime.add(24 * 60 * 60)
803            ) in -3..3
804   end
805 end