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