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
14 alias Pleroma.Web.ActivityPub.ActivityPub
15 alias Pleroma.Web.CommonAPI
16 alias Pleroma.Web.MastodonAPI.FilterView
17 alias Pleroma.Web.OAuth.App
18 alias Pleroma.Web.OStatus
19 alias Pleroma.Web.Push
20 alias Pleroma.Web.TwitterAPI.TwitterAPI
21 import Pleroma.Factory
22 import ExUnit.CaptureLog
26 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
30 test "the home timeline", %{conn: conn} do
32 following = insert(:user)
34 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
38 |> assign(:user, user)
39 |> get("/api/v1/timelines/home")
41 assert Enum.empty?(json_response(conn, 200))
43 {:ok, user} = User.follow(user, following)
47 |> assign(:user, user)
48 |> get("/api/v1/timelines/home")
50 assert [%{"content" => "test"}] = json_response(conn, 200)
53 test "the public timeline", %{conn: conn} do
54 following = insert(:user)
57 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
60 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
64 |> get("/api/v1/timelines/public", %{"local" => "False"})
66 assert length(json_response(conn, 200)) == 2
70 |> get("/api/v1/timelines/public", %{"local" => "True"})
72 assert [%{"content" => "test"}] = json_response(conn, 200)
76 |> get("/api/v1/timelines/public", %{"local" => "1"})
78 assert [%{"content" => "test"}] = json_response(conn, 200)
82 test "posting a status", %{conn: conn} do
85 idempotency_key = "Pikachu rocks!"
89 |> assign(:user, user)
90 |> put_req_header("idempotency-key", idempotency_key)
91 |> post("/api/v1/statuses", %{
93 "spoiler_text" => "2hu",
94 "sensitive" => "false"
97 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
99 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
101 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
102 json_response(conn_one, 200)
104 assert Repo.get(Activity, id)
108 |> assign(:user, user)
109 |> put_req_header("idempotency-key", idempotency_key)
110 |> post("/api/v1/statuses", %{
112 "spoiler_text" => "2hu",
113 "sensitive" => "false"
116 assert %{"id" => second_id} = json_response(conn_two, 200)
118 assert id == second_id
122 |> assign(:user, user)
123 |> post("/api/v1/statuses", %{
125 "spoiler_text" => "2hu",
126 "sensitive" => "false"
129 assert %{"id" => third_id} = json_response(conn_three, 200)
131 refute id == third_id
134 test "posting a sensitive status", %{conn: conn} do
139 |> assign(:user, user)
140 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
142 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
143 assert Repo.get(Activity, id)
146 test "posting a status with OGP link preview", %{conn: conn} do
147 Pleroma.Config.put([:rich_media, :enabled], true)
152 |> assign(:user, user)
153 |> post("/api/v1/statuses", %{
154 "status" => "http://example.com/ogp"
157 assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
158 assert Repo.get(Activity, id)
159 Pleroma.Config.put([:rich_media, :enabled], false)
162 test "posting a direct status", %{conn: conn} do
163 user1 = insert(:user)
164 user2 = insert(:user)
165 content = "direct cofe @#{user2.nickname}"
169 |> assign(:user, user1)
170 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
172 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
173 assert activity = Repo.get(Activity, id)
174 assert activity.recipients == [user2.ap_id, user1.ap_id]
175 assert activity.data["to"] == [user2.ap_id]
176 assert activity.data["cc"] == []
179 test "direct timeline", %{conn: conn} do
180 user_one = insert(:user)
181 user_two = insert(:user)
183 {:ok, user_two} = User.follow(user_two, user_one)
186 CommonAPI.post(user_one, %{
187 "status" => "Hi @#{user_two.nickname}!",
188 "visibility" => "direct"
191 {:ok, _follower_only} =
192 CommonAPI.post(user_one, %{
193 "status" => "Hi @#{user_two.nickname}!",
194 "visibility" => "private"
197 # Only direct should be visible here
200 |> assign(:user, user_two)
201 |> get("api/v1/timelines/direct")
203 [status] = json_response(res_conn, 200)
205 assert %{"visibility" => "direct"} = status
206 assert status["url"] != direct.data["id"]
208 # User should be able to see his own direct message
211 |> assign(:user, user_one)
212 |> get("api/v1/timelines/direct")
214 [status] = json_response(res_conn, 200)
216 assert %{"visibility" => "direct"} = status
218 # Both should be visible here
221 |> assign(:user, user_two)
222 |> get("api/v1/timelines/home")
224 [_s1, _s2] = json_response(res_conn, 200)
227 Enum.each(1..20, fn _ ->
229 CommonAPI.post(user_one, %{
230 "status" => "Hi @#{user_two.nickname}!",
231 "visibility" => "direct"
237 |> assign(:user, user_two)
238 |> get("api/v1/timelines/direct")
240 statuses = json_response(res_conn, 200)
241 assert length(statuses) == 20
245 |> assign(:user, user_two)
246 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
248 [status] = json_response(res_conn, 200)
250 assert status["url"] != direct.data["id"]
253 test "doesn't include DMs from blocked users", %{conn: conn} do
254 blocker = insert(:user)
255 blocked = insert(:user)
257 {:ok, blocker} = User.block(blocker, blocked)
259 {:ok, _blocked_direct} =
260 CommonAPI.post(blocked, %{
261 "status" => "Hi @#{blocker.nickname}!",
262 "visibility" => "direct"
266 CommonAPI.post(user, %{
267 "status" => "Hi @#{blocker.nickname}!",
268 "visibility" => "direct"
273 |> assign(:user, user)
274 |> get("api/v1/timelines/direct")
276 [status] = json_response(res_conn, 200)
277 assert status["id"] == direct.id
280 test "replying to a status", %{conn: conn} do
283 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
287 |> assign(:user, user)
288 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
290 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
292 activity = Repo.get(Activity, id)
294 assert activity.data["context"] == replied_to.data["context"]
295 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
298 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
303 |> assign(:user, user)
304 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
306 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
308 activity = Repo.get(Activity, id)
313 test "verify_credentials", %{conn: conn} do
318 |> assign(:user, user)
319 |> get("/api/v1/accounts/verify_credentials")
321 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
322 assert id == to_string(user.id)
325 test "verify_credentials default scope unlisted", %{conn: conn} do
326 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
330 |> assign(:user, user)
331 |> get("/api/v1/accounts/verify_credentials")
333 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
334 assert id == to_string(user.id)
337 test "apps/verify_credentials", %{conn: conn} do
338 token = insert(:oauth_token)
342 |> assign(:user, token.user)
343 |> assign(:token, token)
344 |> get("/api/v1/apps/verify_credentials")
346 app = Repo.preload(token, :app).app
349 "name" => app.client_name,
350 "website" => app.website,
351 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
354 assert expected == json_response(conn, 200)
357 test "creates an oauth app", %{conn: conn} do
359 app_attrs = build(:oauth_app)
363 |> assign(:user, user)
364 |> post("/api/v1/apps", %{
365 client_name: app_attrs.client_name,
366 redirect_uris: app_attrs.redirect_uris
369 [app] = Repo.all(App)
372 "name" => app.client_name,
373 "website" => app.website,
374 "client_id" => app.client_id,
375 "client_secret" => app.client_secret,
376 "id" => app.id |> to_string(),
377 "redirect_uri" => app.redirect_uris,
378 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
381 assert expected == json_response(conn, 200)
384 test "get a status", %{conn: conn} do
385 activity = insert(:note_activity)
389 |> get("/api/v1/statuses/#{activity.id}")
391 assert %{"id" => id} = json_response(conn, 200)
392 assert id == to_string(activity.id)
395 describe "deleting a status" do
396 test "when you created it", %{conn: conn} do
397 activity = insert(:note_activity)
398 author = User.get_by_ap_id(activity.data["actor"])
402 |> assign(:user, author)
403 |> delete("/api/v1/statuses/#{activity.id}")
405 assert %{} = json_response(conn, 200)
407 refute Repo.get(Activity, activity.id)
410 test "when you didn't create it", %{conn: conn} do
411 activity = insert(:note_activity)
416 |> assign(:user, user)
417 |> delete("/api/v1/statuses/#{activity.id}")
419 assert %{"error" => _} = json_response(conn, 403)
421 assert Repo.get(Activity, activity.id) == activity
424 test "when you're an admin or moderator", %{conn: conn} do
425 activity1 = insert(:note_activity)
426 activity2 = insert(:note_activity)
427 admin = insert(:user, info: %{is_admin: true})
428 moderator = insert(:user, info: %{is_moderator: true})
432 |> assign(:user, admin)
433 |> delete("/api/v1/statuses/#{activity1.id}")
435 assert %{} = json_response(res_conn, 200)
439 |> assign(:user, moderator)
440 |> delete("/api/v1/statuses/#{activity2.id}")
442 assert %{} = json_response(res_conn, 200)
444 refute Repo.get(Activity, activity1.id)
445 refute Repo.get(Activity, activity2.id)
449 describe "filters" do
450 test "creating a filter", %{conn: conn} do
453 filter = %Pleroma.Filter{
460 |> assign(:user, user)
461 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
463 assert response = json_response(conn, 200)
464 assert response["phrase"] == filter.phrase
465 assert response["context"] == filter.context
466 assert response["id"] != nil
467 assert response["id"] != ""
470 test "fetching a list of filters", %{conn: conn} do
473 query_one = %Pleroma.Filter{
480 query_two = %Pleroma.Filter{
487 {:ok, filter_one} = Pleroma.Filter.create(query_one)
488 {:ok, filter_two} = Pleroma.Filter.create(query_two)
492 |> assign(:user, user)
493 |> get("/api/v1/filters")
494 |> json_response(200)
500 filters: [filter_two, filter_one]
504 test "get a filter", %{conn: conn} do
507 query = %Pleroma.Filter{
514 {:ok, filter} = Pleroma.Filter.create(query)
518 |> assign(:user, user)
519 |> get("/api/v1/filters/#{filter.filter_id}")
521 assert _response = json_response(conn, 200)
524 test "update a filter", %{conn: conn} do
527 query = %Pleroma.Filter{
534 {:ok, _filter} = Pleroma.Filter.create(query)
536 new = %Pleroma.Filter{
543 |> assign(:user, user)
544 |> put("/api/v1/filters/#{query.filter_id}", %{
549 assert response = json_response(conn, 200)
550 assert response["phrase"] == new.phrase
551 assert response["context"] == new.context
554 test "delete a filter", %{conn: conn} do
557 query = %Pleroma.Filter{
564 {:ok, filter} = Pleroma.Filter.create(query)
568 |> assign(:user, user)
569 |> delete("/api/v1/filters/#{filter.filter_id}")
571 assert response = json_response(conn, 200)
572 assert response == %{}
577 test "creating a list", %{conn: conn} do
582 |> assign(:user, user)
583 |> post("/api/v1/lists", %{"title" => "cuties"})
585 assert %{"title" => title} = json_response(conn, 200)
586 assert title == "cuties"
589 test "adding users to a list", %{conn: conn} do
591 other_user = insert(:user)
592 {:ok, list} = Pleroma.List.create("name", user)
596 |> assign(:user, user)
597 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
599 assert %{} == json_response(conn, 200)
600 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
601 assert following == [other_user.follower_address]
604 test "removing users from a list", %{conn: conn} do
606 other_user = insert(:user)
607 third_user = insert(:user)
608 {:ok, list} = Pleroma.List.create("name", user)
609 {:ok, list} = Pleroma.List.follow(list, other_user)
610 {:ok, list} = Pleroma.List.follow(list, third_user)
614 |> assign(:user, user)
615 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
617 assert %{} == json_response(conn, 200)
618 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
619 assert following == [third_user.follower_address]
622 test "listing users in a list", %{conn: conn} do
624 other_user = insert(:user)
625 {:ok, list} = Pleroma.List.create("name", user)
626 {:ok, list} = Pleroma.List.follow(list, other_user)
630 |> assign(:user, user)
631 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
633 assert [%{"id" => id}] = json_response(conn, 200)
634 assert id == to_string(other_user.id)
637 test "retrieving a list", %{conn: conn} do
639 {:ok, list} = Pleroma.List.create("name", user)
643 |> assign(:user, user)
644 |> get("/api/v1/lists/#{list.id}")
646 assert %{"id" => id} = json_response(conn, 200)
647 assert id == to_string(list.id)
650 test "renaming a list", %{conn: conn} do
652 {:ok, list} = Pleroma.List.create("name", user)
656 |> assign(:user, user)
657 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
659 assert %{"title" => name} = json_response(conn, 200)
660 assert name == "newname"
663 test "deleting a list", %{conn: conn} do
665 {:ok, list} = Pleroma.List.create("name", user)
669 |> assign(:user, user)
670 |> delete("/api/v1/lists/#{list.id}")
672 assert %{} = json_response(conn, 200)
673 assert is_nil(Repo.get(Pleroma.List, list.id))
676 test "list timeline", %{conn: conn} do
678 other_user = insert(:user)
679 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
680 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
681 {:ok, list} = Pleroma.List.create("name", user)
682 {:ok, list} = Pleroma.List.follow(list, other_user)
686 |> assign(:user, user)
687 |> get("/api/v1/timelines/list/#{list.id}")
689 assert [%{"id" => id}] = json_response(conn, 200)
691 assert id == to_string(activity_two.id)
694 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
696 other_user = insert(:user)
697 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
699 {:ok, _activity_two} =
700 TwitterAPI.create_status(other_user, %{
701 "status" => "Marisa is cute.",
702 "visibility" => "private"
705 {:ok, list} = Pleroma.List.create("name", user)
706 {:ok, list} = Pleroma.List.follow(list, other_user)
710 |> assign(:user, user)
711 |> get("/api/v1/timelines/list/#{list.id}")
713 assert [%{"id" => id}] = json_response(conn, 200)
715 assert id == to_string(activity_one.id)
719 describe "notifications" do
720 test "list of notifications", %{conn: conn} do
722 other_user = insert(:user)
725 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
727 {:ok, [_notification]} = Notification.create_notifications(activity)
731 |> assign(:user, user)
732 |> get("/api/v1/notifications")
735 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
737 }\">@<span>#{user.nickname}</span></a></span>"
739 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
740 assert response == expected_response
743 test "getting a single notification", %{conn: conn} do
745 other_user = insert(:user)
748 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
750 {:ok, [notification]} = Notification.create_notifications(activity)
754 |> assign(:user, user)
755 |> get("/api/v1/notifications/#{notification.id}")
758 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
760 }\">@<span>#{user.nickname}</span></a></span>"
762 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
763 assert response == expected_response
766 test "dismissing a single notification", %{conn: conn} do
768 other_user = insert(:user)
771 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
773 {:ok, [notification]} = Notification.create_notifications(activity)
777 |> assign(:user, user)
778 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
780 assert %{} = json_response(conn, 200)
783 test "clearing all notifications", %{conn: conn} do
785 other_user = insert(:user)
788 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
790 {:ok, [_notification]} = Notification.create_notifications(activity)
794 |> assign(:user, user)
795 |> post("/api/v1/notifications/clear")
797 assert %{} = json_response(conn, 200)
801 |> assign(:user, user)
802 |> get("/api/v1/notifications")
804 assert all = json_response(conn, 200)
808 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
810 other_user = insert(:user)
812 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
813 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
814 {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
815 {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
817 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
818 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
819 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
820 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
824 |> assign(:user, user)
829 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
831 result = json_response(conn_res, 200)
832 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
837 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
839 result = json_response(conn_res, 200)
840 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
845 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
847 result = json_response(conn_res, 200)
848 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
851 test "filters notifications using exclude_types", %{conn: conn} do
853 other_user = insert(:user)
855 {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
856 {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
857 {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
858 {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
859 {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
861 mention_notification_id =
862 Repo.get_by(Notification, activity_id: mention_activity.id).id |> to_string()
864 favorite_notification_id =
865 Repo.get_by(Notification, activity_id: favorite_activity.id).id |> to_string()
867 reblog_notification_id =
868 Repo.get_by(Notification, activity_id: reblog_activity.id).id |> to_string()
870 follow_notification_id =
871 Repo.get_by(Notification, activity_id: follow_activity.id).id |> to_string()
875 |> assign(:user, user)
878 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
880 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
883 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
885 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
888 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
890 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
893 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
895 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
899 describe "reblogging" do
900 test "reblogs and returns the reblogged status", %{conn: conn} do
901 activity = insert(:note_activity)
906 |> assign(:user, user)
907 |> post("/api/v1/statuses/#{activity.id}/reblog")
909 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
910 json_response(conn, 200)
912 assert to_string(activity.id) == id
916 describe "unreblogging" do
917 test "unreblogs and returns the unreblogged status", %{conn: conn} do
918 activity = insert(:note_activity)
921 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
925 |> assign(:user, user)
926 |> post("/api/v1/statuses/#{activity.id}/unreblog")
928 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
930 assert to_string(activity.id) == id
934 describe "favoriting" do
935 test "favs a status and returns it", %{conn: conn} do
936 activity = insert(:note_activity)
941 |> assign(:user, user)
942 |> post("/api/v1/statuses/#{activity.id}/favourite")
944 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
945 json_response(conn, 200)
947 assert to_string(activity.id) == id
950 test "returns 500 for a wrong id", %{conn: conn} do
955 |> assign(:user, user)
956 |> post("/api/v1/statuses/1/favourite")
957 |> json_response(500)
959 assert resp == "Something went wrong"
963 describe "unfavoriting" do
964 test "unfavorites a status and returns it", %{conn: conn} do
965 activity = insert(:note_activity)
968 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
972 |> assign(:user, user)
973 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
975 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
976 json_response(conn, 200)
978 assert to_string(activity.id) == id
982 describe "user timelines" do
983 test "gets a users statuses", %{conn: conn} do
984 user_one = insert(:user)
985 user_two = insert(:user)
986 user_three = insert(:user)
988 {:ok, user_three} = User.follow(user_three, user_one)
990 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
992 {:ok, direct_activity} =
993 CommonAPI.post(user_one, %{
994 "status" => "Hi, @#{user_two.nickname}.",
995 "visibility" => "direct"
998 {:ok, private_activity} =
999 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
1003 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1005 assert [%{"id" => id}] = json_response(resp, 200)
1006 assert id == to_string(activity.id)
1010 |> assign(:user, user_two)
1011 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1013 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1014 assert id_one == to_string(direct_activity.id)
1015 assert id_two == to_string(activity.id)
1019 |> assign(:user, user_three)
1020 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1022 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1023 assert id_one == to_string(private_activity.id)
1024 assert id_two == to_string(activity.id)
1027 test "unimplemented pinned statuses feature", %{conn: conn} do
1028 note = insert(:note_activity)
1029 user = User.get_by_ap_id(note.data["actor"])
1033 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1035 assert json_response(conn, 200) == []
1038 test "gets an users media", %{conn: conn} do
1039 note = insert(:note_activity)
1040 user = User.get_by_ap_id(note.data["actor"])
1042 file = %Plug.Upload{
1043 content_type: "image/jpg",
1044 path: Path.absname("test/fixtures/image.jpg"),
1045 filename: "an_image.jpg"
1049 TwitterAPI.upload(file, user, "json")
1053 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
1057 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
1059 assert [%{"id" => id}] = json_response(conn, 200)
1060 assert id == to_string(image_post.id)
1064 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
1066 assert [%{"id" => id}] = json_response(conn, 200)
1067 assert id == to_string(image_post.id)
1070 test "gets a user's statuses without reblogs", %{conn: conn} do
1071 user = insert(:user)
1072 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
1073 {:ok, _, _} = CommonAPI.repeat(post.id, user)
1077 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
1079 assert [%{"id" => id}] = json_response(conn, 200)
1080 assert id == to_string(post.id)
1084 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
1086 assert [%{"id" => id}] = json_response(conn, 200)
1087 assert id == to_string(post.id)
1091 describe "user relationships" do
1092 test "returns the relationships for the current user", %{conn: conn} do
1093 user = insert(:user)
1094 other_user = insert(:user)
1095 {:ok, user} = User.follow(user, other_user)
1099 |> assign(:user, user)
1100 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
1102 assert [relationship] = json_response(conn, 200)
1104 assert to_string(other_user.id) == relationship["id"]
1108 describe "locked accounts" do
1109 test "/api/v1/follow_requests works" do
1110 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1111 other_user = insert(:user)
1113 {:ok, _activity} = ActivityPub.follow(other_user, user)
1115 user = Repo.get(User, user.id)
1116 other_user = Repo.get(User, other_user.id)
1118 assert User.following?(other_user, user) == false
1122 |> assign(:user, user)
1123 |> get("/api/v1/follow_requests")
1125 assert [relationship] = json_response(conn, 200)
1126 assert to_string(other_user.id) == relationship["id"]
1129 test "/api/v1/follow_requests/:id/authorize works" do
1130 user = insert(:user, %{info: %User.Info{locked: true}})
1131 other_user = insert(:user)
1133 {:ok, _activity} = ActivityPub.follow(other_user, user)
1135 user = Repo.get(User, user.id)
1136 other_user = Repo.get(User, other_user.id)
1138 assert User.following?(other_user, user) == false
1142 |> assign(:user, user)
1143 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
1145 assert relationship = json_response(conn, 200)
1146 assert to_string(other_user.id) == relationship["id"]
1148 user = Repo.get(User, user.id)
1149 other_user = Repo.get(User, other_user.id)
1151 assert User.following?(other_user, user) == true
1154 test "verify_credentials", %{conn: conn} do
1155 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
1159 |> assign(:user, user)
1160 |> get("/api/v1/accounts/verify_credentials")
1162 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
1163 assert id == to_string(user.id)
1166 test "/api/v1/follow_requests/:id/reject works" do
1167 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1168 other_user = insert(:user)
1170 {:ok, _activity} = ActivityPub.follow(other_user, user)
1172 user = Repo.get(User, user.id)
1176 |> assign(:user, user)
1177 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
1179 assert relationship = json_response(conn, 200)
1180 assert to_string(other_user.id) == relationship["id"]
1182 user = Repo.get(User, user.id)
1183 other_user = Repo.get(User, other_user.id)
1185 assert User.following?(other_user, user) == false
1189 test "account fetching", %{conn: conn} do
1190 user = insert(:user)
1194 |> get("/api/v1/accounts/#{user.id}")
1196 assert %{"id" => id} = json_response(conn, 200)
1197 assert id == to_string(user.id)
1201 |> get("/api/v1/accounts/-1")
1203 assert %{"error" => "Can't find user"} = json_response(conn, 404)
1206 test "account fetching also works nickname", %{conn: conn} do
1207 user = insert(:user)
1211 |> get("/api/v1/accounts/#{user.nickname}")
1213 assert %{"id" => id} = json_response(conn, 200)
1214 assert id == user.id
1217 test "media upload", %{conn: conn} do
1218 file = %Plug.Upload{
1219 content_type: "image/jpg",
1220 path: Path.absname("test/fixtures/image.jpg"),
1221 filename: "an_image.jpg"
1224 desc = "Description of the image"
1226 user = insert(:user)
1230 |> assign(:user, user)
1231 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1233 assert media = json_response(conn, 200)
1235 assert media["type"] == "image"
1236 assert media["description"] == desc
1239 object = Repo.get(Object, media["id"])
1240 assert object.data["actor"] == User.ap_id(user)
1243 test "hashtag timeline", %{conn: conn} do
1244 following = insert(:user)
1247 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1249 {:ok, [_activity]} =
1250 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1254 |> get("/api/v1/timelines/tag/2hu")
1256 assert [%{"id" => id}] = json_response(nconn, 200)
1258 assert id == to_string(activity.id)
1260 # works for different capitalization too
1263 |> get("/api/v1/timelines/tag/2HU")
1265 assert [%{"id" => id}] = json_response(nconn, 200)
1267 assert id == to_string(activity.id)
1271 test "multi-hashtag timeline", %{conn: conn} do
1272 user = insert(:user)
1274 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1275 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1276 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1280 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1282 [status_none, status_test1, status_test] = json_response(any_test, 200)
1284 assert to_string(activity_test.id) == status_test["id"]
1285 assert to_string(activity_test1.id) == status_test1["id"]
1286 assert to_string(activity_none.id) == status_none["id"]
1290 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1292 assert [status_test1] == json_response(restricted_test, 200)
1294 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1296 assert [status_none] == json_response(all_test, 200)
1299 test "getting followers", %{conn: conn} do
1300 user = insert(:user)
1301 other_user = insert(:user)
1302 {:ok, user} = User.follow(user, other_user)
1306 |> get("/api/v1/accounts/#{other_user.id}/followers")
1308 assert [%{"id" => id}] = json_response(conn, 200)
1309 assert id == to_string(user.id)
1312 test "getting followers, hide_followers", %{conn: conn} do
1313 user = insert(:user)
1314 other_user = insert(:user, %{info: %{hide_followers: true}})
1315 {:ok, _user} = User.follow(user, other_user)
1319 |> get("/api/v1/accounts/#{other_user.id}/followers")
1321 assert [] == json_response(conn, 200)
1324 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1325 user = insert(:user)
1326 other_user = insert(:user, %{info: %{hide_followers: true}})
1327 {:ok, _user} = User.follow(user, other_user)
1331 |> assign(:user, other_user)
1332 |> get("/api/v1/accounts/#{other_user.id}/followers")
1334 refute [] == json_response(conn, 200)
1337 test "getting followers, pagination", %{conn: conn} do
1338 user = insert(:user)
1339 follower1 = insert(:user)
1340 follower2 = insert(:user)
1341 follower3 = insert(:user)
1342 {:ok, _} = User.follow(follower1, user)
1343 {:ok, _} = User.follow(follower2, user)
1344 {:ok, _} = User.follow(follower3, user)
1348 |> assign(:user, user)
1352 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1354 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1355 assert id3 == follower3.id
1356 assert id2 == follower2.id
1360 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1362 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1363 assert id2 == follower2.id
1364 assert id1 == follower1.id
1368 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1370 assert [%{"id" => id2}] = json_response(res_conn, 200)
1371 assert id2 == follower2.id
1373 assert [link_header] = get_resp_header(res_conn, "link")
1374 assert link_header =~ ~r/since_id=#{follower2.id}/
1375 assert link_header =~ ~r/max_id=#{follower2.id}/
1378 test "getting following", %{conn: conn} do
1379 user = insert(:user)
1380 other_user = insert(:user)
1381 {:ok, user} = User.follow(user, other_user)
1385 |> get("/api/v1/accounts/#{user.id}/following")
1387 assert [%{"id" => id}] = json_response(conn, 200)
1388 assert id == to_string(other_user.id)
1391 test "getting following, hide_follows", %{conn: conn} do
1392 user = insert(:user, %{info: %{hide_follows: true}})
1393 other_user = insert(:user)
1394 {:ok, user} = User.follow(user, other_user)
1398 |> get("/api/v1/accounts/#{user.id}/following")
1400 assert [] == json_response(conn, 200)
1403 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1404 user = insert(:user, %{info: %{hide_follows: true}})
1405 other_user = insert(:user)
1406 {:ok, user} = User.follow(user, other_user)
1410 |> assign(:user, user)
1411 |> get("/api/v1/accounts/#{user.id}/following")
1413 refute [] == json_response(conn, 200)
1416 test "getting following, pagination", %{conn: conn} do
1417 user = insert(:user)
1418 following1 = insert(:user)
1419 following2 = insert(:user)
1420 following3 = insert(:user)
1421 {:ok, _} = User.follow(user, following1)
1422 {:ok, _} = User.follow(user, following2)
1423 {:ok, _} = User.follow(user, following3)
1427 |> assign(:user, user)
1431 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1433 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1434 assert id3 == following3.id
1435 assert id2 == following2.id
1439 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1441 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1442 assert id2 == following2.id
1443 assert id1 == following1.id
1447 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1449 assert [%{"id" => id2}] = json_response(res_conn, 200)
1450 assert id2 == following2.id
1452 assert [link_header] = get_resp_header(res_conn, "link")
1453 assert link_header =~ ~r/since_id=#{following2.id}/
1454 assert link_header =~ ~r/max_id=#{following2.id}/
1457 test "following / unfollowing a user", %{conn: conn} do
1458 user = insert(:user)
1459 other_user = insert(:user)
1463 |> assign(:user, user)
1464 |> post("/api/v1/accounts/#{other_user.id}/follow")
1466 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1468 user = Repo.get(User, user.id)
1472 |> assign(:user, user)
1473 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1475 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1477 user = Repo.get(User, user.id)
1481 |> assign(:user, user)
1482 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1484 assert %{"id" => id} = json_response(conn, 200)
1485 assert id == to_string(other_user.id)
1488 test "muting / unmuting a user", %{conn: conn} do
1489 user = insert(:user)
1490 other_user = insert(:user)
1494 |> assign(:user, user)
1495 |> post("/api/v1/accounts/#{other_user.id}/mute")
1497 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1499 user = Repo.get(User, user.id)
1503 |> assign(:user, user)
1504 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1506 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1509 test "getting a list of mutes", %{conn: conn} do
1510 user = insert(:user)
1511 other_user = insert(:user)
1513 {:ok, user} = User.mute(user, other_user)
1517 |> assign(:user, user)
1518 |> get("/api/v1/mutes")
1520 other_user_id = to_string(other_user.id)
1521 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1524 test "blocking / unblocking a user", %{conn: conn} do
1525 user = insert(:user)
1526 other_user = insert(:user)
1530 |> assign(:user, user)
1531 |> post("/api/v1/accounts/#{other_user.id}/block")
1533 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1535 user = Repo.get(User, user.id)
1539 |> assign(:user, user)
1540 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1542 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1545 test "getting a list of blocks", %{conn: conn} do
1546 user = insert(:user)
1547 other_user = insert(:user)
1549 {:ok, user} = User.block(user, other_user)
1553 |> assign(:user, user)
1554 |> get("/api/v1/blocks")
1556 other_user_id = to_string(other_user.id)
1557 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1560 test "blocking / unblocking a domain", %{conn: conn} do
1561 user = insert(:user)
1562 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1566 |> assign(:user, user)
1567 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1569 assert %{} = json_response(conn, 200)
1570 user = User.get_cached_by_ap_id(user.ap_id)
1571 assert User.blocks?(user, other_user)
1575 |> assign(:user, user)
1576 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1578 assert %{} = json_response(conn, 200)
1579 user = User.get_cached_by_ap_id(user.ap_id)
1580 refute User.blocks?(user, other_user)
1583 test "getting a list of domain blocks", %{conn: conn} do
1584 user = insert(:user)
1586 {:ok, user} = User.block_domain(user, "bad.site")
1587 {:ok, user} = User.block_domain(user, "even.worse.site")
1591 |> assign(:user, user)
1592 |> get("/api/v1/domain_blocks")
1594 domain_blocks = json_response(conn, 200)
1596 assert "bad.site" in domain_blocks
1597 assert "even.worse.site" in domain_blocks
1600 test "unimplemented follow_requests, blocks, domain blocks" do
1601 user = insert(:user)
1603 ["blocks", "domain_blocks", "follow_requests"]
1604 |> Enum.each(fn endpoint ->
1607 |> assign(:user, user)
1608 |> get("/api/v1/#{endpoint}")
1610 assert [] = json_response(conn, 200)
1614 test "account search", %{conn: conn} do
1615 user = insert(:user)
1616 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1617 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1621 |> assign(:user, user)
1622 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1623 |> json_response(200)
1625 result_ids = for result <- results, do: result["acct"]
1627 assert user_two.nickname in result_ids
1628 assert user_three.nickname in result_ids
1632 |> assign(:user, user)
1633 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1634 |> json_response(200)
1636 result_ids = for result <- results, do: result["acct"]
1638 assert user_three.nickname in result_ids
1641 test "search", %{conn: conn} do
1642 user = insert(:user)
1643 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1644 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1646 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1649 CommonAPI.post(user, %{
1650 "status" => "This is about 2hu, but private",
1651 "visibility" => "private"
1654 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1658 |> get("/api/v1/search", %{"q" => "2hu"})
1660 assert results = json_response(conn, 200)
1662 [account | _] = results["accounts"]
1663 assert account["id"] == to_string(user_three.id)
1665 assert results["hashtags"] == []
1667 [status] = results["statuses"]
1668 assert status["id"] == to_string(activity.id)
1671 test "search fetches remote statuses", %{conn: conn} do
1675 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1677 assert results = json_response(conn, 200)
1679 [status] = results["statuses"]
1680 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1684 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1686 CommonAPI.post(insert(:user), %{
1687 "status" => "This is about 2hu, but private",
1688 "visibility" => "private"
1694 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1696 assert results = json_response(conn, 200)
1698 [] = results["statuses"]
1702 test "search fetches remote accounts", %{conn: conn} do
1705 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1707 assert results = json_response(conn, 200)
1708 [account] = results["accounts"]
1709 assert account["acct"] == "shp@social.heldscal.la"
1712 test "returns the favorites of a user", %{conn: conn} do
1713 user = insert(:user)
1714 other_user = insert(:user)
1716 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1717 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1719 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1723 |> assign(:user, user)
1724 |> get("/api/v1/favourites")
1726 assert [status] = json_response(first_conn, 200)
1727 assert status["id"] == to_string(activity.id)
1729 assert [{"link", _link_header}] =
1730 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1732 # Honours query params
1733 {:ok, second_activity} =
1734 CommonAPI.post(other_user, %{
1736 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1739 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1741 last_like = status["id"]
1745 |> assign(:user, user)
1746 |> get("/api/v1/favourites?since_id=#{last_like}")
1748 assert [second_status] = json_response(second_conn, 200)
1749 assert second_status["id"] == to_string(second_activity.id)
1753 |> assign(:user, user)
1754 |> get("/api/v1/favourites?limit=0")
1756 assert [] = json_response(third_conn, 200)
1759 describe "updating credentials" do
1760 test "updates the user's bio", %{conn: conn} do
1761 user = insert(:user)
1762 user2 = insert(:user)
1766 |> assign(:user, user)
1767 |> patch("/api/v1/accounts/update_credentials", %{
1768 "note" => "I drink #cofe with @#{user2.nickname}"
1771 assert user = json_response(conn, 200)
1773 assert user["note"] ==
1774 ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe" rel="tag">#cofe</a> with <span class="h-card"><a data-user=") <>
1776 ~s(" class="u-url mention" href=") <>
1777 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
1780 test "updates the user's locking status", %{conn: conn} do
1781 user = insert(:user)
1785 |> assign(:user, user)
1786 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1788 assert user = json_response(conn, 200)
1789 assert user["locked"] == true
1792 test "updates the user's name", %{conn: conn} do
1793 user = insert(:user)
1797 |> assign(:user, user)
1798 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1800 assert user = json_response(conn, 200)
1801 assert user["display_name"] == "markorepairs"
1804 test "updates the user's avatar", %{conn: conn} do
1805 user = insert(:user)
1807 new_avatar = %Plug.Upload{
1808 content_type: "image/jpg",
1809 path: Path.absname("test/fixtures/image.jpg"),
1810 filename: "an_image.jpg"
1815 |> assign(:user, user)
1816 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1818 assert user_response = json_response(conn, 200)
1819 assert user_response["avatar"] != User.avatar_url(user)
1822 test "updates the user's banner", %{conn: conn} do
1823 user = insert(:user)
1825 new_header = %Plug.Upload{
1826 content_type: "image/jpg",
1827 path: Path.absname("test/fixtures/image.jpg"),
1828 filename: "an_image.jpg"
1833 |> assign(:user, user)
1834 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1836 assert user_response = json_response(conn, 200)
1837 assert user_response["header"] != User.banner_url(user)
1840 test "requires 'write' permission", %{conn: conn} do
1841 token1 = insert(:oauth_token, scopes: ["read"])
1842 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1844 for token <- [token1, token2] do
1847 |> put_req_header("authorization", "Bearer #{token.token}")
1848 |> patch("/api/v1/accounts/update_credentials", %{})
1850 if token == token1 do
1851 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
1853 assert json_response(conn, 200)
1859 test "get instance information", %{conn: conn} do
1860 conn = get(conn, "/api/v1/instance")
1861 assert result = json_response(conn, 200)
1863 # Note: not checking for "max_toot_chars" since it's optional
1871 "streaming_api" => _
1876 "registrations" => _
1880 test "get instance stats", %{conn: conn} do
1881 user = insert(:user, %{local: true})
1883 user2 = insert(:user, %{local: true})
1884 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1886 insert(:user, %{local: false, nickname: "u@peer1.com"})
1887 insert(:user, %{local: false, nickname: "u@peer2.com"})
1889 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
1891 # Stats should count users with missing or nil `info.deactivated` value
1892 user = Repo.get(User, user.id)
1893 info_change = Changeset.change(user.info, %{deactivated: nil})
1897 |> Changeset.change()
1898 |> Changeset.put_embed(:info, info_change)
1899 |> User.update_and_set_cache()
1901 Pleroma.Stats.update_stats()
1903 conn = get(conn, "/api/v1/instance")
1905 assert result = json_response(conn, 200)
1907 stats = result["stats"]
1910 assert stats["user_count"] == 1
1911 assert stats["status_count"] == 1
1912 assert stats["domain_count"] == 2
1915 test "get peers", %{conn: conn} do
1916 insert(:user, %{local: false, nickname: "u@peer1.com"})
1917 insert(:user, %{local: false, nickname: "u@peer2.com"})
1919 Pleroma.Stats.update_stats()
1921 conn = get(conn, "/api/v1/instance/peers")
1923 assert result = json_response(conn, 200)
1925 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1928 test "put settings", %{conn: conn} do
1929 user = insert(:user)
1933 |> assign(:user, user)
1934 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1936 assert _result = json_response(conn, 200)
1938 user = User.get_cached_by_ap_id(user.ap_id)
1939 assert user.info.settings == %{"programming" => "socks"}
1942 describe "pinned statuses" do
1944 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1946 user = insert(:user)
1947 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1949 [user: user, activity: activity]
1952 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1953 {:ok, _} = CommonAPI.pin(activity.id, user)
1957 |> assign(:user, user)
1958 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1959 |> json_response(200)
1961 id_str = to_string(activity.id)
1963 assert [%{"id" => ^id_str, "pinned" => true}] = result
1966 test "pin status", %{conn: conn, user: user, activity: activity} do
1967 id_str = to_string(activity.id)
1969 assert %{"id" => ^id_str, "pinned" => true} =
1971 |> assign(:user, user)
1972 |> post("/api/v1/statuses/#{activity.id}/pin")
1973 |> json_response(200)
1975 assert [%{"id" => ^id_str, "pinned" => true}] =
1977 |> assign(:user, user)
1978 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1979 |> json_response(200)
1982 test "unpin status", %{conn: conn, user: user, activity: activity} do
1983 {:ok, _} = CommonAPI.pin(activity.id, user)
1985 id_str = to_string(activity.id)
1986 user = refresh_record(user)
1988 assert %{"id" => ^id_str, "pinned" => false} =
1990 |> assign(:user, user)
1991 |> post("/api/v1/statuses/#{activity.id}/unpin")
1992 |> json_response(200)
1996 |> assign(:user, user)
1997 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1998 |> json_response(200)
2001 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2002 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2004 id_str_one = to_string(activity_one.id)
2006 assert %{"id" => ^id_str_one, "pinned" => true} =
2008 |> assign(:user, user)
2009 |> post("/api/v1/statuses/#{id_str_one}/pin")
2010 |> json_response(200)
2012 user = refresh_record(user)
2014 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2016 |> assign(:user, user)
2017 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2018 |> json_response(400)
2021 test "Status rich-media Card", %{conn: conn, user: user} do
2022 Pleroma.Config.put([:rich_media, :enabled], true)
2023 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2027 |> get("/api/v1/statuses/#{activity.id}/card")
2028 |> json_response(200)
2030 assert response == %{
2031 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2032 "provider_name" => "www.imdb.com",
2033 "provider_url" => "http://www.imdb.com",
2034 "title" => "The Rock",
2036 "url" => "http://www.imdb.com/title/tt0117500/",
2037 "description" => nil,
2040 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2041 "title" => "The Rock",
2042 "type" => "video.movie",
2043 "url" => "http://www.imdb.com/title/tt0117500/"
2048 # works with private posts
2050 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2054 |> assign(:user, user)
2055 |> get("/api/v1/statuses/#{activity.id}/card")
2056 |> json_response(200)
2058 assert response_two == response
2060 Pleroma.Config.put([:rich_media, :enabled], false)
2065 user = insert(:user)
2066 for_user = insert(:user)
2069 CommonAPI.post(user, %{
2070 "status" => "heweoo?"
2074 CommonAPI.post(user, %{
2075 "status" => "heweoo!"
2080 |> assign(:user, for_user)
2081 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2083 assert json_response(response1, 200)["bookmarked"] == true
2087 |> assign(:user, for_user)
2088 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2090 assert json_response(response2, 200)["bookmarked"] == true
2094 |> assign(:user, for_user)
2095 |> get("/api/v1/bookmarks")
2097 assert [json_response(response2, 200), json_response(response1, 200)] ==
2098 json_response(bookmarks, 200)
2102 |> assign(:user, for_user)
2103 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2105 assert json_response(response1, 200)["bookmarked"] == false
2109 |> assign(:user, for_user)
2110 |> get("/api/v1/bookmarks")
2112 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2115 describe "conversation muting" do
2117 user = insert(:user)
2118 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2120 [user: user, activity: activity]
2123 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2124 id_str = to_string(activity.id)
2126 assert %{"id" => ^id_str, "muted" => true} =
2128 |> assign(:user, user)
2129 |> post("/api/v1/statuses/#{activity.id}/mute")
2130 |> json_response(200)
2133 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2134 {:ok, _} = CommonAPI.add_mute(user, activity)
2136 id_str = to_string(activity.id)
2137 user = refresh_record(user)
2139 assert %{"id" => ^id_str, "muted" => false} =
2141 |> assign(:user, user)
2142 |> post("/api/v1/statuses/#{activity.id}/unmute")
2143 |> json_response(200)
2147 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2148 user = insert(:user)
2152 |> assign(:user, user)
2153 |> get("/api/v1/pleroma/flavour")
2155 assert "glitch" == json_response(get_old_flavour, 200)
2159 |> assign(:user, user)
2160 |> post("/api/v1/pleroma/flavour/vanilla")
2162 assert "vanilla" == json_response(set_flavour, 200)
2166 |> assign(:user, user)
2167 |> post("/api/v1/pleroma/flavour/vanilla")
2169 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2172 describe "reports" do
2174 reporter = insert(:user)
2175 target_user = insert(:user)
2177 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2179 [reporter: reporter, target_user: target_user, activity: activity]
2182 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2183 assert %{"action_taken" => false, "id" => _} =
2185 |> assign(:user, reporter)
2186 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2187 |> json_response(200)
2190 test "submit a report with statuses and comment", %{
2193 target_user: target_user,
2196 assert %{"action_taken" => false, "id" => _} =
2198 |> assign(:user, reporter)
2199 |> post("/api/v1/reports", %{
2200 "account_id" => target_user.id,
2201 "status_ids" => [activity.id],
2202 "comment" => "bad status!"
2204 |> json_response(200)
2207 test "account_id is required", %{
2212 assert %{"error" => "Valid `account_id` required"} =
2214 |> assign(:user, reporter)
2215 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2216 |> json_response(400)
2219 test "comment must be up to the size specified in the config", %{
2222 target_user: target_user
2224 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2225 comment = String.pad_trailing("a", max_size + 1, "a")
2227 error = %{"error" => "Comment must be up to #{max_size} characters"}
2231 |> assign(:user, reporter)
2232 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2233 |> json_response(400)
2237 describe "link headers" do
2238 test "preserves parameters in link headers", %{conn: conn} do
2239 user = insert(:user)
2240 other_user = insert(:user)
2243 CommonAPI.post(other_user, %{
2244 "status" => "hi @#{user.nickname}",
2245 "visibility" => "public"
2249 CommonAPI.post(other_user, %{
2250 "status" => "hi @#{user.nickname}",
2251 "visibility" => "public"
2254 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2255 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2259 |> assign(:user, user)
2260 |> get("/api/v1/notifications", %{media_only: true})
2262 assert [link_header] = get_resp_header(conn, "link")
2263 assert link_header =~ ~r/media_only=true/
2264 assert link_header =~ ~r/since_id=#{notification2.id}/
2265 assert link_header =~ ~r/max_id=#{notification1.id}/