1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.Notification
13 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.OAuth.App
18 alias Pleroma.Web.OAuth.Token
19 alias Pleroma.Web.Push
21 import ExUnit.CaptureLog
22 import Pleroma.Factory
23 import Swoosh.TestAssertions
26 @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
29 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
33 clear_config([:instance, :public])
34 clear_config([:rich_media, :enabled])
36 test "verify_credentials", %{conn: conn} do
41 |> assign(:user, user)
42 |> get("/api/v1/accounts/verify_credentials")
44 response = json_response(conn, 200)
46 assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
47 assert response["pleroma"]["chat_token"]
48 assert id == to_string(user.id)
51 test "verify_credentials default scope unlisted", %{conn: conn} do
52 user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}})
56 |> assign(:user, user)
57 |> get("/api/v1/accounts/verify_credentials")
59 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
60 assert id == to_string(user.id)
63 test "apps/verify_credentials", %{conn: conn} do
64 token = insert(:oauth_token)
68 |> assign(:user, token.user)
69 |> assign(:token, token)
70 |> get("/api/v1/apps/verify_credentials")
72 app = Repo.preload(token, :app).app
75 "name" => app.client_name,
76 "website" => app.website,
77 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
80 assert expected == json_response(conn, 200)
83 test "user avatar can be set", %{conn: conn} do
85 avatar_image = File.read!("test/fixtures/avatar_data_uri")
89 |> assign(:user, user)
90 |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
92 user = refresh_record(user)
106 assert %{"url" => _} = json_response(conn, 200)
109 test "user avatar can be reset", %{conn: conn} do
114 |> assign(:user, user)
115 |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
117 user = User.get_cached_by_id(user.id)
119 assert user.avatar == nil
121 assert %{"url" => nil} = json_response(conn, 200)
124 test "can set profile banner", %{conn: conn} do
129 |> assign(:user, user)
130 |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
132 user = refresh_record(user)
133 assert user.info.banner["type"] == "Image"
135 assert %{"url" => _} = json_response(conn, 200)
138 test "can reset profile banner", %{conn: conn} do
143 |> assign(:user, user)
144 |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
146 user = refresh_record(user)
147 assert user.info.banner == %{}
149 assert %{"url" => nil} = json_response(conn, 200)
152 test "background image can be set", %{conn: conn} do
157 |> assign(:user, user)
158 |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
160 user = refresh_record(user)
161 assert user.info.background["type"] == "Image"
162 assert %{"url" => _} = json_response(conn, 200)
165 test "background image can be reset", %{conn: conn} do
170 |> assign(:user, user)
171 |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
173 user = refresh_record(user)
174 assert user.info.background == %{}
175 assert %{"url" => nil} = json_response(conn, 200)
178 test "creates an oauth app", %{conn: conn} do
180 app_attrs = build(:oauth_app)
184 |> assign(:user, user)
185 |> post("/api/v1/apps", %{
186 client_name: app_attrs.client_name,
187 redirect_uris: app_attrs.redirect_uris
190 [app] = Repo.all(App)
193 "name" => app.client_name,
194 "website" => app.website,
195 "client_id" => app.client_id,
196 "client_secret" => app.client_secret,
197 "id" => app.id |> to_string(),
198 "redirect_uri" => app.redirect_uris,
199 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
202 assert expected == json_response(conn, 200)
205 describe "user timelines" do
206 test "gets a users statuses", %{conn: conn} do
207 user_one = insert(:user)
208 user_two = insert(:user)
209 user_three = insert(:user)
211 {:ok, user_three} = User.follow(user_three, user_one)
213 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
215 {:ok, direct_activity} =
216 CommonAPI.post(user_one, %{
217 "status" => "Hi, @#{user_two.nickname}.",
218 "visibility" => "direct"
221 {:ok, private_activity} =
222 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
226 |> get("/api/v1/accounts/#{user_one.id}/statuses")
228 assert [%{"id" => id}] = json_response(resp, 200)
229 assert id == to_string(activity.id)
233 |> assign(:user, user_two)
234 |> get("/api/v1/accounts/#{user_one.id}/statuses")
236 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
237 assert id_one == to_string(direct_activity.id)
238 assert id_two == to_string(activity.id)
242 |> assign(:user, user_three)
243 |> get("/api/v1/accounts/#{user_one.id}/statuses")
245 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
246 assert id_one == to_string(private_activity.id)
247 assert id_two == to_string(activity.id)
250 test "unimplemented pinned statuses feature", %{conn: conn} do
251 note = insert(:note_activity)
252 user = User.get_cached_by_ap_id(note.data["actor"])
256 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
258 assert json_response(conn, 200) == []
261 test "gets an users media", %{conn: conn} do
262 note = insert(:note_activity)
263 user = User.get_cached_by_ap_id(note.data["actor"])
266 content_type: "image/jpg",
267 path: Path.absname("test/fixtures/image.jpg"),
268 filename: "an_image.jpg"
271 {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
273 {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
277 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
279 assert [%{"id" => id}] = json_response(conn, 200)
280 assert id == to_string(image_post.id)
284 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
286 assert [%{"id" => id}] = json_response(conn, 200)
287 assert id == to_string(image_post.id)
290 test "gets a user's statuses without reblogs", %{conn: conn} do
292 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
293 {:ok, _, _} = CommonAPI.repeat(post.id, user)
297 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
299 assert [%{"id" => id}] = json_response(conn, 200)
300 assert id == to_string(post.id)
304 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
306 assert [%{"id" => id}] = json_response(conn, 200)
307 assert id == to_string(post.id)
310 test "filters user's statuses by a hashtag", %{conn: conn} do
312 {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
313 {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
317 |> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
319 assert [%{"id" => id}] = json_response(conn, 200)
320 assert id == to_string(post.id)
324 describe "user relationships" do
325 test "returns the relationships for the current user", %{conn: conn} do
327 other_user = insert(:user)
328 {:ok, user} = User.follow(user, other_user)
332 |> assign(:user, user)
333 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
335 assert [relationship] = json_response(conn, 200)
337 assert to_string(other_user.id) == relationship["id"]
340 test "returns an empty list on a bad request", %{conn: conn} do
345 |> assign(:user, user)
346 |> get("/api/v1/accounts/relationships", %{})
348 assert [] = json_response(conn, 200)
352 describe "media upload" do
358 |> assign(:user, user)
360 image = %Plug.Upload{
361 content_type: "image/jpg",
362 path: Path.absname("test/fixtures/image.jpg"),
363 filename: "an_image.jpg"
366 [conn: conn, image: image]
369 clear_config([:media_proxy])
370 clear_config([Pleroma.Upload])
372 test "returns uploaded image", %{conn: conn, image: image} do
373 desc = "Description of the image"
377 |> post("/api/v1/media", %{"file" => image, "description" => desc})
378 |> json_response(:ok)
380 assert media["type"] == "image"
381 assert media["description"] == desc
384 object = Repo.get(Object, media["id"])
385 assert object.data["actor"] == User.ap_id(conn.assigns[:user])
389 describe "locked accounts" do
390 test "verify_credentials", %{conn: conn} do
391 user = insert(:user, %{info: %User.Info{default_scope: "private"}})
395 |> assign(:user, user)
396 |> get("/api/v1/accounts/verify_credentials")
398 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
399 assert id == to_string(user.id)
403 describe "account fetching" do
404 test "works by id" do
409 |> get("/api/v1/accounts/#{user.id}")
411 assert %{"id" => id} = json_response(conn, 200)
412 assert id == to_string(user.id)
416 |> get("/api/v1/accounts/-1")
418 assert %{"error" => "Can't find user"} = json_response(conn, 404)
421 test "works by nickname" do
426 |> get("/api/v1/accounts/#{user.nickname}")
428 assert %{"id" => id} = json_response(conn, 200)
432 test "works by nickname for remote users" do
433 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
434 Pleroma.Config.put([:instance, :limit_to_local_content], false)
435 user = insert(:user, nickname: "user@example.com", local: false)
439 |> get("/api/v1/accounts/#{user.nickname}")
441 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
442 assert %{"id" => id} = json_response(conn, 200)
446 test "respects limit_to_local_content == :all for remote user nicknames" do
447 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
448 Pleroma.Config.put([:instance, :limit_to_local_content], :all)
450 user = insert(:user, nickname: "user@example.com", local: false)
454 |> get("/api/v1/accounts/#{user.nickname}")
456 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
457 assert json_response(conn, 404)
460 test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
461 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
462 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
464 user = insert(:user, nickname: "user@example.com", local: false)
465 reading_user = insert(:user)
469 |> get("/api/v1/accounts/#{user.nickname}")
471 assert json_response(conn, 404)
475 |> assign(:user, reading_user)
476 |> get("/api/v1/accounts/#{user.nickname}")
478 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
479 assert %{"id" => id} = json_response(conn, 200)
484 describe "/api/v1/pleroma/mascot" do
485 test "mascot upload", %{conn: conn} do
488 non_image_file = %Plug.Upload{
489 content_type: "audio/mpeg",
490 path: Path.absname("test/fixtures/sound.mp3"),
491 filename: "sound.mp3"
496 |> assign(:user, user)
497 |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
499 assert json_response(conn, 415)
502 content_type: "image/jpg",
503 path: Path.absname("test/fixtures/image.jpg"),
504 filename: "an_image.jpg"
509 |> assign(:user, user)
510 |> put("/api/v1/pleroma/mascot", %{"file" => file})
512 assert %{"id" => _, "type" => image} = json_response(conn, 200)
515 test "mascot retrieving", %{conn: conn} do
517 # When user hasn't set a mascot, we should just get pleroma tan back
520 |> assign(:user, user)
521 |> get("/api/v1/pleroma/mascot")
523 assert %{"url" => url} = json_response(conn, 200)
524 assert url =~ "pleroma-fox-tan-smol"
526 # When a user sets their mascot, we should get that back
528 content_type: "image/jpg",
529 path: Path.absname("test/fixtures/image.jpg"),
530 filename: "an_image.jpg"
535 |> assign(:user, user)
536 |> put("/api/v1/pleroma/mascot", %{"file" => file})
538 assert json_response(conn, 200)
540 user = User.get_cached_by_id(user.id)
544 |> assign(:user, user)
545 |> get("/api/v1/pleroma/mascot")
547 assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
548 assert url =~ "an_image"
552 test "getting followers", %{conn: conn} do
554 other_user = insert(:user)
555 {:ok, user} = User.follow(user, other_user)
559 |> get("/api/v1/accounts/#{other_user.id}/followers")
561 assert [%{"id" => id}] = json_response(conn, 200)
562 assert id == to_string(user.id)
565 test "getting followers, hide_followers", %{conn: conn} do
567 other_user = insert(:user, %{info: %{hide_followers: true}})
568 {:ok, _user} = User.follow(user, other_user)
572 |> get("/api/v1/accounts/#{other_user.id}/followers")
574 assert [] == json_response(conn, 200)
577 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
579 other_user = insert(:user, %{info: %{hide_followers: true}})
580 {:ok, _user} = User.follow(user, other_user)
584 |> assign(:user, other_user)
585 |> get("/api/v1/accounts/#{other_user.id}/followers")
587 refute [] == json_response(conn, 200)
590 test "getting followers, pagination", %{conn: conn} do
592 follower1 = insert(:user)
593 follower2 = insert(:user)
594 follower3 = insert(:user)
595 {:ok, _} = User.follow(follower1, user)
596 {:ok, _} = User.follow(follower2, user)
597 {:ok, _} = User.follow(follower3, user)
601 |> assign(:user, user)
605 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
607 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
608 assert id3 == follower3.id
609 assert id2 == follower2.id
613 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
615 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
616 assert id2 == follower2.id
617 assert id1 == follower1.id
621 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
623 assert [%{"id" => id2}] = json_response(res_conn, 200)
624 assert id2 == follower2.id
626 assert [link_header] = get_resp_header(res_conn, "link")
627 assert link_header =~ ~r/min_id=#{follower2.id}/
628 assert link_header =~ ~r/max_id=#{follower2.id}/
631 test "getting following", %{conn: conn} do
633 other_user = insert(:user)
634 {:ok, user} = User.follow(user, other_user)
638 |> get("/api/v1/accounts/#{user.id}/following")
640 assert [%{"id" => id}] = json_response(conn, 200)
641 assert id == to_string(other_user.id)
644 test "getting following, hide_follows", %{conn: conn} do
645 user = insert(:user, %{info: %{hide_follows: true}})
646 other_user = insert(:user)
647 {:ok, user} = User.follow(user, other_user)
651 |> get("/api/v1/accounts/#{user.id}/following")
653 assert [] == json_response(conn, 200)
656 test "getting following, hide_follows, same user requesting", %{conn: conn} do
657 user = insert(:user, %{info: %{hide_follows: true}})
658 other_user = insert(:user)
659 {:ok, user} = User.follow(user, other_user)
663 |> assign(:user, user)
664 |> get("/api/v1/accounts/#{user.id}/following")
666 refute [] == json_response(conn, 200)
669 test "getting following, pagination", %{conn: conn} do
671 following1 = insert(:user)
672 following2 = insert(:user)
673 following3 = insert(:user)
674 {:ok, _} = User.follow(user, following1)
675 {:ok, _} = User.follow(user, following2)
676 {:ok, _} = User.follow(user, following3)
680 |> assign(:user, user)
684 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
686 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
687 assert id3 == following3.id
688 assert id2 == following2.id
692 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
694 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
695 assert id2 == following2.id
696 assert id1 == following1.id
700 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
702 assert [%{"id" => id2}] = json_response(res_conn, 200)
703 assert id2 == following2.id
705 assert [link_header] = get_resp_header(res_conn, "link")
706 assert link_header =~ ~r/min_id=#{following2.id}/
707 assert link_header =~ ~r/max_id=#{following2.id}/
710 test "following / unfollowing a user", %{conn: conn} do
712 other_user = insert(:user)
716 |> assign(:user, user)
717 |> post("/api/v1/accounts/#{other_user.id}/follow")
719 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
721 user = User.get_cached_by_id(user.id)
725 |> assign(:user, user)
726 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
728 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
730 user = User.get_cached_by_id(user.id)
734 |> assign(:user, user)
735 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
737 assert %{"id" => id} = json_response(conn, 200)
738 assert id == to_string(other_user.id)
741 test "following without reblogs" do
742 follower = insert(:user)
743 followed = insert(:user)
744 other_user = insert(:user)
748 |> assign(:user, follower)
749 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
751 assert %{"showing_reblogs" => false} = json_response(conn, 200)
753 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
754 {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
758 |> assign(:user, User.get_cached_by_id(follower.id))
759 |> get("/api/v1/timelines/home")
761 assert [] == json_response(conn, 200)
765 |> assign(:user, follower)
766 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
768 assert %{"showing_reblogs" => true} = json_response(conn, 200)
772 |> assign(:user, User.get_cached_by_id(follower.id))
773 |> get("/api/v1/timelines/home")
775 expected_activity_id = reblog.id
776 assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
779 test "following / unfollowing errors" do
784 |> assign(:user, user)
787 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
788 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
791 user = User.get_cached_by_id(user.id)
792 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
793 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
795 # self follow via uri
796 user = User.get_cached_by_id(user.id)
797 conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
798 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
800 # follow non existing user
801 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
802 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
804 # follow non existing user via uri
805 conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
806 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
808 # unfollow non existing user
809 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
810 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
813 describe "mute/unmute" do
814 test "with notifications", %{conn: conn} do
816 other_user = insert(:user)
820 |> assign(:user, user)
821 |> post("/api/v1/accounts/#{other_user.id}/mute")
823 response = json_response(conn, 200)
825 assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
826 user = User.get_cached_by_id(user.id)
830 |> assign(:user, user)
831 |> post("/api/v1/accounts/#{other_user.id}/unmute")
833 response = json_response(conn, 200)
834 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
837 test "without notifications", %{conn: conn} do
839 other_user = insert(:user)
843 |> assign(:user, user)
844 |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
846 response = json_response(conn, 200)
848 assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
849 user = User.get_cached_by_id(user.id)
853 |> assign(:user, user)
854 |> post("/api/v1/accounts/#{other_user.id}/unmute")
856 response = json_response(conn, 200)
857 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
861 describe "subscribing / unsubscribing" do
862 test "subscribing / unsubscribing to a user", %{conn: conn} do
864 subscription_target = insert(:user)
868 |> assign(:user, user)
869 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
871 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
875 |> assign(:user, user)
876 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
878 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
882 describe "subscribing" do
883 test "returns 404 when subscription_target not found", %{conn: conn} do
888 |> assign(:user, user)
889 |> post("/api/v1/pleroma/accounts/target_id/subscribe")
891 assert %{"error" => "Record not found"} = json_response(conn, 404)
895 describe "unsubscribing" do
896 test "returns 404 when subscription_target not found", %{conn: conn} do
901 |> assign(:user, user)
902 |> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
904 assert %{"error" => "Record not found"} = json_response(conn, 404)
908 test "getting a list of mutes", %{conn: conn} do
910 other_user = insert(:user)
912 {:ok, user} = User.mute(user, other_user)
916 |> assign(:user, user)
917 |> get("/api/v1/mutes")
919 other_user_id = to_string(other_user.id)
920 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
923 test "blocking / unblocking a user", %{conn: conn} do
925 other_user = insert(:user)
929 |> assign(:user, user)
930 |> post("/api/v1/accounts/#{other_user.id}/block")
932 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
934 user = User.get_cached_by_id(user.id)
938 |> assign(:user, user)
939 |> post("/api/v1/accounts/#{other_user.id}/unblock")
941 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
944 test "getting a list of blocks", %{conn: conn} do
946 other_user = insert(:user)
948 {:ok, user} = User.block(user, other_user)
952 |> assign(:user, user)
953 |> get("/api/v1/blocks")
955 other_user_id = to_string(other_user.id)
956 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
959 test "unimplemented follow_requests, blocks, domain blocks" do
962 ["blocks", "domain_blocks", "follow_requests"]
963 |> Enum.each(fn endpoint ->
966 |> assign(:user, user)
967 |> get("/api/v1/#{endpoint}")
969 assert [] = json_response(conn, 200)
973 test "returns the favorites of a user", %{conn: conn} do
975 other_user = insert(:user)
977 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
978 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
980 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
984 |> assign(:user, user)
985 |> get("/api/v1/favourites")
987 assert [status] = json_response(first_conn, 200)
988 assert status["id"] == to_string(activity.id)
990 assert [{"link", _link_header}] =
991 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
993 # Honours query params
994 {:ok, second_activity} =
995 CommonAPI.post(other_user, %{
997 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1000 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1002 last_like = status["id"]
1006 |> assign(:user, user)
1007 |> get("/api/v1/favourites?since_id=#{last_like}")
1009 assert [second_status] = json_response(second_conn, 200)
1010 assert second_status["id"] == to_string(second_activity.id)
1014 |> assign(:user, user)
1015 |> get("/api/v1/favourites?limit=0")
1017 assert [] = json_response(third_conn, 200)
1020 describe "getting favorites timeline of specified user" do
1022 [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
1023 [current_user: current_user, user: user]
1026 test "returns list of statuses favorited by specified user", %{
1028 current_user: current_user,
1031 [activity | _] = insert_pair(:note_activity)
1032 CommonAPI.favorite(activity.id, user)
1036 |> assign(:user, current_user)
1037 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1038 |> json_response(:ok)
1042 assert length(response) == 1
1043 assert like["id"] == activity.id
1046 test "returns favorites for specified user_id when user is not logged in", %{
1050 activity = insert(:note_activity)
1051 CommonAPI.favorite(activity.id, user)
1055 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1056 |> json_response(:ok)
1058 assert length(response) == 1
1061 test "returns favorited DM only when user is logged in and he is one of recipients", %{
1063 current_user: current_user,
1067 CommonAPI.post(current_user, %{
1068 "status" => "Hi @#{user.nickname}!",
1069 "visibility" => "direct"
1072 CommonAPI.favorite(direct.id, user)
1076 |> assign(:user, current_user)
1077 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1078 |> json_response(:ok)
1080 assert length(response) == 1
1082 anonymous_response =
1084 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1085 |> json_response(:ok)
1087 assert Enum.empty?(anonymous_response)
1090 test "does not return others' favorited DM when user is not one of recipients", %{
1092 current_user: current_user,
1095 user_two = insert(:user)
1098 CommonAPI.post(user_two, %{
1099 "status" => "Hi @#{user.nickname}!",
1100 "visibility" => "direct"
1103 CommonAPI.favorite(direct.id, user)
1107 |> assign(:user, current_user)
1108 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1109 |> json_response(:ok)
1111 assert Enum.empty?(response)
1114 test "paginates favorites using since_id and max_id", %{
1116 current_user: current_user,
1119 activities = insert_list(10, :note_activity)
1121 Enum.each(activities, fn activity ->
1122 CommonAPI.favorite(activity.id, user)
1125 third_activity = Enum.at(activities, 2)
1126 seventh_activity = Enum.at(activities, 6)
1130 |> assign(:user, current_user)
1131 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
1132 since_id: third_activity.id,
1133 max_id: seventh_activity.id
1135 |> json_response(:ok)
1137 assert length(response) == 3
1138 refute third_activity in response
1139 refute seventh_activity in response
1142 test "limits favorites using limit parameter", %{
1144 current_user: current_user,
1148 |> insert_list(:note_activity)
1149 |> Enum.each(fn activity ->
1150 CommonAPI.favorite(activity.id, user)
1155 |> assign(:user, current_user)
1156 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
1157 |> json_response(:ok)
1159 assert length(response) == 3
1162 test "returns empty response when user does not have any favorited statuses", %{
1164 current_user: current_user,
1169 |> assign(:user, current_user)
1170 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1171 |> json_response(:ok)
1173 assert Enum.empty?(response)
1176 test "returns 404 error when specified user is not exist", %{conn: conn} do
1177 conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
1179 assert json_response(conn, 404) == %{"error" => "Record not found"}
1182 test "returns 403 error when user has hidden own favorites", %{
1184 current_user: current_user
1186 user = insert(:user, %{info: %{hide_favorites: true}})
1187 activity = insert(:note_activity)
1188 CommonAPI.favorite(activity.id, user)
1192 |> assign(:user, current_user)
1193 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1195 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1198 test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
1199 user = insert(:user)
1200 activity = insert(:note_activity)
1201 CommonAPI.favorite(activity.id, user)
1205 |> assign(:user, current_user)
1206 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1208 assert user.info.hide_favorites
1209 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1213 test "get instance information", %{conn: conn} do
1214 conn = get(conn, "/api/v1/instance")
1215 assert result = json_response(conn, 200)
1217 email = Config.get([:instance, :email])
1218 # Note: not checking for "max_toot_chars" since it's optional
1224 "email" => from_config_email,
1226 "streaming_api" => _
1231 "registrations" => _,
1235 assert email == from_config_email
1238 test "get instance stats", %{conn: conn} do
1239 user = insert(:user, %{local: true})
1241 user2 = insert(:user, %{local: true})
1242 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1244 insert(:user, %{local: false, nickname: "u@peer1.com"})
1245 insert(:user, %{local: false, nickname: "u@peer2.com"})
1247 {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"})
1249 # Stats should count users with missing or nil `info.deactivated` value
1253 |> User.get_cached_by_id()
1254 |> User.update_info(&Changeset.change(&1, %{deactivated: nil}))
1256 Pleroma.Stats.force_update()
1258 conn = get(conn, "/api/v1/instance")
1260 assert result = json_response(conn, 200)
1262 stats = result["stats"]
1265 assert stats["user_count"] == 1
1266 assert stats["status_count"] == 1
1267 assert stats["domain_count"] == 2
1270 test "get peers", %{conn: conn} do
1271 insert(:user, %{local: false, nickname: "u@peer1.com"})
1272 insert(:user, %{local: false, nickname: "u@peer2.com"})
1274 Pleroma.Stats.force_update()
1276 conn = get(conn, "/api/v1/instance/peers")
1278 assert result = json_response(conn, 200)
1280 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1283 test "put settings", %{conn: conn} do
1284 user = insert(:user)
1288 |> assign(:user, user)
1289 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1291 assert _result = json_response(conn, 200)
1293 user = User.get_cached_by_ap_id(user.ap_id)
1294 assert user.info.settings == %{"programming" => "socks"}
1297 describe "pinned statuses" do
1299 user = insert(:user)
1300 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1302 [user: user, activity: activity]
1305 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1306 {:ok, _} = CommonAPI.pin(activity.id, user)
1310 |> assign(:user, user)
1311 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1312 |> json_response(200)
1314 id_str = to_string(activity.id)
1316 assert [%{"id" => ^id_str, "pinned" => true}] = result
1320 describe "link headers" do
1321 test "preserves parameters in link headers", %{conn: conn} do
1322 user = insert(:user)
1323 other_user = insert(:user)
1326 CommonAPI.post(other_user, %{
1327 "status" => "hi @#{user.nickname}",
1328 "visibility" => "public"
1332 CommonAPI.post(other_user, %{
1333 "status" => "hi @#{user.nickname}",
1334 "visibility" => "public"
1337 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
1338 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
1342 |> assign(:user, user)
1343 |> get("/api/v1/notifications", %{media_only: true})
1345 assert [link_header] = get_resp_header(conn, "link")
1346 assert link_header =~ ~r/media_only=true/
1347 assert link_header =~ ~r/min_id=#{notification2.id}/
1348 assert link_header =~ ~r/max_id=#{notification1.id}/
1352 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
1353 # Need to set an old-style integer ID to reproduce the problem
1354 # (these are no longer assigned to new accounts but were preserved
1355 # for existing accounts during the migration to flakeIDs)
1356 user_one = insert(:user, %{id: 1212})
1357 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
1361 |> get("/api/v1/accounts/#{user_one.id}")
1365 |> get("/api/v1/accounts/#{user_two.nickname}")
1369 |> get("/api/v1/accounts/#{user_two.id}")
1371 acc_one = json_response(resp_one, 200)
1372 acc_two = json_response(resp_two, 200)
1373 acc_three = json_response(resp_three, 200)
1374 refute acc_one == acc_two
1375 assert acc_two == acc_three
1378 describe "custom emoji" do
1379 test "with tags", %{conn: conn} do
1382 |> get("/api/v1/custom_emojis")
1383 |> json_response(200)
1385 assert Map.has_key?(emoji, "shortcode")
1386 assert Map.has_key?(emoji, "static_url")
1387 assert Map.has_key?(emoji, "tags")
1388 assert is_list(emoji["tags"])
1389 assert Map.has_key?(emoji, "category")
1390 assert Map.has_key?(emoji, "url")
1391 assert Map.has_key?(emoji, "visible_in_picker")
1395 describe "index/2 redirections" do
1396 setup %{conn: conn} do
1400 signing_salt: "cooldude"
1405 |> Plug.Session.call(Plug.Session.init(session_opts))
1408 test_path = "/web/statuses/test"
1409 %{conn: conn, path: test_path}
1412 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
1413 conn = get(conn, path)
1415 assert conn.status == 302
1416 assert redirected_to(conn) == "/web/login"
1419 test "redirects not logged-in users to the login page on private instances", %{
1423 Config.put([:instance, :public], false)
1425 conn = get(conn, path)
1427 assert conn.status == 302
1428 assert redirected_to(conn) == "/web/login"
1431 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
1432 token = insert(:oauth_token)
1436 |> assign(:user, token.user)
1437 |> put_session(:oauth_token, token.token)
1440 assert conn.status == 200
1443 test "saves referer path to session", %{conn: conn, path: path} do
1444 conn = get(conn, path)
1445 return_to = Plug.Conn.get_session(conn, :return_to)
1447 assert return_to == path
1450 test "redirects to the saved path after log in", %{conn: conn, path: path} do
1451 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1452 auth = insert(:oauth_authorization, app: app)
1456 |> put_session(:return_to, path)
1457 |> get("/web/login", %{code: auth.token})
1459 assert conn.status == 302
1460 assert redirected_to(conn) == path
1463 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
1464 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1465 auth = insert(:oauth_authorization, app: app)
1467 conn = get(conn, "/web/login", %{code: auth.token})
1469 assert conn.status == 302
1470 assert redirected_to(conn) == "/web/getting-started"
1474 describe "create account by app" do
1478 email: "lain@example.org",
1479 password: "PlzDontHackLain",
1483 [valid_params: valid_params]
1486 test "Account registration via Application", %{conn: conn} do
1489 |> post("/api/v1/apps", %{
1490 client_name: "client_name",
1491 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
1492 scopes: "read, write, follow"
1496 "client_id" => client_id,
1497 "client_secret" => client_secret,
1499 "name" => "client_name",
1500 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1503 } = json_response(conn, 200)
1507 |> post("/oauth/token", %{
1508 grant_type: "client_credentials",
1509 client_id: client_id,
1510 client_secret: client_secret
1513 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1514 json_response(conn, 200)
1517 token_from_db = Repo.get_by(Token, token: token)
1518 assert token_from_db
1520 assert scope == "read write follow"
1524 |> put_req_header("authorization", "Bearer " <> token)
1525 |> post("/api/v1/accounts", %{
1527 email: "lain@example.org",
1528 password: "PlzDontHackLain",
1534 "access_token" => token,
1535 "created_at" => _created_at,
1537 "token_type" => "Bearer"
1538 } = json_response(conn, 200)
1540 token_from_db = Repo.get_by(Token, token: token)
1541 assert token_from_db
1542 token_from_db = Repo.preload(token_from_db, :user)
1543 assert token_from_db.user
1545 assert token_from_db.user.info.confirmation_pending
1548 test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
1549 _user = insert(:user, email: "lain@example.org")
1550 app_token = insert(:oauth_token, user: nil)
1554 |> put_req_header("authorization", "Bearer " <> app_token.token)
1556 res = post(conn, "/api/v1/accounts", valid_params)
1557 assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
1560 test "rate limit", %{conn: conn} do
1561 app_token = insert(:oauth_token, user: nil)
1564 put_req_header(conn, "authorization", "Bearer " <> app_token.token)
1565 |> Map.put(:remote_ip, {15, 15, 15, 15})
1570 |> post("/api/v1/accounts", %{
1571 username: "#{i}lain",
1572 email: "#{i}lain@example.org",
1573 password: "PlzDontHackLain",
1578 "access_token" => token,
1579 "created_at" => _created_at,
1581 "token_type" => "Bearer"
1582 } = json_response(conn, 200)
1584 token_from_db = Repo.get_by(Token, token: token)
1585 assert token_from_db
1586 token_from_db = Repo.preload(token_from_db, :user)
1587 assert token_from_db.user
1589 assert token_from_db.user.info.confirmation_pending
1594 |> post("/api/v1/accounts", %{
1596 email: "6lain@example.org",
1597 password: "PlzDontHackLain",
1601 assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
1604 test "returns bad_request if missing required params", %{
1606 valid_params: valid_params
1608 app_token = insert(:oauth_token, user: nil)
1612 |> put_req_header("authorization", "Bearer " <> app_token.token)
1614 res = post(conn, "/api/v1/accounts", valid_params)
1615 assert json_response(res, 200)
1617 [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
1618 |> Stream.zip(valid_params)
1619 |> Enum.each(fn {ip, {attr, _}} ->
1622 |> Map.put(:remote_ip, ip)
1623 |> post("/api/v1/accounts", Map.delete(valid_params, attr))
1624 |> json_response(400)
1626 assert res == %{"error" => "Missing parameters"}
1630 test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
1633 |> put_req_header("authorization", "Bearer " <> "invalid-token")
1635 res = post(conn, "/api/v1/accounts", valid_params)
1636 assert json_response(res, 403) == %{"error" => "Invalid credentials"}
1640 describe "GET /api/v1/polls/:id" do
1641 test "returns poll entity for object id", %{conn: conn} do
1642 user = insert(:user)
1645 CommonAPI.post(user, %{
1646 "status" => "Pleroma does",
1647 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
1650 object = Object.normalize(activity)
1654 |> assign(:user, user)
1655 |> get("/api/v1/polls/#{object.id}")
1657 response = json_response(conn, 200)
1658 id = to_string(object.id)
1659 assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
1662 test "does not expose polls for private statuses", %{conn: conn} do
1663 user = insert(:user)
1664 other_user = insert(:user)
1667 CommonAPI.post(user, %{
1668 "status" => "Pleroma does",
1669 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
1670 "visibility" => "private"
1673 object = Object.normalize(activity)
1677 |> assign(:user, other_user)
1678 |> get("/api/v1/polls/#{object.id}")
1680 assert json_response(conn, 404)
1684 describe "POST /api/v1/polls/:id/votes" do
1685 test "votes are added to the poll", %{conn: conn} do
1686 user = insert(:user)
1687 other_user = insert(:user)
1690 CommonAPI.post(user, %{
1691 "status" => "A very delicious sandwich",
1693 "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
1699 object = Object.normalize(activity)
1703 |> assign(:user, other_user)
1704 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
1706 assert json_response(conn, 200)
1707 object = Object.get_by_id(object.id)
1709 assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
1714 test "author can't vote", %{conn: conn} do
1715 user = insert(:user)
1718 CommonAPI.post(user, %{
1719 "status" => "Am I cute?",
1720 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
1723 object = Object.normalize(activity)
1726 |> assign(:user, user)
1727 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
1728 |> json_response(422) == %{"error" => "Poll's author can't vote"}
1730 object = Object.get_by_id(object.id)
1732 refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
1735 test "does not allow multiple choices on a single-choice question", %{conn: conn} do
1736 user = insert(:user)
1737 other_user = insert(:user)
1740 CommonAPI.post(user, %{
1741 "status" => "The glass is",
1742 "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
1745 object = Object.normalize(activity)
1748 |> assign(:user, other_user)
1749 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
1750 |> json_response(422) == %{"error" => "Too many choices"}
1752 object = Object.get_by_id(object.id)
1754 refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
1759 test "does not allow choice index to be greater than options count", %{conn: conn} do
1760 user = insert(:user)
1761 other_user = insert(:user)
1764 CommonAPI.post(user, %{
1765 "status" => "Am I cute?",
1766 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
1769 object = Object.normalize(activity)
1773 |> assign(:user, other_user)
1774 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
1776 assert json_response(conn, 422) == %{"error" => "Invalid indices"}
1779 test "returns 404 error when object is not exist", %{conn: conn} do
1780 user = insert(:user)
1784 |> assign(:user, user)
1785 |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
1787 assert json_response(conn, 404) == %{"error" => "Record not found"}
1790 test "returns 404 when poll is private and not available for user", %{conn: conn} do
1791 user = insert(:user)
1792 other_user = insert(:user)
1795 CommonAPI.post(user, %{
1796 "status" => "Am I cute?",
1797 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
1798 "visibility" => "private"
1801 object = Object.normalize(activity)
1805 |> assign(:user, other_user)
1806 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
1808 assert json_response(conn, 404) == %{"error" => "Record not found"}
1812 describe "POST /auth/password, with valid parameters" do
1813 setup %{conn: conn} do
1814 user = insert(:user)
1815 conn = post(conn, "/auth/password?email=#{user.email}")
1816 %{conn: conn, user: user}
1819 test "it returns 204", %{conn: conn} do
1820 assert json_response(conn, :no_content)
1823 test "it creates a PasswordResetToken record for user", %{user: user} do
1824 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1828 test "it sends an email to user", %{user: user} do
1829 ObanHelpers.perform_all()
1830 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1832 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1833 notify_email = Config.get([:instance, :notify_email])
1834 instance_name = Config.get([:instance, :name])
1837 from: {instance_name, notify_email},
1838 to: {user.name, user.email},
1839 html_body: email.html_body
1844 describe "POST /auth/password, with invalid parameters" do
1846 user = insert(:user)
1850 test "it returns 404 when user is not found", %{conn: conn, user: user} do
1851 conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
1852 assert conn.status == 404
1853 assert conn.resp_body == ""
1856 test "it returns 400 when user is not local", %{conn: conn, user: user} do
1857 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1858 conn = post(conn, "/auth/password?email=#{user.email}")
1859 assert conn.status == 400
1860 assert conn.resp_body == ""
1864 describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
1868 |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
1871 assert user.info.confirmation_pending
1876 clear_config([:instance, :account_activation_required]) do
1877 Config.put([:instance, :account_activation_required], true)
1880 test "resend account confirmation email", %{conn: conn, user: user} do
1882 |> assign(:user, user)
1883 |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
1884 |> json_response(:no_content)
1886 ObanHelpers.perform_all()
1888 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1889 notify_email = Config.get([:instance, :notify_email])
1890 instance_name = Config.get([:instance, :name])
1893 from: {instance_name, notify_email},
1894 to: {user.name, user.email},
1895 html_body: email.html_body
1900 describe "GET /api/v1/suggestions" do
1902 user = insert(:user)
1903 other_user = insert(:user)
1904 host = Config.get([Pleroma.Web.Endpoint, :url, :host])
1905 url500 = "http://test500?#{host}&#{user.nickname}"
1906 url200 = "http://test200?#{host}&#{user.nickname}"
1909 %{method: :get, url: ^url500} ->
1910 %Tesla.Env{status: 500, body: "bad request"}
1912 %{method: :get, url: ^url200} ->
1916 ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
1918 }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
1922 [user: user, other_user: other_user]
1925 clear_config(:suggestions)
1927 test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
1928 Config.put([:suggestions, :enabled], false)
1932 |> assign(:user, user)
1933 |> get("/api/v1/suggestions")
1934 |> json_response(200)
1939 test "returns error", %{conn: conn, user: user} do
1940 Config.put([:suggestions, :enabled], true)
1941 Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
1943 assert capture_log(fn ->
1946 |> assign(:user, user)
1947 |> get("/api/v1/suggestions")
1948 |> json_response(500)
1950 assert res == "Something went wrong"
1951 end) =~ "Could not retrieve suggestions"
1954 test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
1955 Config.put([:suggestions, :enabled], true)
1956 Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
1960 |> assign(:user, user)
1961 |> get("/api/v1/suggestions")
1962 |> json_response(200)
1967 "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
1968 "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
1972 "acct" => other_user.ap_id,
1973 "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
1974 "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
1975 "id" => other_user.id
1981 describe "PUT /api/v1/media/:id" do
1983 actor = insert(:user)
1985 file = %Plug.Upload{
1986 content_type: "image/jpg",
1987 path: Path.absname("test/fixtures/image.jpg"),
1988 filename: "an_image.jpg"
1991 {:ok, %Object{} = object} =
1994 actor: User.ap_id(actor),
1995 description: "test-m"
1998 [actor: actor, object: object]
2001 test "updates name of media", %{conn: conn, actor: actor, object: object} do
2004 |> assign(:user, actor)
2005 |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
2006 |> json_response(:ok)
2008 assert media["description"] == "test-media"
2009 assert refresh_record(object).data["name"] == "test-media"
2012 test "returns error wheb request is bad", %{conn: conn, actor: actor, object: object} do
2015 |> assign(:user, actor)
2016 |> put("/api/v1/media/#{object.id}", %{})
2017 |> json_response(400)
2019 assert media == %{"error" => "bad_request"}
2023 describe "DELETE /auth/sign_out" do
2024 test "redirect to root page", %{conn: conn} do
2025 user = insert(:user)
2029 |> assign(:user, user)
2030 |> delete("/auth/sign_out")
2032 assert conn.status == 302
2033 assert redirected_to(conn) == "/"
2037 describe "GET /api/v1/accounts/:id/lists - account_lists" do
2038 test "returns lists to which the account belongs", %{conn: conn} do
2039 user = insert(:user)
2040 other_user = insert(:user)
2041 assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
2042 {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
2046 |> assign(:user, user)
2047 |> get("/api/v1/accounts/#{other_user.id}/lists")
2048 |> json_response(200)
2050 assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
2054 describe "empty_array, stubs for mastodon api" do
2055 test "GET /api/v1/accounts/:id/identity_proofs", %{conn: conn} do
2056 user = insert(:user)
2060 |> assign(:user, user)
2061 |> get("/api/v1/accounts/#{user.id}/identity_proofs")
2062 |> json_response(200)
2067 test "GET /api/v1/endorsements", %{conn: conn} do
2068 user = insert(:user)
2072 |> assign(:user, user)
2073 |> get("/api/v1/endorsements")
2074 |> json_response(200)
2079 test "GET /api/v1/trends", %{conn: conn} do
2080 user = insert(:user)
2084 |> assign(:user, user)
2085 |> get("/api/v1/trends")
2086 |> json_response(200)